cakephp 3编辑用户用户名和密码 - 无法找到当前实体的表类

时间:2015-12-01 16:34:06

标签: php cakephp

我正在使用cakephp 3.5(今天运行更新)来创建我的第一个非教程Web应用程序。我正在尝试设置我的应用,以便我可以编辑我的用户帐户详细信息(用户名和密码)。 我不确定我做了什么,但在登录时我实际上无法访问我的edit.ctp(视图)。我不断收到“无法找到当前实体的表类”错误。

我的目标是让用户能够编辑他们的用户名(这是一个电子邮件地址),并在他们想要的时候更改他们的密码。

有人可以帮助我锻炼我出错的地方,以及为什么我一直得到“无法找到当前实体的表类”错误以及我可以做些什么来解决它。 我已经阅读了尽可能多的相关文章。我已经尝试了各种“isAuthorised”函数版本,并且我不断收到同样的错误,所以我确信这是我不知道该找什么的东西。

以下是我的代码:

The User.php file:

<?php
namespace App\Model\Entity;

use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;

/**
 * User Entity.
 *
 * @property int $id
 * @property string $username
 * @property string $password
 * @property string $role
 * @property \Cake\I18n\Time $created
 * @property \Cake\I18n\Time $activity_date
 * @property bool $terms_of_service
 * @property bool $paid
 * @property \Cake\I18n\Time $paid_date
 * @property \Cake\I18n\Time $paid_until
 * @property bool $verified
 * @property \App\Model\Entity\Agent[] $agents
 */
class User extends Entity
{

    /**
     * Fields that can be mass assigned using newEntity() or patchEntity().
     *
     * Note that when '*' is set to true, this allows all unspecified fields to
     * be mass assigned. For security purposes, it is advised to set '*' to false
     * (or remove it), and explicitly make individual fields accessible as needed.
     *
     * @var array
     */
    protected $_accessible = [
        '*' => true,
        'id' => false,
    ];
    protected function _setPassword($password)
    {
        return (new DefaultPasswordHasher)->hash($password);
    }
}

The UsersTable.php file:
<?php 
namespace App\Model\Table;

use App\Model\Entity\User;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

/**
 * Users Model
 *
 * @property \Cake\ORM\Association\HasMany $Agents
 */
class UsersTable extends Table
{
    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('users');
        $this->displayField('username');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');

        $this->hasMany('Agents', [
            'foreignKey' => 'user_id'
        ]);
    }

    /**
     * Default validation rules.
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */
    public function validationDefault(Validator $validator)
    {
         $validator
            ->notEmpty('username','Please supply your email address')
            ->add('username', 'valid', ['rule'=>'email']);

        $validator
            ->notEmpty('password','Please supply your password');

        $validator
            ->notEmpty('role','Please select your account type')
            ->add('role','inList',[
                'rule' => ['inList',['agent','buyer']],
                'message' => 'Please select a valid role'
            ]);

        $validator
            ->add('terms_of_service', 'valid', ['rule' => 'boolean'])
            ->notEmpty('terms_of_service','You must agree to the terms of service to register');

        return $validator;
    }
    public function isOwnedBy($userId)
    {
        return $this->exists(['id' => $userId]);
    }
    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->isUnique(['username']));
        return $rules;
    }
}

The relevant pieces UsersController.php file:

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\ORM\TableRegistry;
use Cake\Event\Event;
//use Cake\ORM\Entity;

/**
 * Users Controller
 *
 * @property \App\Model\Table\UsersTable $Users
 */
class UsersController extends AppController
{
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        $this->Auth->allow(['signup','logout']);
        $this->Auth->deny(['index']);

    }
    // The owner of an user can edit and delete it
    public function isAuthorized($user)
    {
        if (in_array($this->request->action, ['edit', 'delete','view'])) {
            if ($this->Users->isOwnedBy($user['id'])) {
                return true;
            }
        }
        return parent::isAuthorized($user);
    }

    /**
     * Edit method
     *
     * @param string|null $id User id.
     * @return void Redirects on successful edit, renders view otherwise.
     * @throws \Cake\Network\Exception\NotFoundException When record not found.
     */
    public function edit($id = null)
    {
        $id = $this->Auth->user('id');
        $user = $this->Users->get($id, [
            'contain' => []
        ]); 
        if ($this->request->is(['patch', 'post', 'put'])) {
            $user = $this->Users->patchEntity($user, $this->request->data);
            if ($this->Users->save($user)) {
                $this->Flash->success(__('Your account has been edited.'));
                return $this->redirect(['controller','Users','action' => 'edit']);
            } else {
                $this->Flash->error(__('The user could not be saved. Please, try again.'));
            }
        }
        $this->set(compact('user'));
        $this->set('_serialize', ['user']);
    }

The AppController.php file

<?php
/**
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link      http://cakephp.org CakePHP(tm) Project
 * @since     0.2.9
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
 */
namespace App\Controller;

use Cake\Controller\Controller;
use Cake\Event\Event;

/**
 * Application Controller
 *
 * Add your application-wide methods in the class below, your controllers
 * will inherit them.
 *
 * @link http://book.cakephp.org/3.0/en/controllers.html#the-app-controller
 */
class AppController extends Controller
{
    /**
     * Initialization hook method.
     *
     * Use this method to add common initialization code like loading components.
     *
     * e.g. `$this->loadComponent('Security');`
     *
     * @return void
     */
    public function initialize()
    {
        parent::initialize();

        $this->loadComponent('RequestHandler');
        $this->loadComponent('Flash');
        $this->loadComponent('Auth', [
            /*'authenticate' => [
                'Form' => [
                    'fields' => ['username' => 'email', 'password' => 'password']
                ]
            ],*/
            'authorize' => 'Controller',
            'loginRedirect' => [
                'controller' => 'Properties',
                'action' => 'myproperties'
            ],
            'logoutRedirect' => [
                'controller' => '',
                'action' => 'index'
            ],
            'unauthorizedRedirect' => $this->referer(),
            //'authError' => 'You must be logged in to view that page.',
        ]);
        // Allow the display action so our pages controller continues to work
        $this->Auth->allow(['display']);
    }
    public function beforeFilter(Event $event)
    {
        $this->Auth->allow(['index', 'view','logout','search']);
    }
    /**
     * Before render callback.
     *
     * @param \Cake\Event\Event $event The beforeRender event.
     * @return void
     */
    public function beforeRender(Event $event)
    {
        if (!array_key_exists('_serialize', $this->viewVars) &&
            in_array($this->response->type(), ['application/json', 'application/xml'])
        ) {
            $this->set('_serialize', true);
        }
        $this -> set('user', $this -> Auth -> user());
    }

    public function isAuthorized($user) {
    $childClass = get_called_class();

    if(method_exists($childClass, '_isAuthorized'))
        return $childClass::_isAuthorized($user, $this -> request);

    return static::_isAuthorized($user, $request);
    }
    static public function _isAuthorized($user, $request)
    {

        // Admin can access every action
        if (isset($user['role']) && $user['role'] === 'admin') {
            return true;
        }       
        // Default deny
        return false;
    }
}

2 个答案:

答案 0 :(得分:6)

问题在于AppController beforeRender方法中你有这个..

    $this -> set('user', $this -> Auth -> user());

这意味着您将与所有控制器和操作共享当前用户。

另请注意,在用户控制器的编辑操作中,您还调用了变量$user,并通过set将其发送到视图...

这就是问题的根源,这就是为什么如果你用users更改名称就行了!在$user方法中发送的beforeRender与用户控制器中的编辑操作中发送的$user之间似乎存在冲突

答案 1 :(得分:1)

好的,经过大量的反复试验后,我解决了这个问题。这是一个简单的修复,虽然我不知道它为什么会起作用...所以如果有人能解释那会很棒:我将控制器文件中的$user变量的编辑功能更改为{{1以及edit.ctp文件中的$users变量到$user,并且它已经工作了。