我有一个Orders
和一个Users
表,例如Orders
belongsTo
Users
。
我希望用户能够软删除其帐户,因此我添加了一个删除字段并修改了删除方法。用户信息出于管理目的是必需的,因此无需硬删除。
我还覆盖了UsersTable
的默认查找程序,以使已删除的用户不会在列表中或Users->get()
的结果中弹出:
public function findAll(Query $query, array $options)
{
return $query->where(['Users.deleted' => false]);
}
我对它的工作方式感到满意,大多数情况下,我现在不能忘记排除已删除的用户,因为默认查找程序已经可以完成工作。
问题是当订单中包含用户时,我仍要包括该用户:
$order = $this->Orders->get($id, ['contain' => 'Users']);
显然,在使用contain()findAll()
时,因为它不包括已删除的用户。
我如何仍将软删除的实体包括在contain()
中?
是否可以为容器设置其他默认查找器?
答案 0 :(得分:1)
例如,您可以对包含使用finder
选项,以指定要使用的查找程序,例如:
$this->Orders->get($id, [
'contain' => [
'Users' => [
'finder' => 'withDeleted'
]
]
]);
或直接修改查询:
$this->Orders->get($id, [
'contain' => [
'Users' => function (\Cake\ORM\Query $query) {
return $query->find('withDeleted');
}
]
]);
另请参见 Cookbook > Database Access & ORM > Query Builder > Passing Conditions to Contain
但是任何自定义查找器都会绕开您修改后的all
查找器,这表明您的方法存在缺陷,一旦查询使用其他查找器,并且未明确使用{ {1}}查找程序,您的条件将不会被应用,您很可能不希望如此轻易地发生这种情况。
更好的方法可能是使用all
事件/回调。这是一个使用选项方法的基本示例,非常严格:
Model.beforeFind
这将确保仅当存在public function beforeFind(\Cake\Event\Event $event, \Cake\ORM\Query $query, \ArrayObject $options)
{
if (!isset($options['findWithDeleted']) ||
$options['findWithDeleted'] !== true
) {
$query->where(['Users.deleted' => false]);
}
}
public function findWithDeleted(\Cake\ORM\Query $query, array $options)
{
return $query->applyOptions(['findWithDeleted' => true]);
}
选项并将其设置为findWithDeleted
时,该条件才会适用。
您可能还想看看可以解决此问题的插件,例如 https://github.com/usemuffin/trash 。