CakePHP: get user info in models
Asked Answered
T

10

12

I'm moving some of my find code inside models.

Previously in my controller I had

$this->Book->Review->find('first', array(
    'conditions' => array(
        'Review.book_id' => $id,
        'Review.user_id' => $this->Auth->user('id')
    )
));

so in my Review model I put something like

function own($id) {
    $this->contain();
    $review = $this->find('first', array(
        'conditions' => array(
            'Review.book_id' => $id,
            'Review.user_id' => AuthComponent::user('id')
        )
    ));
    return $review;
}

So I'm calling AuthComponent statically from the Model. I know I can do this for the method AuthComponent::password(), which is useful for validation. But I'm getting errors using the method AuthComponent::user(), in particular

Fatal error: Call to a member function check() on a non-object in /var/www/MathOnline/cake/libs/controller/components/auth.php on line 663

Is there a way to get the info about the currently logged user from a model?

Tyson answered 27/1, 2010 at 20:24 Comment(0)
M
3

There is a nice solution by Matt Curry. You store the data of the current logged user in the app_controller using the beforeFilter callback and access it later using static calls. A description can be found here: http://www.pseudocoder.com/archives/2008/10/06/accessing-user-sessions-from-models-or-anywhere-in-cakephp-revealed/


EDIT: the above link is outdated: https://github.com/mcurry/cakephp_static_user

Mimosa answered 27/1, 2010 at 23:9 Comment(1)
Thank you, this seems the best solution!Tyson
S
13

Create a new function in the "app_model.php" ("AppModel.php" in CakePHP 2.x), so it will be available at all models within our application:

function getCurrentUser() {
  // for CakePHP 1.x:
  App::import('Component','Session');
  $Session = new SessionComponent();

  // for CakePHP 2.x:
  App::uses('CakeSession', 'Model/Datasource');
  $Session = new CakeSession();


  $user = $Session->read('Auth.User');

  return $user;
}

in the model:

$user = $this->getCurrentUser();
$user_id = $user['id'];
$username = $user['username'];
Salto answered 12/4, 2011 at 11:43 Comment(0)
K
11

The way that I use is this:

App::import('component', 'CakeSession');        
$thisUserID = CakeSession::read('Auth.User.id');

It seems to work quite nicely :-)

Kozak answered 20/3, 2011 at 5:27 Comment(0)
Q
6

I think the code is fine as it is and belongs in the Controller, or at the very least it needs to receive the ids from the Controller and not try to get them itself. The Model should only be concerned with fetching data from a data store and returning it. It must not be concerned with how the data is handled in the rest of the application or where the parameters to its request are coming from. Otherwise you paint yourself into a corner where the ReviewModel can only retrieve data for logged in users, which might not always be what you want.

As such, I'd use a function signature like this:

function findByBookAndUserId($book_id, $user_id) {
    …
}

$this->Review->findByBookAndUserId($id, $this->Auth->user('id'));
Quartus answered 27/1, 2010 at 23:14 Comment(3)
I have many request that only fetch data linked to the current user. Just trying to simplify the code without having to pass the user id everywhere.Tyson
Just to add a few examples, by having your model method expect a controller (with session data), you can no longer easily use that model method in shells or test cases (in which there is no controller or session).Wanyen
@deizel Good point, too. This move can create unnecessary dependencies just for the sake of saving ~20 characters of code...Quartus
M
3

There is a nice solution by Matt Curry. You store the data of the current logged user in the app_controller using the beforeFilter callback and access it later using static calls. A description can be found here: http://www.pseudocoder.com/archives/2008/10/06/accessing-user-sessions-from-models-or-anywhere-in-cakephp-revealed/


EDIT: the above link is outdated: https://github.com/mcurry/cakephp_static_user

Mimosa answered 27/1, 2010 at 23:9 Comment(1)
Thank you, this seems the best solution!Tyson
E
2

I think this is not good idea to get value from Session. Better solution to get logged user id inside any model simply try this:

AuthComponent::user('id');

This will work almost every where. View, Model and Controller

Enterprising answered 26/6, 2014 at 10:35 Comment(0)
R
1

Dirtiest way would be to just access the user information in the Session. Least amount of overhead associated with that.

The "proper" way would probably be to instantiate the AuthComponent object, so that it does all the stuff it needs to be fully operational. Much like a death star, the AuthComponent doesn't really work well when not fully setup.

To get a new AC object, in the model:

App::import( 'Component', 'Auth' );
$this->Auth = new AuthComponent();

Now you can use $this->Auth in the model, same as you would in the controller.

Rosetta answered 27/1, 2010 at 21:32 Comment(5)
Notice (8): Undefined property: AuthComponent::$Session [CORE/cake/libs/controller/components/auth.php, line 663] Fatal error: Call to a member function check() on a non-object in /var/www/MathOnline/cake/libs/controller/components/auth.php on line 663Tyson
Instantiating models yourself, especially Controllers or Components, is tricky business. Better use ClassRegistry::getInstance() or ClassRegistry::init() (off the top of my head).Quartus
@Quartus would you recommend using those functions (instead) always rather than App::import? I've used App::import for models inside AppController quite a few times, never had any probs. But I'm willing to change if you think it's a better way of doing it -- do you recommend it?Rosetta
The thing is, App::import() just imports the .php file which contains the Class, it doesn't instantiate anything. Some Classes depend on certain arguments to their constructor, Components for example expect a reference to a Controller. The best way to construct classes correctly is to just get an already existing instance from the ClassRegistry (saves memory, too). Otherwise, leave it to the ClassRegistry to instantiate the Class (not sure if it does it for Components that easily).Quartus
In CakePHP 2.2. the syntax is: App::uses('AuthComponent', 'Controller/Component'); $this->Auth = new AuthComponent();Chesnut
P
1

For CakePHP 3.x this easy component is available: http://cakemanager.org/docs/utils/1.0/components/globalauth/. Direct accessing the Session is not possible because of different SessionKeys.

With the GlobalAuthComponent you can access your user-data everywhere with: Configure::read('GlobalAuth');.

Greetz

Bob

Pinero answered 12/6, 2015 at 22:55 Comment(0)
R
0

I use cake 2.2 and these both work great:

$this->Session->read('Auth.User');
//or
$this->Auth->user();

You can also get a field of currently logged in user:

$this->Session->read('Auth.User.email');
//or
$this->Auth->user()['email'];
Rustproof answered 9/11, 2012 at 16:37 Comment(4)
In beforeFilter of your Controller, assign user variable into Model's variable like: $this->MyModel->user = $this->Session->read('Auth.user'); Now you can call 'user' in your model.Rustproof
The only issue with that is then you have to assign it for every single model, which means that you are going to end up with a lot of memory usage.Lagomorph
Actually, this is the same as accepted solution, except i told you to use it in the controller you need. But the accepted solution suggests that you use it in app controller, which means literally more memory usage than only in needed controller.Rustproof
Once you need this in more than one controller code duplication appears. And you would be coupling every controller to a particular implementation as well. This should definitely go into the model. Or at least into a component where you could change the implementation only once.Gaga
D
0

None of these solutions work in CakePHP version 3. Anyone know of a way to do this? Right now, I'm completely stepping around the framework by accessing the $_SESSION variable directly from my model.

Damalus answered 25/5, 2015 at 19:19 Comment(3)
This is not recommended by cake: book.cakephp.org/3.0/en/development/sessions.html#sessions: Usage of $_SESSION is generally avoided in CakePHPPinero
Understood, but how do you access the session object from a model then in 3.0? The only way that I have found to do it is via $_SESSIONDamalus
I created the following to get the auth-data everywhere... cakemanager.org/docs/utils/1.0/components/globalauth. It's something ;)... And useful!Pinero
F
0

In CakePHP 4, with the Authentication plugin, you should be able to access the currently authenticated user in the Table model with:

namespace App\Model\Table;

use Cake\Http\Session;

class MyTable extends Table
{
    public function myFunction()
    {
        $session = new Session();
        $userId = $session->read('Auth.id');
    }
}

The Auth object in session should have other fields from your Users table as well, accessed via $session->read('Auth.your_field_name');.

Fantom answered 19/6, 2023 at 6:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.