Static Variable/Methods in PHP using CakePHP - php

I'm saving the ID of the conected user in a static variable at MainController, but I need to access this variable in others controllers. When I try to get the value from the variable, the result is always the initial value of the variable, even when I have already modified it.
class MainController extends AppController {
//...
public static $loggedClienteId;
//functions
public function loginCliente(){
//code...
self::$loggedClienteId = $cliente['Cliente']['id'];
var_dump(MainController::$loggedClienteId); //returns the correct value.
return $this->redirect(array('controller' => 'clientes', 'action' => 'index'));
}
}
So, in another controller...
include "MainController.php";
class ClientesController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
var_dump(MainController::$loggedClienteId); //null, althought it already has a value...
$this->set('clientes', $this->Cliente->find('all'));
}
//functions...
}
Why is that happening?

Use $this->Auth->user('id') to get the current logged in user's id.
The reason your code does not work is because once the request for the login action is completed, the script is over. Setting a variable does not persist across requests. You have to save variables in the session for that.
If it's not the logged in user's id you need, what you have to do is use the SessionComponent and use $this->Session->write('key', 'value'); and to read it in another request/controller $this->Session->read('key');.

Related

How to access one controller action inside another controller action?

I am using cakephp-2.x. I have one function name user_info() in the UsersController.php i want to access this in another controller name MessagesController.php
Code -
UsersController.php
public function user_info(){
$user_id=$this->Session->read('Auth.User.id');
$data=$this->User->findById($user_id);
$this->set('user_info',$data);
}
MessagesController.php
public function index(){
//$userInfo=new UsersController();
//$userInfo->user_info();
$this->user_info();
pr($data);
}
Error Message-
Fatal Error
Error: Call to undefined method MessagesController::user_info()
File: E:\xampp\htdocs\2014\myshowcam\msc\app\Controller\MessagesController.php
Line: 18
Notice: If you want to customize this error message, create app\View\Errors\fatal_error.ctp
Typically if you're trying to access a function in one controller from another controller you have a fundamental flaw in your project's logic.
But in general object usage is thus:
$otherController = new whateverMyControllerNameIs();
$otherController->functionName();
However I'm not familiar enough with cake to tell you the pitfalls of doing such a thing. For example I have no idea what this would do to routes or what other variables/objects are required to initialize a controller correctly.
EDIT:
Ref: CakePHP 2.3.8: Calling Another Controller function in CronController.php
App::import('Controller', 'Products'); // mention at top
// Instantiation // mention within cron function
$Products = new ProductsController;
// Call a method from
$Products->ControllerFunction();
Try requestAction function of cakephp
$result = $this->requestAction(array('controller' => 'users', 'action' => 'user_info'));
Why would a simple, When can complicated?
All the information for a registered user of User model is accessible in the following manner:
AppController.php
public $user_info; /* global scope */
public function beforeFilter(){
$this->user_info = $this->Auth->user(); // for access user data in any controller
$this->set('user_info_view',$this->Auth->user()); // for access user data in any view or layout
}
MessagesController.php
public function index(){
debug($this->user_info);
$my_messages = $this->Message->find('all',
array('conditions' => array('Message.user_id' => $this->user_info['id']))
}
....
layout or view.ctp
<?php echo $user_info_view['name']; ?> // email, etc
Why not take advantage of the way CakePHP handles relationships? There's a very easy way to achieve what you're trying to do without extending controllers or loading in additional controllers which seems excessive for your example.
Inside AppController's beforeFilter()
Configure::write('UserId', $this->Session->read('Auth.User.id'));
This will allow you to access the UserID from your models
Inside your User's model, create the following function
/**
* Sample query which can be expanded upon, adding fields or contains.
*
* #return array The user data if found
*/
public function findByUserId() {
$user = $this->find('first', array(
'conditions' => array(
'User.id' => Configure::read('UserId')
)
));
return $user;
}
Inside your Users controller (Minimal is better, no?)
public function user_info() {
$this->set('user', $this->User->findByUserId());
}
Inside your Messages controller
public function index() {
$this->set('user', $this->Message->User->findByUserId());
// --- Some more stuff here ---
}
And that's it, no need to be extending controllers, just make sure your Message and User model are related to each other, failing that you can bindModel or use ClassRegistry::init('User')-> for example.

CakePhp Error: Call to a member function create() on a non-object

I am currently learning how to use CakePhp.
I have created a function in my custom controller as follows:
class FormatsController extends AppController
{
// ....
function admin_add()
{
// if the form data is not empty
if (!empty($this->data)) {
// initialise the format model
$this->Format->create();
// create the slug
$this->data['Format']['slug'] = $this->slug($this->data['Format']['name']);
// try saving the format
if ($this->Format->save($this->data)) {
// set a flash message
$this->Session->setFlash('The Format has been saved', 'flash_good');
// redirect
$this->redirect(array('action' => 'index'));
} else {
// set a flash message
$this->Session->setFlash('The Format could not be saved. Please, try again.', 'flash_bad');
}
}
}
}
However in my view I am getting this error:
Error: Call to a member function create() on a non-object
Why is this error caused and how can I fix it?
My apologies, I believe the line it is referencing is not in the Controller but in my view itself. It refers to my view which has the following line:
<?php echo $form->create('Format');?>
Is there something else I need to declare before using this? i.e. $this->Format->create();
you should be using:
$this->Form->create('Format');
delete the
<?php echo $form->create('Format');?>
and replace it with
<?php echo $this->Form->create('Format');?>
$form is the one that causes the error.
Need to define the global name of the model. So, to access it anywhere in application.
For example: my model is User
class User extends AppModel {
var $name = 'User';
function myfunction ($id) {
.....
}
}
To use in controller
Controller:
class UsersController extends AppController
{
function test()
{
$this->User->myfunction();
......
}
}
I hope this will help you!
This is probably being caused because for some reason $this->Format isn't being created. If you look in your code snippet you see it calling the create() function. Add this as a debug statement in your controller function before you call create() to see if it is even set.
debug( isset( $this->Format ) );
If it is set should output true. If you try this let me know what it says I might have some other suggestions to go from there.
Have you created the model "Format"?
This kind of errors arise when the called model has a problem. Either it is not created, or it is not properly created or it is not imported/ initiated properly.
If you declared $uses variable in your controller, make sure you include "Format" in your $uses array along the other models.
Try this one into your action
$this->loadModel('Format');
$this->Format
is undefined (so it's value is null), a null object has no functions, therefor you can't use
$this->Format->create();
It's pretty much equal to
null->create();
Try
$this->Form->create(null,['url' => ['controller' => 'yourController', 'action' => 'yourAction']])

CodeIgniter: Update public variable in MY_Controller from model

I am working on a project with CodeIgniter. I extended CI's base Controller class with a custom MY_Controller. MY_Controller has a authentication flag variable $auth = FALSE. On pages that require authentication, I call my auth_model->runAuth() function to run checks and this flag should be updated to TRUE if all checks pass. For some reason I can't update my $auth variable in MY_Controller directly from the auth_model with $this->auth = TRUE, but I have to pass the check result back to the page controller first and then update the $auth variable in MY_Controller. Any ideas how to update the $auth flag in MY_Controller directly from the model without going through a controller? Thank you very much in advance!
Your best bet would be to assign the flag directly via the method call like this
$this->auth = $this->auth_model->runAuth();
In the MY_Controller class! The method runAuth() does not need a big change:
Instead of calling $auth = TRUE or FALSE, just return true or false like this:
public function runAuth()
{
// do stuff
return true; // or false depending on success.
}
Hope that helps. Otherwise you would need a refernce to the MY_Controller object somehow. For Example:
$this->auth_model->runAuth($this);
Now in your method:
public function runAuth(MY_Controller $myctrl)
{
// do stuff
$myctrl->auth = true; // or false
}
Another option would be to use static fields:
class MY_Controller extends Controller
{
public static $auth = false;
// the other stuff
}
Now you can update this without an object refernce:
public function runAuth()
{
// do stuff
MY_Controller::$auth = true;
}
In your models you can access it like this:
if (static::$auth) echo "Boo Yeah!";

CakePHP - BaseAuthenticate altering loginRedirect

I have a number of authentication components that extend the BaseAuthenticate class. These are setup in the AppController in the normal way.
Is it possible for an authentication component to alter the AuthComponent's loginRedirect variable?
To clarify the situation, one of my authentication components looks at a certain subset of users. It checks to see if the credentials are valid before checking to see if that person has any outstanding invoices. Depending on the outstanding value, I'd like to redirect the user to a given page or block them out altogether.
Thanks
Yes it's possible. The AuthComponent's redirect location is just a session variable (so technically it can be set anywhere).
To change the redirect location, you can set it manually:
$this->Session->write('Auth.redirect', 'http://example.com');
On the next request, they will be redirected by the AuthComponent.
Or, have your component redirect them then and there:
$this->_Collection->getController()->redirect('http://example.com');
A big thanks to #jerermyharris for pushing me in the right direction. Here goes with what I ended up doing.
1. Extended the AuthComponent
App::uses('AuthComponent', 'Controller/Component');
class MyAuthComponent extends AuthComponent {
var $components = array('Session');
public function identify(CakeRequest $request, CakeResponse $response) {
if (empty($this->_authenticateObjects)) {
$this->constructAuthenticate();
}
foreach ($this->_authenticateObjects as $auth) {
$result = $auth->authenticate($request, $response);
if (!empty($result) && is_array($result)) {
if(isset($result['Redirect']))
{
$this->Session->write('Auth.redirect', $result['Redirect']);
}
return $result;
}
}
return false;
}
}
2. Add this the AppController components
public $components = array(
'Auth' => array(
'className' => 'MyAuth',
)
);
Add this bit around whatever other definitions you have for your AuthComponent.
3. Return a redirect from your authentication component
App::uses('BaseAuthenticate', 'Controller/Component/Auth');
class TutorAuthenticate extends BaseAuthenticate {
public function authenticate(CakeRequest $request, CakeResponse $response) {
$user = ...... // However you authenticate your user
$user['Redirect'] = "http://example.com";
return $user;
}
}
So now if you want to redirect based on the user you can just add it in, if you don't then cake will obey the directives you set up in AppController.
Wow, that seems like I've had to do loads extra, but it's the right thing to do.

CakePHP: how to check a session before each action?

I have two things I need to do in Cake 2.2. I need to check that someone is logged in on every page, and then I need to store their user ID as a constant named UID.
I want to avoid being on each controller and having to check the user. I want it done automatically, so naturally I go to AppController and try BeforeFilter. It doesn't seem to have initialized the session, so I scratch that and try afterFilter, but that (and BeforeRender) is really not what I want to do; I don't want a single thing that I can stop from happening, to happen on page request if they're not logged in. Bootstrapping was also not the answer, as far as I could tell.
So how can I check if a user's logged in, and at the same time define a constant for the rest of my application?
You can do the same by invoking a user session check method in beforeFilter() method in AppController. Your code should looks like:
<?php
App::uses('Sanitize', 'Utility');
App::uses('Controller', 'Controller');
class AppController extends Controller
{
public $components = array(
'Session',
'RequestHandler'
);
public $helpers = array('Html', 'Form', 'Session', 'Js' => array('Jquery'), 'Text');
public $uses = array('User');
public function beforeFilter()
{
if($this->Session->check('User.id'))
{
$this->set('logged_in', true);
$this->set('username', trim($this->Session->read('User.first_name'). ' '. $this->Session->read('User.last_name')));
}
else
{
$this->set('logged_in', false);
}
}
/*.......... Rest of your code ..............*/
}
Kindly ask if it not worked for you.

Categories