Simple Auth with Users HABTM Groups in CakePHP
In almost every project I need to setup some sort of login, and usually it requires group access to certain data depending on different criteria.
For example I may have groups Admin+Member and I want Members to only be able to see other Users Profiles if the other Profile is active.
Little Helper
This function checks if the user is in a group. config/bootstrap.php
<?php
function in_group($group,$groups) {
if (isset($groups['Group'])) {
$groups = $groups['Group'];
}
if (!$groups || !is_array($groups) || empty($groups)) {
return false;
}
$allow = false;
foreach($groups as $_group) {
if ($_group['name'] == $group) {
$allow = true;
break;
}
}
return $allow;
}
?>
The Tables
# users CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) NOT NULL auto_increment, `username` char(50) NOT NULL, `password` char(50) NOT NULL, `active` tinyint(4) NOT NULL default '0', `email` varchar(255) NOT NULL, PRIMARY KEY (`id`) ); # groups CREATE TABLE IF NOT EXISTS `groups` ( `id` int(11) NOT NULL auto_increment, `name` varchar(128) NOT NULL, `created` datetime default NULL, `modified` datetime default NULL, PRIMARY KEY (`id`) ); # groups_to_users CREATE TABLE IF NOT EXISTS `groups_to_users` ( `group_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, PRIMARY KEY (`group_id`,`user_id`) );
The Models
Before we get started, lets setup the models. I have added some validation to get you started. app_model.php
<?php
class AppModel extends Model {
function validUnique($value,$field){
if (is_array($field)) {
foreach($field as $v) $field = $v;
}
$conditions = array();
$conditions["{$this->name}.{$field}"] = $value;
if (isset($this->id) && $this->id) {
$conditions["{$this->name}.{$this->primaryKey}"] = "!={$this->id}";
}
$this->recursive = -1;
return !$this->hasAny($conditions);
}
function required($field) {
foreach($field as $k=>$v){}
return $v?true:false;
}
}
?>
models/user.php
<?php
class User extends AppModel {
var $name = 'User';
var $displayField = 'username';
var $validate = array(
'username' => array(
'not unique' => array(
'rule'=>array('validUnique','username'),
'required' => true,
),
'must be alpha-numeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
),
'required field' => array(
'rule' => 'required',
'required' => true,
),
),
'email' => array(
'not unique' => array(
'rule'=>array('validUnique','email'),
'required' => true,
),
'invalid email' => array(
'rule'=>'email',
'required' => true,
),
'required field' => array(
'rule' => 'required',
'required' => true,
),
),
'password_confirm' => array(
'does not match' => array(
'rule' => 'validPasswordConfirm',
'required' => false,
),
),
);
var $hasAndBelongsToMany = array(
'Group' => array(
'className' => 'Group',
'joinTable' => 'groups_to_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'group_id',
'with' => 'GroupToUser',
),
);
function validPasswordConfirm($value){
if ($this->data[$this->alias]['password_change'] != $this->data[$this->alias]['password_confirm']) {
return false;
}
return true;
}
}
?>
models/group.php
<?php
class Group extends AppModel {
var $name = 'Group';
var $validate = array(
'name' => array(
'required field' => array(
'rule' => 'required',
'required' => true,
),
'not unique' => array(
'rule'=>array('validUnique','name'),
'required' => true,
),
),
);
}
?>
The Controllers
The app_controller will do the work of setting the related Groups into the Auth data. app_controller.php
<?php
class AppController extends Controller {
var $components = array('Auth');
function beforeFilter() {
$this->__setAuthUser();
// allow pages to be displayed to anyone
if ($this->name=='Pages') {
$this->Auth->allow('display');
}
parent::beforeFilter();
}
function __setAuthUser() {
$this->Auth->userScope = array('User.active = 1');
// read the auth info
$auth = $this->Session->read('Auth');
// set the auth users groups
if (!isset($auth['GroupUser']) || $auth['GroupUser']!=$auth['User']['id']) {
$User = ClassRegistry::init('User');
$auth = $User->find('first',array('conditions'=>array('User.id'=>$this->Auth->user('id'))));
$auth['GroupUser'] = $this->Auth->user('id');
}
// check permissions for admin access
if(isset($this->params[Configure::read('Routing.admin')])) {
if (isset($auth['User']['id']) && !in_group('admin',$auth)) {
$this->_flash(__('You do not have permission to access the administration.',true),'error');
$this->redirect(array('admin'=>false,'controller'=>'users','action'=>'login'));
}
}
// save and set the auth info
$this->Session->write('Auth',$auth);
$this->set('auth',isset($auth['User'])?$auth:false);
}
function _flash($message,$type='message') {
$messages = (array)$this->Session->read('Message.multiFlash');
$messages[] = array('message'=>$message, 'layout'=>'default', 'params'=>array('class'=>$type));
$this->Session->write('Message.multiFlash', $messages);
}
}
?>
Next I have provided a fully working users_controller, complete with account register, account management and lost password email.
I have also included some extra goodies such as habtm checkbox, breadcrumbs, search and multi-actions.
controllers/users_controller.php
<?php
class UsersController extends AppController {
var $name = 'Users';
var $components = array('Email');
var $multiActions = array(
'multi_delete',
);
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('register','password');
if (isset($this->passedArgs['key'])) {
$this->Auth->allow('account');
}
}
//
// PUBLIC ACTIONS
//
function index() {
$title = 'My Account';
// set breadcrumb
$breadcrumb = array();
$breadcrumb[] = array(
'name' => 'Home',
'href' => '/',
);
$breadcrumb[] = array(
'name' => $title,
);
$this->set(compact('title','breadcrumb'));
}
function account() {
// load account from key
if (isset($this->passedArgs['key'])) {
$this->recursive = -1;
$user = $this->User->findByPassword($this->passedArgs['key']);
if (!$user) {
$this->_flash(__('Invalid Key.', true),'error');
$this->redirect(array('action'=>'index'));
}
$this->Auth->login($user);
}
// load account from auth user
$id = $this->Auth->user('id');
if (!$id) {
$this->_flash(__('Invalid User.', true),'error');
$this->redirect(array('action'=>'index'));
}
// process submit
if (!empty($this->data)) {
$error = false;
$this->User->create();
$this->User->id = $id;
if ($this->data['User']['password_change']) {
$this->data['User']['password'] = $this->Auth->password($this->data['User']['password_change']);
}
if ($this->User->save($this->data,true,array('email','username','password','password_change','password_confirm'))) {
$this->_flash(__('Your Account has been saved.', true),'success');
$this->redirect(array('action'=>'index'));
}
$this->_flash(__('Your Account could not be saved. Please, try again.', true),'warning');
}
if (empty($this->data)) {
$this->data = $this->User->read(null, $id);
}
$title = 'Modify Details';
// set breadcrumb
$breadcrumb = array();
$breadcrumb[] = array(
'name' => 'Home',
'href' => '/',
);
$breadcrumb[] = array(
'name' => 'My Account',
'href' => array('controller'=>'users','action'=>'index'),
);
$breadcrumb[] = array(
'name' => $title,
);
$this->set(compact('title','breadcrumb'));
}
function register() {
$title = 'Register';
// process submit
if (!empty($this->data)) {
if (!$this->data['User']['password_confirm']) {
$this->data['User']['password_confirm']=' ';
}
$this->data['User']['password'] = $this->Auth->password($this->data['User']['password_change']);
$this->data['User']['active'] = 1;
$this->User->create();
if ($this->User->save($this->data,true,array('email','username','active','password','password_change','password_confirm'))) {
$this->Auth->login($this->data);
$this->_flash(__('Your Account has been created.', true),'success');
$this->redirect(array('action'=>'index'));
}
$this->_flash(__('Your Account could not be created. Please, try again.', true),'warning');
}
// set breadcrumb
$breadcrumb = array();
$breadcrumb[] = array(
'name' => 'Home',
'href' => '/',
);
$breadcrumb[] = array(
'name' => 'My Account',
'href' => array('controller'=>'users','action'=>'index'),
);
$breadcrumb[] = array(
'name' => $title,
);
$this->set(compact('title','breadcrumb'));
}
function login() {
$title = 'Login';
// set breadcrumb
$breadcrumb = array();
$breadcrumb[] = array(
'name' => 'Home',
'href' => '/',
);
$breadcrumb[] = array(
'name' => 'My Account',
'href' => array('controller'=>'users','action'=>'index'),
);
$breadcrumb[] = array(
'name' => $title,
);
$this->set(compact('title','breadcrumb'));
}
function logout() {
$this->Session->delete('Auth.GroupUser');
$this->redirect($this->Auth->logout());
}
function password() {
$error = false;
if (!$error) {
if (!isset($this->data['User']['lost_password']) || !$this->data['User']['lost_password']) {
$this->_flash(__('Please enter an email address or username.', true),'warning');
$error = true;
}
}
if (!$error) {
$this->User->recursive = -1;
$user = $this->User->findByUsername($this->data['User']['lost_password']);
if (!$user) {
$user = $this->User->findByEmail($this->data['User']['lost_password']);
}
if (!$user) {
$this->_flash(__('Account not found.', true),'error');
$error = true;
}
}
if (!$error) {
$this->Email->to = $user['User']['email'];
$this->Email->subject = 'New Password for '.Configure::read('Settings.app.name');
$this->Email->replyTo = Configure::read('Settings.app.email');
$this->Email->from = Configure::read('Settings.app.name').' <'.Configure::read('Settings.app.email').'>';
$this->Email->template = 'password';
$this->Email->sendAs = 'both';
$this->Email->delivery = Configure::read('Settings.smtp.delivery');
$this->Email->smtpOptions = array(
'port'=> 25,
'host' => 'localhost',
'timeout' => 30,
'username' => Configure::read('Settings.smtp.username'),
'password' => Configure::read('Settings.smtp.password'),
);
$this->set(compact('user'));
if (!$this->Email->send()) {
debug($this->Email);
$this->_flash(__('Email could not be sent.', true),'error');
$error = true;
}
}
if (!$error) {
$this->_flash(__(sprintf('New password has been sent to %s.',$user['User']['email']), true),'success');
$this->redirect(array('action'=>'login'));
}
$this->login();
$this->render('login');
}
//
// ADMIN ACTIONS
//
function admin_index() {
if (!isset($this->passedArgs['sort'])) {
$this->paginate['order'] = array('User.id'=>'desc');
}
// keywords
if(isset($this->passedArgs['keywords'])) {
$keywords = $this->passedArgs['keywords'];
$this->paginate['conditions'][] = array(
'OR' => array(
'User.id' => $keywords,
'User.username LIKE' => "%$keywords%",
'User.email LIKE' => "%$keywords%",
)
);
$this->data['Search']['keywords'] = $keywords;
}
// username
if(isset($this->passedArgs['username'])) {
$this->paginate['conditions'][]['User.username LIKE'] = str_replace('*','%',$this->passedArgs['username']);
$this->data['Search']['username'] = $this->passedArgs['username'];
}
// email
if(isset($this->passedArgs['email'])) {
$this->paginate['conditions'][]['User.email LIKE'] = str_replace('*','%',$this->passedArgs['email']);
$this->data['Search']['email'] = $this->passedArgs['email'];
}
// filter by group_id
if (isset($this->passedArgs['group_id'])) {
$this->User->bindModel(array(
'hasOne' => array(
'GroupToUser' => array(
'className' => 'GroupToUser',
'foreign_key' => 'user_id',
),
),
),false);
$this->paginate['conditions'][]['GroupToUser.group_id'] = $this->passedArgs['group_id'];
$this->data['Search']['group_id'] = $this->passedArgs['group_id'];
}
// load the data
$users = $this->paginate();
// set related data
$groups = $this->User->Group->find('list');
$this->set(compact('users','groups'));
}
function admin_search() {
$url = array();
$url['action'] = 'index';
if (isset($this->data['Search']['keywords']) && $this->data['Search']['keywords']) {
$url['keywords'] = $this->data['Search']['keywords'];
}
if (isset($this->data['Search']['id']) && $this->data['Search']['id']) {
$url['id'] = $this->data['Search']['id'];
}
if (isset($this->data['Search']['username']) && $this->data['Search']['username']) {
$url['username'] = $this->data['Search']['username'];
}
if (isset($this->data['Search']['email']) && $this->data['Search']['email']) {
$url['email'] = $this->data['Search']['email'];
}
if (isset($this->data['Search']['group_id']) && $this->data['Search']['group_id']) {
$url['group_id'] = $this->data['Search']['group_id'];
}
$this->redirect($url, null, true);
}
function admin_view($id = null) {
if (!$id) {
$this->_flash(__('Invalid User.', true),'error');
$this->redirect(array('action'=>'index'));
}
$user = $this->User->read(null, $id);
$this->set(compact('user'));
}
function admin_add() {
$this->admin_form();
$this->render('admin_form');
}
function admin_edit($id = null) {
if (!$id && empty($this->data)) {
$this->_flash(__('Invalid User.', true),'error');
$this->redirect(array('action'=>'index'));
}
$this->admin_form($id);
$this->render('admin_form');
}
function admin_form($id = null) {
// process submit
if (!empty($this->data)) {
// get the groups from the checkbox data
$this->data['Group']['Group'] = array();
foreach($this->data['Group']['checkbox'] as $k=>$v) {
if ($v) $this->data['Group']['Group'][] = $k;
}
// save the data
$id = $this->data['User']['id'];
$this->User->create();
if (!$id && !$this->data['User']['password_confirm']) {
$this->data['User']['password_confirm']=' ';
}
if ($this->data['User']['password_change']) {
$this->data['User']['password'] = $this->Auth->password($this->data['User']['password_change']);
}
if ($this->User->save($this->data)) {
$this->_flash(__('The User has been saved.', true),'success');
$this->redirect(array('action'=>'view', $this->User->id));
}
$this->_flash(__('The User could not be saved. Please, try again.', true),'warning');
}
if (empty($this->data)) {
$this->data = $this->User->read(null, $id);
}
$groups = $this->User->Group->find('list');
$this->set(compact('groups'));
}
function admin_delete($id = null) {
if (!$id) {
$this->_flash(__('Invalid User.', true),'error');
$this->redirect(array('action'=>'index'));
}
$this->User->del($id);
$this->_flash(__('The User has been deleted.', true),'success');
$this->redirect($this->referer(), null, true);
}
function admin_multi_delete() {
if (!isset($this->params['form']['record']) || !count($this->params['form']['record'])) {
$this->_flash(__('No records selected.', true),'warning');
$this->redirect($this->referer(), null, true);
}
$ids = array();
foreach($this->params['form']['record'] as $id=>$v) {
$ids[] = '#'.$id;
$this->User->del($id);
}
$this->_flash(__(sprintf('Deleted Users - %s.',implode(', ',$ids)),true),'success');
$this->redirect($this->referer(), null, true);
}
function admin_login() {
$title = 'Admin Login';
$this->set(compact('title'));
}
function admin_logout() {
$this->Session->delete('Auth.GroupUser');
$this->redirect($this->Auth->logout());
}
}
?>
The Views
views/users/login.php
<?php
if ($session->check('Message.auth')) $session->flash('auth');
echo $form->create('User', array('action' => 'login'));
echo $form->input('username');
echo $form->input('password');
echo $form->end('Login');
?>
views/users/index.php
views/users/account.php<?php debug($auth); ?>
<?php
echo $form->create('User',array('url'=>array('action'=>'account')));
echo $form->input('email');
echo $form->input('username');
echo $form->input('password_change',array('type'=>'password','after'=>__('Leave blank if you do not wish to change the password.',true)));
echo $form->input('password_confirm',array('type'=>'password'));
echo $form->end('Save');
?>
views/users/register.php
<?php
echo $form->create('User', array('action' => 'register'));
echo $form->input('email');
echo $form->input('username');
echo $form->input('password_change',array('label'=>__('Password',true),'type'=>'password'));
echo $form->input('password_confirm',array('type'=>'password'));
echo $form->end('Register');
?>
views/users/admin_login.php
<?php
if ($session->check('Message.auth')) $session->flash('auth');
echo $form->create('User', array('action' => 'login'));
echo $form->input('username');
echo $form->input('password');
echo $form->end('Login');
?>
views/users/admin_index.php
<div class="actions">
<ul>
<li><?php echo $html->link(__('New User', true), array('action'=>'add')); ?></li>
<li><?php echo $html->link(__('Search', true), 'javascript:void(0)', array('class'=>'search-toggle')); ?></li>
</ul>
</div>
<div class="users index">
<h2><?php __('Users');?></h2>
<?php echo $form->create('User',array('action'=>'search'));?>
<fieldset>
<legend><?php __('User Search');?></legend>
<?php
echo $form->input('Search.keywords');
echo $form->input('Search.id');
echo $form->input('Search.username',array(
'after' => 'wildcard is *',
));
echo $form->input('Search.email',array(
'after' => 'wildcard is *',
));
echo $form->input('Search.group_id',array('empty'=>__('All',true)));
echo $form->submit('Search');
?>
</fieldset>
<?php echo $form->end();?>
<?php echo $form->create('User',array('id'=>'UserListForm','url'=>array('controller'=>'users','action'=>'multi')));?>
<table cellpadding="0" cellspacing="0" class="listTable">
<tr>
<th>
<span class="select_all">a</span>|<span class="select_none">n</span>
</th>
<th><?php echo $paginator->sort('id');?></th>
<th><?php echo $paginator->sort('username');?></th>
<th><?php echo $paginator->sort('email');?></th>
<th><?php echo $paginator->sort('created');?></th>
<th><?php echo $paginator->sort('modified');?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($users as $user):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td>
<?php echo $form->input($user['User']['id'],array(
'type'=>'checkbox',
'label'=>false,
'name'=>'record['.$user['User']['id'].']',
'id'=>'listRecord_'.$user['User']['id'],
)); ?>
</td>
<td>
<?php echo $user['User']['id']; ?>
</td>
<td>
<b><?php echo $user['User']['username']; ?></b>
</td>
<td>
<?php echo $user['User']['email']; ?>
</td>
<td align="center">
<?php echo str_replace(' ','<br/>',$user['User']['created']); ?>
</td>
<td align="center">
<?php echo str_replace(' ','<br/>',$user['User']['modified']); ?>
</td>
<td class="actions">
<?php echo $html->link(__('View', true), array('action'=>'view', $user['User']['id'])); ?>
<?php echo $html->link(__('Edit', true), array('action'=>'edit', $user['User']['id'])); ?>
<?php echo $html->link(__('Delete', true), array('action'=>'delete', $user['User']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $user['User']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<div class="multi_actions">
<input type="submit" name="data[action][multi_delete]" value="Delete" onclick="return confirm('<?php __('Are you sure you want to delete the selected records?'); ?>');"/>
</div>
<?php echo $form->end();?>
<?php echo $this->renderElement('paging');?>
</div>
views/users/admin_view.php
<div class="actions">
<ul>
<li><?php echo $html->link(__('Edit User', true), array('action'=>'edit', $user['User']['id'])); ?> </li>
<li><?php echo $html->link(__('Delete User', true), array('action'=>'delete', $user['User']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $user['User']['id'])); ?> </li>
<li><?php echo $html->link(__('List Users', true), array('action'=>'index')); ?> </li>
<li><?php echo $html->link(__('New User', true), array('action'=>'add')); ?> </li>
</ul>
</div>
<h2><?php __('User');?></h2>
<div class="users view">
<dl><?php $i = 0; $class = ' class="altrow"';?>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Id'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['id']; ?>
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Username'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['username']; ?>
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Email'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['email']; ?>
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Created'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['created']; ?>
</dd>
<dt<?php if ($i % 2 == 0) echo $class;?>><?php __('Modified'); ?></dt>
<dd<?php if ($i++ % 2 == 0) echo $class;?>>
<?php echo $user['User']['modified']; ?>
</dd>
</dl>
</div>
<div class="related">
<h3><?php __('Groups');?></h3>
<?php if (!empty($user['Group'])):?>
<table cellpadding="0" cellspacing="0" class="listTable">
<tr>
<th><?php __('Id'); ?></th>
<th width="90%"><?php __('Name'); ?></th>
<th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($user['Group'] as $group):
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $group['id'];?></td>
<td><?php echo $group['name'];?></td>
<td class="actions">
<?php echo $html->link(__('View Users', true), array('controller'=> 'users', 'action'=>'index', 'group_id'=>$group['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php echo $form->end();?>
<?php endif; ?>
</div>
views/users/admin_form.php
<div class="actions">
<ul>
<li><?php echo $html->link(__('View', true), array('action'=>'view', $form->value('User.id')));?></li>
<li><?php echo $html->link(__('Delete', true), array('action'=>'delete', $form->value('User.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $form->value('User.id'))); ?></li>
<li><?php echo $html->link(__('List Users', true), array('action'=>'index'));?></li>
</ul>
</div>
<div class="users form">
<h2><?php __('Edit User'); ?></h2>
<?php echo $form->create('User');?>
<fieldset>
<legend><?php __('User');?></legend>
<?php
echo $form->input('id');
echo $form->input('email');
echo $form->input('username');
echo $form->input('active',array('type'=>'checkbox'));
echo $form->input('password_change',array('type'=>'password','after'=>__('Leave blank if you do not wish to change the password.',true)));
echo $form->input('password_confirm',array('type'=>'password'));
?>
</fieldset>
<fieldset>
<legend><?php __('Groups');?></legend>
<?php
$checked = $form->value("Group.Group");
foreach ($groups as $id=>$label) {
echo $form->input("Group.checkbox.$id", array(
'label'=>$label,
'type'=>'checkbox',
'checked'=>(isset($checked[$id])?'checked':false),
));
}
?>
</fieldset>
<?php echo $form->end('Submit');?>
</div>

Comments
I have been working on something similar for a couple of days, coming across this helped me finish up the final pieces, thank's so much for posting this.
Hello,
thanks for a nice example!
When I am making above mention files and try to run the script, it gives me below error:
Notice (8): Undefined property: UsersController::$Session [APP\app_controller.php, line 22]
Code
//pr($_SESSION); die;
$auth = $this->Session->read('Auth');
AppController::__setAuthUser() - APP\app_controller.php, line 22
AppController::beforeFilter() - APP\app_controller.php, line 6
UsersController::beforeFilter() - APP\controllers\users_controller.php, line 11
Controller::startupProcess() - CORE\cake\libs\controller\controller.php, line 526
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 187
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 171
[main] - APP\webroot\index.php, line 83
Fatal error: Call to a member function read() on a non-object in C:\wamp\www\cakegroup\app\app_controller.php on line 22
Can you please let me know, why it is showing?
Hope to hear from you soon!
Thanks,
Aditya
Hello,
I've got the same error. Have you solved the problem?
Best,
Did you get this figured out? You need to add 'Session' to your components array in app controller
var $components = array('Auth', 'Session');
GL
got an error for this line
foreach( $this->groups as $group
any suggestions?
i get this error
Error: Database table group_to_users for model GroupToUser was not found.
in the GroupToUser model add:
I am creating one website with admin panel as per your instructions. But when i am integrating the website , i was getting the following errors
Missing Database Table
Error: Database table group_to_users for model GroupToUser was not found.
Could any of you please suggest me in this since i am new to cakephp.
The answer was right above your comment.
Post new comment