【问题标题】:CakePHP 4.1 saving belongsTo association doesn't workCakePHP 4.1 保存 belongsTo 关联不起作用
【发布时间】:2020-12-05 03:30:07
【问题描述】:

我有两个数据库表 - UsersUserTypes 其中Users 有一个外键user_type_id。 以下是他们的样板模型代码。

Entity/User.php:

class User extends Entity {
    protected $_accessible = [
        'id' => true,
        'email' => true,
        'password' => true,
        'name' => true,
        'user_type_id' => true, // added this as an experiment now, but I shouldn't need it if I understand correctly
        'user_type' => true
    ];
}

Entity/UserType.php:

class UserType extends Entity {
    protected $_accessible = [
        'id' => true,
        'name' => true,
        'users' => true,
    ];
}

Table/UsersTable.php:

class UsersTable extends Table
{
public function initialize(array $config): void
{
    parent::initialize($config);

    $this->setTable('users');
    $this->setDisplayField('name');
    $this->setPrimaryKey('id');

    $this->belongsTo('UserTypes', [
        'joinType' => 'INNER'
    ]);
}


public function validationDefault(Validator $validator): Validator
{
    $validator
        ->integer('id')
        ->allowEmptyString('id', null, 'create');

    $validator
        ->email('email')
        ->requirePresence('email', 'create')
        ->notEmptyString('email');

    $validator
        ->scalar('password')
        ->maxLength('password', 255)
        ->requirePresence('password', 'create')
        ->notEmptyString('password');

    $validator
        ->scalar('name')
        ->maxLength('name', 255)
        ->allowEmptyString('name');

    return $validator;
}

public function buildRules(RulesChecker $rules): RulesChecker
{
    $rules->add($rules->isUnique(['email']));
    $rules->add($rules->existsIn(['user_type_id'], 'UserTypes'));

    return $rules;
}
}

Table/UserTypesTable.php:

class UserTypesTable extends Table
{
    public function initialize(array $config): void
    {
        parent::initialize($config);

        $this->setTable('user_types');
        $this->setDisplayField('name');
        $this->setPrimaryKey('id');
        $this->hasMany('Users');
    }

    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', null, 'create');

        $validator
            ->scalar('name')
            ->requirePresence('name', 'create')
            ->notEmptyString('name');

        return $validator;
    }
}

现在的问题是我似乎无法将记录的user_type_id 字段保存在数据库的users 表中。 为了重现该问题,我在 UsersController.php 中创建了以下简单操作:

public function testAdd()
{
    $testUser = $this->Users->newEmptyEntity();
    $testUser->name = "Test";
    $testUser->email = "test@test.com";
    $testUser->password = "secret";
    $testUser->user_type = $this->Users->UserTypes->get(1); // this exists and I've verified get() finds it correctly
    $this->Users->save($testUser);
}

结果是SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails,尝试查询是INSERT INTO users (email, password, name) VALUES (:c0, :c1, :c2),显然没有必要的user_type_id字段。

我已尝试更改现有用户的用户类型,该用户类型不会失败(因为已经满足 FK 约束)但也没有发生任何更改。

我也尝试了$this->Users->save($testUser, ['associated' => ['UserTypes']]);,这对生成的INSERT SQL 查询没有任何改变。

所以我的问题是,如何插入和更新我的用户实体的外键字段?

---- 编辑----

save() 之前运行debug(get_class($this->Users)) 产生:

APP/Controller/UsersController.php (line 270)
'App\Model\Table\UsersTable'

save() 之前运行debug($testUser) 会产生:

APP/Controller/UsersController.php (line 271)
object(App\Model\Entity\User) id:0 {
'name' => 'Test'
'email' => 'test@test.com'
'password' => '$2y$10$13nmS6Iag3seqkae9L.M0Ow.xV0Tasd/y9XNu12xX9yIozsXNLEnO'
'user_type' => object(App\Model\Entity\UserType) id:1 {
'id' => (int) 1
'name' => 'Full admin'
'[new]' => false
'[accessible]' => [
'id' => true,
'name' => true,
'users' => true,
]
'[dirty]' => [
]
'[original]' => [
]
'[virtual]' => [
]
'[hasErrors]' => false
'[errors]' => [
]
'[invalid]' => [
]
'[repository]' => 'UserTypes'
protected _accessible => [
'id' => true,
'name' => true,
'users' => true,
]
protected _fields => [
'id' => (int) 1,
'name' => 'Full admin',
]
protected _original => [
]
protected _hidden => [
]
protected _virtual => [
]
protected _dirty => [
]
protected _accessors => [
'App\Model\Entity\User' => [
'set' => [
'password' => '_setPassword',
'Password' => '_setPassword',
'name' => '',
'email' => '',
'user_type' => '',
],
],
]
protected _new => false
protected _errors => [
]
protected _invalid => [
]
protected _registryAlias => 'UserTypes'
}
'[new]' => true
'[accessible]' => [
'id' => true,
'email' => true,
'password' => true,
'name' => true,
'created' => true,
'modified' => true,
'user_type_id' => true,
'user_type' => true
]
'[dirty]' => [
'name' => true,
'email' => true,
'password' => true,
'user_type' => true,
]
'[original]' => [
]
'[virtual]' => [
]
'[hasErrors]' => false
'[errors]' => [
]
'[invalid]' => [
]
'[repository]' => 'Users'
protected _accessible => [
'id' => true,
'email' => true,
'password' => true,
'name' => true,
'created' => true,
'modified' => true,
'user_type_id' => true,
'user_type' => true
]
protected _hidden => [
(int) 0 => 'password',
]
protected _fields => [
'name' => 'Test',
'email' => 'test@test.com',
'password' => '$2y$10$13nmS6Iag3seqkau9L.M0Ow.xV0Tasd/y9XNe12xX9yIozsXNLEnO',
'user_type' => object(App\Model\Entity\UserType) id: 1 {},
]
protected _original => [
]
protected _virtual => [
]
protected _dirty => [
'name' => true,
'email' => true,
'password' => true,
'user_type' => true,
]
protected _accessors => [
'App\Model\Entity\User' => [
'set' => [
'password' => '_setPassword',
'Password' => '_setPassword',
'name' => '',
'email' => '',
'user_type' => '',
],
],
]
protected _new => true
protected _errors => [
]
protected _invalid => [
]
protected _registryAlias => 'Users'
}

【问题讨论】:

  • 还有其他更简单的方法可以做到这一点,但这也应该有效,因此可能值得弄清楚发生了什么。尝试使用debug(get_class($this->Users));debug($testUser);(就在save() 调用之前)收集一些上下文。
  • @ndm 我已编辑问题以包含两个 debug() 输出。我也很想听听您所指的这些更简单的方法。谢谢!
  • 天哪,新的调试格式不会产生真正的空白缩进;(无论如何,user_type_id 可能是您之后添加的字段,即在数据库表已经创建之后?
  • 是的,我对调试也有同样的想法 :( 它是后来添加的,是的。但是,如果在实体和表对象中正确描述了它,那又有什么关系呢?呃,我一直都有用 ORM 挑选的骨头
  • 这是相关的,因为 ORM 只会尝试保存架构中存在的那些字段,并且架构默认情况下会被缓存,所以如果您稍后添加了字段并且没有这样做后清除缓存,您的新字段将不会被保存。尝试清除模型缓存 (/tmp/cache/models) 并重试。

标签: cakephp orm entity cakephp-4.x


【解决方案1】:

写@ndm 的评论作为答案,以帮助任何最终遇到同样问题的人。原来我的 ORM 模式在我添加 user_types DB 表之前被缓存了。清除/tmp/cache/models 对我有用。小心缓存!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多