CakePHP organising controllers - cakephp

i have the following queries common on few methods of the controllers. so is there a way to organise it ? i will need all the variables in the controller so i cant create a private method and return it.
// Checks if the User is logged in if yes gathers the ID
$id = $this->_loggedIN();
// Find the ItemID from the Item Table
$itemId = $this->User->Item->itemId('1', $id);
// Finding the User Data and last Status Message
$user = $this->User->Item->find('first', array('conditions' => array('Item.id' => $itemId), 'contain' => array('User', 'StatusMessage' => array('limit' => 1, 'order' => 'StatusMessage.created DESC'))));

Since this seems to pertain to the logged in user, you should do this once and save the data in the session. If you're using the AuthComponent (which you probably should), there already is a generic way to find out whether a user is logged in and what his id is:
$this->Auth->user('id');
All the other data of the user model is accessible in the same way. This is simply stored in the session under the key 'Auth' and is accessible like $this->Session->read('Auth.User.id'). If you want to store even more data about the user in the session (like related items or whatnot), do it once in the login method.
function beforeFilter() {
$this->Auth->autoRedirect = false;
}
function login() {
if ($this->Auth->user()) {
$item = /* find item */;
$user = /* find user */;
$this->Session->write('Auth.Item', $item);
$this->Session->write('Auth.User', $user);
$this->redirect($this->Auth->redirect());
}
}

How about a function in the AppController? Or even better - AppModel?

Related

Auto login after registration in CakePHP 1.3

I create a new User with this code:
controller:
$this->User->createUser($this->data)
Model:
function createUser(){
$this->create();
}
After that I want to login the user. I already tryed this (in the controller):
$this->Auth->login($this->data);
$this->redirect('home');
Unfortunately it does not work that way. Am I doing something wrong?
For cake1.3
In your controller
$id = $this->User->createUser($this->data);
$this->data['User'] = array_merge($this->data['User'], array('id' => $id));
$this->Auth->login($this->data);
$this->redirect('home');
Model
before creating user you've to hash the user entered password and then save into the database
function createUser($data){
$data['User']['password'] = md5($data['User']['password']);
$this->save();
return $this->id; // return id of last saved record
}

Unable to update user profile data in database

In my controller
public function profile() {
$UserInfo = $this->Auth->user()
if(!empty($this->data)) {
print_r($this->data);
$this->User->save($this->data);
}
if(!empty($UserInfo['id'])){
$this->data = $this->User->find('first',array('conditions'=>array('id'=>$UserInfo['id'])));
}
}
when i submit the data it is not submitted to db and i get only previous value.
Why are you querying the session here? of course this will always get you the old data again after the save.
Use the database as always, update the database again and only then overwrite the session maybe (You seem to be using cake 1.3):
public function profile() {
$uid = $this->Session->read('Auth.User.id');
if (!empty($this->data)) {
$this->data['User']['id'] = $uid;
if ($this->User->save($this->data, true, array('email', 'first_name', 'last_name', 'id', ...))) {
// if you rely on auth session data from the user, make sure to update that here
$this->Session->write('Auth.User.email', $this->data['User']['email']); // etc
...
// OK, redirect
} else {
// ERROR
}
} else {
$this->data = $this->User->find('first', ...);
}
}
As you can see I update the session keys that have been changed.
If you are using 2.x (which you did not specify as for now) you could also use
$this->Auth->login($this->request->data['User']); // must be the User array directly
although you will have to careful to pass all the data that has been in the session before.
If you plan on using login(), it would be better to find(first) the updated record again and pass this into login() then.
But personally, I prefer to only update the fields that actually changed.
see Editing own account/profile

cakephp auth component, use two models

My site has a public section for employees and back end for admin. It uses 2 different models, Employee and Admin.
I want to use Auth component for employee login and admin login. I know how to setup Auth component to use a Model other than default User model. But can i have auth component use 2 models, one for Employee authentication and other for Admin authentication? I am using admin_ prefix routing.
Is this possible? I searched but all i could found was tutorials on howto make Auth component use models other than User model.
Please advise!
EDIT
I use separate login forms for admin login and employee login. Both use the employee controller, but separate actions.
http://api.cakephp.org/class/auth-component
check the property authenticate, your answer is there!
and more :
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html.
Look at authentication handlers!
Here is an example directly from cake page
<?php
// Basic setup
$this->Auth->authenticate = array('Form');
// Pass settings in
$this->Auth->authenticate = array(
'Form' => array('userModel' => 'Member'),
'Basic' => array('userModel' => 'Member')
);
Just put something else instead of Form and Basic and associate the good Model
Considering you are using two radio buttons for Employee and Admin. Then you can use the following code into the login method.
function login()
{
if ($this->request->is('post'))
{
$logged_in = false;
$login_type = $this->request->data['User']['login_type']
if ($login_type == 'Admin')
{
$this->Auth->authenticate = array('Form' => array('userModel' => 'Admin' ));
}
else //if ($login_type == 'Employee')
{
$this->Auth->authenticate = array('Form' => array('userModel' => 'Employee' ));
}
$this->Auth->constructAuthenticate();
if ($this->Auth->login())
{
$logged_in = true;
/*.... Do what you want............*/
}
}
}

How do I create a guest account without actually placing it in the db in CakePHP?

So I have a pretty typical user model, nothing special about it. I'd like to be able to use this model as a guest user when no other user is logged in.
Is there a way to create a guest account, or some sort of default when no account is set, in CakePHP so that Auth contains that?
So, for example, the id would be set as 0, username would be set to guest, etc.
Thank you,
James
You could override the find method at your User model, so that when Auth calls it (internally), you can intercept that and return whatever your want instead. Something like this (on your User model):
public function find($conditions, $fields, $order=null, $recursive=false) {
$user = parent::find($conditions, $fields, $order, $recursive);
if(empty($user)) {
// No "real" user found, let's create "guest"
$user = array(
'User' => array(
'id' => 0,
'username' => 'guest'
// add other fields as needed
)
);
}
return $user;
}
Just add it to the session.
$this->Session->write(AuthComponent::$sessionKey, array(
'User' => array(
'id' => 0,
'username' => 'guest'
)
));
In AppController :
public function beforeFilter() {
if(!$this->Auth->loggedIn()){
$this->loadModel('User');
$user = $this->User->findById(0); //Guest user id
$this->Auth->login($user['User']);
}
}
This works fine for me with CakePHP 2.2.
It allows permission configuration including guest's permission via a web interface : http://www.alaxos.net/blaxos/pages/view/plugin_acl_2.0

Cakephp Auth with multiple "Users" tables

I would like to know how to deal with only ONE authentification process and "users" in multiple tables. I have 4 Users table: users, admins, artists, teamadmins which all have specific fields, but I would like all of these users to be able to connect via only one form on the homepage, and being redirected after that to their specific dashboards.
I think the redirections shouldn't be a problem, and some routes added should work, but I really don't know where to look/start to ake this all possible.
Cheers,
Nicolas.
EDIT: here's the final solution (thanks to deizel)
App::import('Component', 'Auth');
class SiteAuthComponent extends AuthComponent {
function identify($user = null, $conditions = null) {
$models = array('User', 'Admin', 'Artist');
foreach ($models as $model) {
$this->userModel = $model; // switch model
$this->params["data"][$model] = $this->params["data"]["User"]; // switch model in params/data too
$result = parent::identify($this->params["data"][$model], $conditions); // let cake do its thing
if ($result) {
return $result; // login success
}
}
return null; // login failure
}
}
CakePHP's AuthComponent only supports authentication against a single "User" model at a time. The model is chosen by setting the Auth::userModel property, but it only accepts a string and not an array of models.
You can switch the userModel on the fly with the following code, but this requires you to know in advance which model to switch to (eg. your users have to choose their account type from a dropdown):
public function beforeFilter() {
if (isset($this->data['User']['model'])) {
$this->Auth->userModel = $this->data['User']['model'];
}
}
You can likely extend the core AuthComponent to add the functionality you want by overwriting the AuthComponent::identify() method so it loops over and attempts authentication with each model:
App::import('Component', 'AuthComponent');
class AppAuthComponent extends AuthComponent {
function identify($user = null, $conditions = null) {
$models = array('User', 'Admin', 'Artist', 'TeamAdmin');
foreach ($models as $model) {
$this->userModel = $model; // switch model
$result = parent::identify($user, $conditions); // let cake do it's thing
if ($result) {
return $result; // login success
}
}
return null; // login failure
}
}
You will have to replace occurrences of Auth in your application with AppAuth to use your extended AuthComponent, unless you use this trick.
While annoying, I think the best solution is probably using Cake's built in ACL support (see http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application.html).
If you do authentication the way you're talking about, you have to keep track of permissions in your controller code, checking to see what the userModel is. If you use an access control list, the permission tree will already exist in the database, which should simplify your code a great deal, and make it more modular.
It also means restructuring your data model to have a single users table and groups table instead of entity classes for each type of user.
I just went through the process of doing this myself... :(
this is also a possibility
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'AnotherModel'),
'Form',
'Basic'
);
}
Here is the final solution as suggested by deizel and modified by Nicolas:
App::import('Component', 'Auth');
class SiteAuthComponent extends AuthComponent {
function identify($user = null, $conditions = null) {
$models = array('User', 'Admin', 'Artist');
foreach ($models as $model) {
$this->userModel = $model; // switch model
$this->params["data"][$model] = $this->params["data"]["User"]; // switch model in params/data too
$result = parent::identify($this->params["data"][$model], $conditions); // let cake do its thing
if ($result) {
return $result; // login success
}
}
return null; // login failure
}
}

Resources