cakephp 3 保存实体,尽管 request-data 为空
cakephp 3 saves entity although request-data is null
我正在使用 cakephp 3 开发 REST api,我发现了一个奇怪的行为。
我更改了 routes.config,因此 .json, .xml
请求是可能的。我还在控制器初始化方法中加载了 RequestHandler
组件。
我在 UsersController() 中的注册操作
public function register()
{
$message = array('code' => '200', 'message' => 'The user could not be saved. Please, try again.');
$user = $this->Users->newEntity($this->request->data);
if ($this->request->is('post')) {
if ($this->Users->save($user)) {
$message = array('code' => '100', 'message' => 'The user has been registred');
}
}
$this->set([
'message' => $message,
'user' => $user,
'_serialize' => ['message', 'user']
]);
}
模型验证:
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create');
$validator
->requirePresence('username', 'create');
$validator
->notEmpty('username', 'A username is required')
->add('username', [
'length' => [
'rule' => ['minLength', 3],
'message' => 'Username need to be at least 3 characters long',
]
])
->notEmpty('password', 'A password is required')
->add('password', [
'length' => [
'rule' => ['minLength', 3],
'message' => 'Password need to be at least 3 characters long',
]
]);
return $validator;
}
问题:
如果我发出内容为 header application/x-www-form-urlencoded
的 post 请求,一切正常,将保存一个新用户并考虑验证规则。但是,如果我发出 post 请求,例如内容 header application/json
,则会保存一个空用户。原因是 $this->request->data
为空。但是为什么cakephp会保存空用户呢? (在数据库中用户名和密码被声明为非空)
通过 null
不会触发验证
newEntity()
的第一个参数是可选的,因此当传递 null
时,就像您根本没有传递任何东西一样,导致创建了一个全新的空实体,即不会被验证。
这就是为什么你不应该在那里做你正在做的事情的原因之一,你不应该将请求数据传递给 newEntity()
,而是在使用 [=14 创建的实体上使用 patchEntity()
=] 相反,就像在 bake shell.
生成的代码中所做的一样
// ...
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
// ...
}
}
// ...
这样传递 null
将不会被接受,而是会导致错误,因为参数是必需的,并且必须是一个数组。
我想文档需要更新以反映这一点。
使用额外的 application/table 规则
除了在 creating/updating 实体时验证数据外,还有 application/table 规则,这些规则将在保存数据之前的任何情况下应用。使用这些规则,无论实体是如何创建的,您都可以防止此类有问题的保存操作。
这是一个非常基本的示例,用于测试字段是否为“空”:
public function buildRules(RulesChecker $rules)
{
$rules->add(function ($entity, $options) {
return !empty($entity->get('field'));
});
return $rules;
}
另见 Bookbook > ORM > Saving Data > Applying Application Rules
完全防止 null
被使用
如果 null
是预期值,即在某些情况下它恰好为 null 是有效的,那么您甚至可能想要添加适当的预防措施并测试数据是否为 null
在尝试使用它之前。
为什么插入的记录虽然列显示 NOT NULL
?
好吧,这很容易解释,ORM 生成的 INSERT
查询将仅包含实体的脏字段(已更改),默认情况下仅包含自动更新的字段Timestamp
行为,因此插入一个空实体可能会导致类似
的结果
INSERT INTO table (created, modified) VALUES ('2015-05-06 11:34:49', '2015-05-06 11:34:49')
根据您的 DBMS 和配置,这不会产生任何错误,例如 MySQL 将在严格模式下不 运行 时将未传递的列设置为其隐式默认值,因此您d 只有在为特定 NOT NULL
列传递实际值 NULL
的情况下才会收到错误。
我正在使用 cakephp 3 开发 REST api,我发现了一个奇怪的行为。
我更改了 routes.config,因此 .json, .xml
请求是可能的。我还在控制器初始化方法中加载了 RequestHandler
组件。
我在 UsersController() 中的注册操作
public function register()
{
$message = array('code' => '200', 'message' => 'The user could not be saved. Please, try again.');
$user = $this->Users->newEntity($this->request->data);
if ($this->request->is('post')) {
if ($this->Users->save($user)) {
$message = array('code' => '100', 'message' => 'The user has been registred');
}
}
$this->set([
'message' => $message,
'user' => $user,
'_serialize' => ['message', 'user']
]);
}
模型验证:
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create');
$validator
->requirePresence('username', 'create');
$validator
->notEmpty('username', 'A username is required')
->add('username', [
'length' => [
'rule' => ['minLength', 3],
'message' => 'Username need to be at least 3 characters long',
]
])
->notEmpty('password', 'A password is required')
->add('password', [
'length' => [
'rule' => ['minLength', 3],
'message' => 'Password need to be at least 3 characters long',
]
]);
return $validator;
}
问题:
如果我发出内容为 header application/x-www-form-urlencoded
的 post 请求,一切正常,将保存一个新用户并考虑验证规则。但是,如果我发出 post 请求,例如内容 header application/json
,则会保存一个空用户。原因是 $this->request->data
为空。但是为什么cakephp会保存空用户呢? (在数据库中用户名和密码被声明为非空)
通过 null
不会触发验证
newEntity()
的第一个参数是可选的,因此当传递 null
时,就像您根本没有传递任何东西一样,导致创建了一个全新的空实体,即不会被验证。
这就是为什么你不应该在那里做你正在做的事情的原因之一,你不应该将请求数据传递给 newEntity()
,而是在使用 [=14 创建的实体上使用 patchEntity()
=] 相反,就像在 bake shell.
// ...
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data);
if ($this->Users->save($user)) {
// ...
}
}
// ...
这样传递 null
将不会被接受,而是会导致错误,因为参数是必需的,并且必须是一个数组。
我想文档需要更新以反映这一点。
使用额外的 application/table 规则
除了在 creating/updating 实体时验证数据外,还有 application/table 规则,这些规则将在保存数据之前的任何情况下应用。使用这些规则,无论实体是如何创建的,您都可以防止此类有问题的保存操作。
这是一个非常基本的示例,用于测试字段是否为“空”:
public function buildRules(RulesChecker $rules)
{
$rules->add(function ($entity, $options) {
return !empty($entity->get('field'));
});
return $rules;
}
另见 Bookbook > ORM > Saving Data > Applying Application Rules
完全防止 null
被使用
如果 null
是预期值,即在某些情况下它恰好为 null 是有效的,那么您甚至可能想要添加适当的预防措施并测试数据是否为 null
在尝试使用它之前。
为什么插入的记录虽然列显示 NOT NULL
?
好吧,这很容易解释,ORM 生成的 INSERT
查询将仅包含实体的脏字段(已更改),默认情况下仅包含自动更新的字段Timestamp
行为,因此插入一个空实体可能会导致类似
INSERT INTO table (created, modified) VALUES ('2015-05-06 11:34:49', '2015-05-06 11:34:49')
根据您的 DBMS 和配置,这不会产生任何错误,例如 MySQL 将在严格模式下不 运行 时将未传递的列设置为其隐式默认值,因此您d 只有在为特定 NOT NULL
列传递实际值 NULL
的情况下才会收到错误。