I'm using CakePHP 2.
This is my controller.
class GroupsController extends AppController {
public $helper = array('Html', 'Form', 'Session');
public function edit($id = null) {
if (empty($this->request->data)) {
$this->request->data = $this->Group->findByGroupId($id);
} else {
if($this->Group->save($this->request->data)) {
$this->Session.setFlash('Saved!!!');
$this->redirect(array('action' => 'index'));
}
}
}
}
When I pressed the save button on the page groups/edit/1, I got an error.
"Error: Call to undefined function setFlash()"
Fortunately, the changes I made were save to the database, I really don't get it, because setFlash() is a method of SessionComponent.
Please help, thanks.
Kongthap.
try this ::
$this->Session->setFlash('Saved!!!');
Related
I have a validator that checks if a vat-number is correct. In order to do that it calls an external service. This external call slows the tests down and is unreliable, so I would like to mock it, but I don't understand how I could do it.
public function validationDefault(Validator $validator)
{
$validator->setProvider('vat', 'App\Model\Validation\VatValidation');
$validator->add('vat_no', 'isValidVatNo', [
'rule' => 'validVatNumber',
'provider' => 'vat',
]);
}
And this is the validation provider:
<?php
namespace App\Model\Validation;
use Cake\Core\Configure;
use Cake\Validation\Validation;
use VatNumberCheck\Utility\Model\VatNumberCheck;
class VatValidation extends Validation
{
public static function validVatNumber($check)
{
$vatNumberCheck = new VatNumberCheck();
try {
return $vatNumberCheck->check($check);
} catch (InternalErrorException $e) {
return false;
}
}
}
public function testValidationFail() {
$VatValidator = $this->getMockBuilder('Cake\Validation\Validator')
->setMethods(['validVatNumber'])
->getMock();
$VatValidator->expects($this->any())
->method('validVatNumber')
->will($this->returnValue(false));
$this->Users->getValidator()->setProvider('vat', $VatValidator);
$user = $this->Users->newEntity([
'vat_no' => 'asdf',
]);
$errors = $user->errors();
$this->assertArrayHasKey('vat_no', $errors);
}
Whenever I call this function, I get the user_id correctly but the password isnt checked...
Model:
<?php
class Prometheus_model extends CI_Model {
var $tables = array(
'bots' => 'bots',
'users' => 'users'
);
function __construct() {
parent::__construct();
}
public function tablename($table = NULL) {
if(! isset($table)) return FALSE;
return $this->tables[$table];
}
public function get($table, $where = array(), $order = NULL) {
$this->db->where($where);
if(isset($order)) {
$this->db->order_by($order);
}
$q = $this->db->get_where($this->tablename($table),$where);
$result = $q->result_array();
// You should use $q->num_rows() to detect the number of returned rows
if($q->num_rows()) {
return $result[0];
}
return $result;
}
public function update($table, $where = array(), $data) {
$this->db->update($this->tablename($table),$data,$where);
return $this->db->affected_rows();
}
public function insert($table, $data) {
$this->db->insert($this->tablename($table),$data);
return $this->db->insert_id();
}
public function delete($table, $where = array()) {
$this->db->delete($this->tablename($table),$where);
return $this->db->affected_rows();
}
public function explicit($query) {
$q = $this->db->query($query);
if(is_object($q)) {
return $q->result_array();
} else {
return $q;
}
}
public function num_rows($table, $where = NULL) {
if(isset($where)){
$this->db->where($where);
}
$q = $this->db->get($table);
return $q->num_rows();
}
public function get_bot_data_by_hw_id($bot_hw_id) {
$q = $this->get('bots', array('bot_hw_id' => $bot_hw_id));
return $q;
}
public function check_user_data($user_incredials, $user_password) {
if($this->num_rows('users', array('user_name' => $user_incredials, 'user_password' => $this->encrypt->decode($user_password))) == 1){
$q = $this->get('users', array('user_name' => $this->security->xss_clean($user_incredials)));
return $q['user_id'];
}
return FALSE;
}
}
?>
My function-calling at the controller:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Login extends CI_Controller {
public function index(){
if($this->input->post('user_login')){
var_dump($this->prometheus_model->check_user_data($this->input->post('user_incredials'), $this->input->post('user_password')));
}
$this->load->view('login_index');
}
}
How can i fixx this ?
In your check_user_data() method you are using
if($this->num_rows('users', array('user_name' => $user_incredials, 'user_password' => $this->encrypt->decode($user_password))) == 1)
I think (logically) following code
$this->encrypt->decode($user_password)
should be
$this->encrypt->encode($user_password)
because, you are calling num_rows() method and it is
public function num_rows($table, $where = NULL)
{
if(isset($where)){
$this->db->where($where);
}
$q = $this->db->get($table);
return $q->num_rows();
}
which is actually querying the data base something like, for example,
select * from USERS where user_name = 'heera' and password = decode('abcde12345')
In this case, the password you are trying to match is need to be encrypted using encode (not decode) method, because the user has given you a non-encrypted (plain) password and the password saved in the database is already encrypted, so encode the plain password using encode method before you query the database to match with already encoded passwords.
It has come to my attention that the redirect controller method is not working part of the time. No message appears when I set debug > 0. I don't echo any code before calling the redirect method so it shouldn't be because of "headers already sent".
Let's take a look at my ArticlesController add action where redirect works in one instance but not in another.
public function add($page = null) {
// Custom component to get if user has required access level
// of page to write an article. If not, setflash to an error message
// specific to user's access level and redirect.
$access_message = $this->CustomPage->AccessMessage(4, $this->viewVars['access']);
if($access_message){
// Flash works but redirect does not
$this->Session->setFlash(__($access_message));
$this->redirect(array('action' => 'index', 'page' => $page));
// Also tried
// $this->redirect(array('controller'=>'articles', 'action' => 'index', 'page' => $page), null, true);
} else
{
if ($this->request->is('post')) {
$this->Article->create();
if ($this->Article->save($this->request->data)) {
// BLAH BLAH save post, do other stuff
// BLAH BLAH save post, do other stuff
// This flash and redirect works
$this->Session->setFlash(__('The article has been saved'));
$this->redirect(array('action' => 'view', 'id' => $article_id, 'page' => $page));
} else {
$this->Session->setFlash(__('The article could not be saved. Please, try again.'));
} // end else if article cannot be saved
} // if method is post
} // end if user has access
} // end add action
It definitely has something to do with the component but I'm not sure what. Maybe since redirect is called right after the component is used, the "$this" is trying to do the redirect method on the component instead of the controller. I tried $this->Article->redirect and reloading the Article model before the redirect but neither of those worked.
My component code is:
public function AccessMessage($required_level, $user_level) {
if(!$user_level && $this->_View->viewVars['access']){
$user_level = $this->_View->viewVars['access'];
}
if(!$required_level || !$user_level || $user_level != $required_level){
$accessModel = ClassRegistry::init('Access');
$access_message = $accessModel->field('access_message', array('Access.id' => $required_level));
}
return $access_message;
}
Edit 1: Ok so I did some digging to find exactly where the problem is stemming from. The USE of the component is not the problem which I thought it was before. If all I have in my component is
public function AccessMessage($required_level, $user_level) {
if(!$user_level && $this->_View->viewVars['access']){
$user_level = $this->_View->viewVars['access'];
}
if(!$required_level || !$user_level || $user_level != $required_level){
$access_message = 1;
}
return $access_message;
}
Then it works. The issue is with these two lines which are correctly implemented because they return the value for $access_message I am expecting, but they are interfering with the ability to redirect. Perhaps headers are already sent out?
$accessModel = ClassRegistry::init('Access');
$access_message = $accessModel->field('access_message', array('Access.id' => $required_level));
Please note I have also tried:
$access_message = ClassRegistry::init('Access')->field('access_message', array('Access.id' => $required_level));
And
$this->loadModel('Access');
$access_message = $this->Access->field('access_message', array('Access.id' => $required_level));
Gists:
component gist: https://gist.github.com/970a951715205c222348
controller gist: https://gist.github.com/2b90e5af2518a81672fb
access model gist: https://gist.github.com/bhndbrwneyes/f333a93f0a21302d832f
You may have space before/after php Opening/Closing tags in controller and models. Remove all the closing tags from all controllers and models and any whitespace before opening tags. Then check the result.
Not an answer yet, but at least there are some variables in your code that may not be defined, or errors that can occur:
public function AccessMessage($required_level, $user_level) {
if(!$user_level && $this->_View->viewVars['access']){
$user_level = $this->_View->viewVars['access'];
}
if(!$required_level || !$user_level || $user_level != $required_level){
$access_message = 1;
}
return $access_message;
}
Variable $access_message will only be defined if a user is not allowed to access the page
An error may occur if the 'access' viewVar is not set at all
Change it to this:
public function AccessMessage($required_level, $user_level) {
$access_message = 0;
if(!$user_level && $this->_View->get('access')){
$user_level = $this->_View->get('access');
}
if(!$required_level || !$user_level || $user_level != $required_level){
$access_message = 1;
}
return $access_message;
}
[updated] saw you did have the $access_message defined on your gist (https://gist.github.com/970a951715205c222348)
However:
This will not work
App::uses('Component', 'Controller', 'ClassRegistry', 'Utility');
App::uses() takes two arguments; the 'class' you would like to use and the location it can be found. The line above should be written as:
App::uses('Component', 'Controller/Component');
App::uses('Controller', 'Controller');
App::uses('ClassRegistry', 'Utility');
But I wonder if ClassRegistry needs to be loaded manually
[update 2] You really have a lot 'weird' things going on in your application, so I wonder if we'll be able to sort that out:
public function add($page = null) {
$access = $this->viewVars['access'];
if($this->CustomPage->AccessMessage(4, $access)){
$this->Session->setFlash(__($this->CustomPage->AccessMessage(4, $access)));
$this->redirect(array('action' => 'index', 'page' => $page));
}
// ......
}
Where is 'viewVars['access']' set?
You're passing 'viewVars['access']' as the second parameter ($user_level) to AccessMessage(), but inside AccessMessage() you're trying to use the same viewVar again if the parameter '$user_level' was not set?
$this->CustomPage->AccessMessage() is called twice once to check if it returned anything, then to use it. Not very efficient
.
public function add($page = null) {
// Where does is $this->viewVars['access'] come from? Where is it set?
$access = empty($this->viewVars['access'])? null : $this->viewVars['access'];
$message = $this->CustomPage->AccessMessage(4, $access);
if ($message) {
$this->Session->setFlash(__($message));
$this->redirect(array('action' => 'index', 'page' => $page));
}
// ......
}
On a further note. you're redirecting the user only if a 'message' was found and not empty, NOT based on the current users permissions, you might consider splitting the two;
In your component:
public function HasAccessLevel($required_level, $user_level) {
if(!$user_level || $user_level != $required_level){
return false;
}
return true;
}
public function AccessMessage($required_level) {
return ClassRegistry::init('Access')->field('access_message', array('Access.id' => $required_level));
}
In your controller:
public function add($page = null) {
// Where does is $this->viewVars['access'] come from? Where is it set?
$access = empty($this->viewVars['access'])? null : $this->viewVars['access'];
if($this->CustomPage->HasAccessLevel(4, $access)){
$this->Session->setFlash(__($this->CustomPage->AccessMessage(4)));
$this->redirect(array('action' => 'index', 'page' => $page));
}
// ......
}
Cake 2: At the top of the component: add
public function initialize(Controller $controller) {
$this->Controller = $controller;
}
inside the function you can redirect like so:
$this->Controller->redirect(array('plugin' => false, 'controller' => 'users', 'action' => 'index'));
If the redirect is called, but you are not redirected I guess you have some permission check in your index() action that prevents the access. Can you confirm or post the whole controller code?
In my controller i have 2 actions e.g
action1() {
//code
SomeArray=();
//code
}
How can i pass all the SomeArray data to action2?
I have tried to create a public array variable in my class and pass it but with no luck.
i have tried to pass as an argument to the action2...
e.g in action1, $this->action2(SomeArray) and then action2($param) with no luck again.
function doExam($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid exam', true));
$this->redirect(array('action' => 'index'));
}
$this->Exam->recursive=1;
$conditions_question = array('Question.exam_id' => $id);
$questions = $this->Exam->Question->find('all',array('conditions' => $conditions_question));
foreach ($questions as $question) {
**$this->questionsByExam[]** = $question['Question']['qst'];
}
//OK PASSED
echo debug($this->questionsByExam);
//OK $exam_id
$this->exam_id = $id;
}
i have another action validate_answer, and i want to pass the questionsByExam in here
any help?
Thanks in advance
I have tried to create a public array variable in my class and pass it but with no luck.
Can you show the code for this? It should work fine as class variable...
E.g:
class FooController extends AppController {
var $someArray = array();
function doExam() {
// Populate the array here
$this->someArray = array(1,2,3);
}
function bar() {
// Use it here, no need to pass it as an argument
print_r($this->someArray);
}
}
when i submit login
I got
Error: LoginsController could not be found.
this Appcontroller
class AppController extends Controller {
var $helpers = array('Html','Form','Ajax','Javascript','Session');
var $components = array('Auth','Session');
function beforeFilter() {
//parent::beforeFilter();
$this->Auth->userModel = 'Member';
$this->Auth->allow('*');
$this->Auth->authError='Please Login for view this page';
$this->Auth->loginError = 'Username or Password does not match';
$this->Auth->loginRedirect = array('Controller'=>'Members','action'=>'dashboard');
$this->Auth->logoutRedirect = array('Controller'=>'Members','action'=>'index');
($this->set('admin',$this->isadmin()));
($this->set('logged_in',$this->logged_in()));
( $this->set('userUsername',$this->userUsername()));
}
function isadmin(){
$admin = FALSE;
if($this->Auth->user('priority') == 'admin')
{
$admin = TRUE;
}
return $admin;
}
function logged_in(){
$logged_in = FALSE;
if ($this->Auth->user())
{
$logged_in = TRUE;
}
return $logged_in;
}
function userUsername(){
$userUsername = NULL;
if($this->Auth->user())
{
$userUsername = $this->Auth->Member('username');
}
return $userUsername;
}
}
I try to search in stackoverflow but I can't found thank for answer
What is happening is that you need to create a LoginsController that extends the AppController and in that controller you will handle the logic for the login. When you go to the url /login, it will automatically look for that controller unless you create a route specifying otherwise.