CakePHP 3 - 如何仍然包含()软删除的实体?
CakePHP 3 - How to still contain() soft-deleted entities?
我有一个 Orders
和一个 Users
table,这样 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()
中包含软删除的实体?
是否可以为包含设置不同的默认查找器?
例如,您可以使用 contain 的 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
查找器,这表明您的方法存在缺陷,一旦查询使用不同的查找器,并且不会也明确使用 all
查找器,您的条件将不会应用,您很可能不希望如此轻易地发生。
更好的方法可能是使用 Model.beforeFind
event/callback。这是一个使用选项方法的基本的、相当严格的示例:
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
选项并设置为 true
时,才不会应用该条件。
您可能还想看看可以处理此问题的插件,例如 https://github.com/usemuffin/trash.
我有一个 Orders
和一个 Users
table,这样 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()
中包含软删除的实体?
是否可以为包含设置不同的默认查找器?
例如,您可以使用 contain 的 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
查找器,这表明您的方法存在缺陷,一旦查询使用不同的查找器,并且不会也明确使用 all
查找器,您的条件将不会应用,您很可能不希望如此轻易地发生。
更好的方法可能是使用 Model.beforeFind
event/callback。这是一个使用选项方法的基本的、相当严格的示例:
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
选项并设置为 true
时,才不会应用该条件。
您可能还想看看可以处理此问题的插件,例如 https://github.com/usemuffin/trash.