学说收集标准 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的主要内容,如果未能解决你的问题,请参考以下文章