CakePHP 3-如何仍然包含()软删除的实体?

时间:2019-08-07 13:40:15

标签: cakephp orm cakephp-3.0 soft-delete

我有一个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()中?

是否可以为容器设置其他默认查找器?

1 个答案:

答案 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