CakePHP 4.1 保存 belongsTo 关联不起作用
CakePHP 4.1 saving belongsTo association doesn't work
我有两个数据库 tables - Users
和 UserTypes
,其中 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
table 中。
为了重现该问题,我在 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 查询没有任何改变。
所以我的问题是,如何插入和更新我的用户实体的外键字段?
---- 编辑 ----
运行 debug(get_class($this->Users))
就在 save()
之前:
APP/Controller/UsersController.php (line 270)
'App\Model\Table\UsersTable'
并且 运行 debug($testUser)
在 save()
之前产生:
APP/Controller/UsersController.php (line 271)
object(App\Model\Entity\User) id:0 {
'name' => 'Test'
'email' => 'test@test.com'
'password' => 'ynmS6Iag3seqkae9L.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' => 'ynmS6Iag3seqkau9L.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'
}
写下@ndm 的评论作为答案,以帮助最终遇到同样问题的任何人。原来我的 ORM 模式在我添加 user_types
数据库 table 之前被缓存了。清除 /tmp/cache/models
对我有用。当心缓存!
我有两个数据库 tables - Users
和 UserTypes
,其中 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
table 中。
为了重现该问题,我在 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 查询没有任何改变。
所以我的问题是,如何插入和更新我的用户实体的外键字段?
---- 编辑 ----
运行 debug(get_class($this->Users))
就在 save()
之前:
APP/Controller/UsersController.php (line 270)
'App\Model\Table\UsersTable'
并且 运行 debug($testUser)
在 save()
之前产生:
APP/Controller/UsersController.php (line 271)
object(App\Model\Entity\User) id:0 {
'name' => 'Test'
'email' => 'test@test.com'
'password' => 'ynmS6Iag3seqkae9L.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' => 'ynmS6Iag3seqkau9L.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'
}
写下@ndm 的评论作为答案,以帮助最终遇到同样问题的任何人。原来我的 ORM 模式在我添加 user_types
数据库 table 之前被缓存了。清除 /tmp/cache/models
对我有用。当心缓存!