学说收集标准 isNull

Posted

技术标签:

【中文标题】学说收集标准 isNull【英文标题】:Doctrine collection criteria isNull 【发布时间】:2018-10-09 23:45:07 【问题描述】:

我有一个用户实体,我尝试通过与用户组的多对多关系加入它。它工作正常,但我尝试过滤加入的实体,因为我使用了例如 softdelete 字段。

class User

    // ...

    /**
     * @ORM\ManyToMany(targetEntity="\UserBundle\Entity\UserGroup")
     * @ORM\JoinTable(name="users_groups",
     *      joinColumns=@ORM\JoinColumn(name="user_id", referencedColumnName="id"),
     *      inverseJoinColumns=@ORM\JoinColumn(name="group_id", referencedColumnName="id")
     * )
     */
    protected $groups;

    public function getGroups()
    
        return $this->groups->matching(Criteria::create()->where(Criteria::expr()->isNull('te.deleted_at')));
    

    // ...

问题:如果条件包含任何空值,则原则不会将其用于 sql 查询。这意味着,在此示例中,SELECT 语句在 where 中不包含任何“deleted_at IS NULL”。

我找到了原因,因为学说在SqlValueVisitor.php中过滤了它

if (($operator === Comparison::EQ || $operator === Comparison::IS) && $value === null) 
    return;
 else if ($operator === Comparison::NEQ && $value === null) 
    return;

好的,但是这个问题的解决方案是什么?或者如果我使用doctrine2,我无法过滤空字段?

我知道,我可以使用学说过滤器,但我不想要,因为在我的例子中(在这个例子中)它很简单,但是我从代码中动态地构建了这个过滤器。

【问题讨论】:

过滤集合时应该查看ClosureExpressionVisitor,而不是SqlValueVisitor。您的 getter 与执行的 SQL 查询无关(SQL fetch 在您的代码甚至被调用之前由代理类中的 getter 触发),如果您想发出自定义查询来获取您的实体,您必须在自定义存储库类。 对不起,但我不明白,因为如果我将 isnull 例如更改为 ->gt('te.id','1') 那么 SQL 查询将包含此条件。所以问题是,为什么不将它包含在 isnull 标准中,或者我如何将任何 IS NULL 放入 sql,例如 ->gt 或任何其他标准?在 ->gt 中查询输出为:SELECT te.name AS name, te.roles AS roles, te.id AS id, te.created_at AS created_at, te.updated_at AS updated_at, te.deleted_at AS deleted_at, te.undeletable AS undeletable FROM user_group te JOIN users_groups t ON t.group_id = te.id WHERE t.user_id = ? AND te.id > ? 【参考方案1】:

你可以试试

public function getGroups()

    return $this->groups->matching(Criteria::create()->where(Criteria::expr()->neq('deleted_at', null)));

【讨论】:

它仅在我使用 EAGER 时才有效(如果我不使用,它将返回所有组),并且 sql 查询不包含它只是 php 侧过滤。所以它不起作用:( @esemve 关系过滤不能在一个 sql 查询中完成。我的意思是你不能在过滤用户组的同时选择用户和用户组,因为这也会过滤用户。所以要么你在php端过滤它,要么做2个查询,第一个选择用户,第二个选择选定用户的未删除用户组。【参考方案2】:

很遗憾,您不能将Criteria::expr()->isNull() 与ManyToMany 关系一起使用。在教义/orm GitHub 存储库中有几个长期存在的问题 - 1、2。

作为一种解决方法,您可以像这样手动过滤掉空值:

$this->groups->filter(function ($group) 
    return null === $group->getDeletedAt();
);

尽管您必须注意,这将从数据库中加载 所有 用户用户组,并通过过滤器函数将它们传递给每个用户。与 ->matching() 方法相反,它构建 SQL 查询并且不会加载任何已删除的用户组。

【讨论】:

以上是关于学说收集标准 isNull的主要内容,如果未能解决你的问题,请参考以下文章

与学说映射学说 2 的关联失败

如何在学说中编写联合查询?

学说 ORM 和继承

学说 targetEntity 接口

Symfony/学说

基于模型实例获取学说结果