多对多关系的原则约束

Doctrine Constraint on a Many-to-Many Relation

我们有一个实体 'User',它与不同的 'Types' 具有多对多关系。 MySQL 关系是通过交叉 Table.

处理的
class User {

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Type")
     * @ORM\JoinTable(name="user_type",
     *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="type_id", referencedColumnName="id")}
     * )
     */
    protected $types;

}



class Type {

     /**
     * @ORM\ManyToMany(targetEntity="App\Entity\User")
     * @ORM\JoinTable(name="user_type",
     *      joinColumns={@ORM\JoinColumn(name="type_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
     * )
     */
    protected $users;

     /**
     * @ORM\Column(type="datetime")
     */
    protected $publishedAt;

}


如何将这种多对多关系中的响应限制为仅显示已发布的类型?

那是事实SQL 应该包括一个WHERE 来过滤尚未发布的相应项目。我可以用注释或类似的东西来做到这一点吗?

我知道我可以通过过滤返回的集合来做到这一点。但是还有比这更有效的吗?

这个问题有点重复。 这里已经回答了:php - Doctrine2 association mapping with conditions - Stack Overflow

其中一条评论指出,这会导致多对多关系错误。从 Doctrine 2.5 开始,情况不再如此。

所以你可以在学说中做的是在请求关系的实体时交出查询条件:

所以您不更改 注释,而是更改实体的 getter:


class User {

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Type")
     * @ORM\JoinTable(name="user_type",
     *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="type_id", referencedColumnName="id")}
     * )
     */
    protected $types;

    public function getTypes()
    {
        $criteria = Criteria::create()->where(Criteria::expr()->lte('publishedAt', date('Y-m-d')));
        return $this->types->matching($criteria);
    }


}

这将导致所需项目的延迟获取(取决于您的设置)。所有的教义魔法仍然有效,比如缓存之类的。所以集合只会被取回,如果没有被取回...

您可以使用 Criteria。 向您的 User class 添加一个名为 getPublishedTypes.

的函数
public function getPublishedTypes()
{
    return $this->getTypes()->matching(TypeRepository::createPublishedCriteria());
}

然后在您的 TypeRepository 中添加函数 createPublishedCriteria

static public function createPublishedCriteria()
{
    return Criteria::create()
        ->andWhere(Criteria::expr()->lte('publishedAt', date('Y-m-d')); //your logic
}

注意: 函数必须是静态的

您也可以稍后在您的查询构建器中使用该条件,并使用以下行 $qb->addCriteria(self::createPublishedCriteria()).


另一种有不良做法的解决方案可能是集合过滤。添加您的用户 class:

public function getPublishedTypes()
{
    return $this->getTypes()->filter(function(Type $type) {
        return $type->getPublishedAt < date('Y-m-d');
}

这个版本不是很好,因为它会产生更多的查询(对数据库中的大数据不利)。