【问题标题】:Symfony entity repository with many-to-many relationship具有多对多关系的 Symfony 实体存储库
【发布时间】:2015-09-22 13:10:45
【问题描述】:

我有两个实体productdocument,它们通过many-to-many 关系与JOIN 表相关联。我的产品实体如下所示,我的文档实体目前没有对产品的引用。

/**
 * @ORM\Entity
 * @ORM\Table(name="product")
 * @ORM\Entity(repositoryClass="\MyApp\CmsBundle\Repository\ProductRepository")
 */
class Product
{
    // ...

    /**
     * @ManyToMany(targetEntity="Document")
     * @JoinTable(name="products_documents",
     *      joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="document_id", referencedColumnName="id")}
     *      )
     **/
     protected $documents;

     // ...

     public function __construct()
     {
         $this->documents = new ArrayCollection();
     }

    public function addDocument(Document $document)
    {
        $this->documents[] = $document;

        return $this;
    }

    public function removeDocument(Document $document)
    {
        $this->documents->removeElement($document);
    }

    public function getDocuments()
    {
        return $this->documents;
    }

当我在网站的前端展示产品时,我还会列出它的文档。但是我需要能够根据它们的属性statusprivacy 过滤掉它们。

所以我一直在尝试创建一个实体存储库来处理此逻辑,但到目前为止我尝试的一切都失败了。我需要实现的是与此类似的查询,但采用 Symfony/Doctrine 格式:

SELECT d.*
FROM documents d, products_documents pd,
WHERE pd.product_id = :product_id
  AND pd.document_id = d.id,
  AND d.status = 'PUBLISHED',
  AND d.privacy = 'PUBLIC';

理想情况下,我希望能够从我的控制器中做这样简单的事情:

// get documents to display on front-end
$documents = $em->getRepository('MyAppCmsBundle:Product')->getDocumentsForProduct($product);

我已经调用了函数,只是不知道如何检索我想要的数据。

更新

这是我到目前为止所得到的,同时维护工作代码,但不是返回文档,而是返回所有产品。我不确定如何将条件添加到我传入的产品中,或者返回文件而不是产品。

ProductRepository.php

public function getDocumentsForProduct(Product $product, $authenticated = false)
{
    $query = $this->createQueryBuilder('p')
    ->join('MyApp\CmsBundle\Entity\Document', 'd')
    ->where('d.status = :status')
    ->andWhere('d.privacy = :privacy')
    ->setParameters(array(
        'status' => 'PUBLISHED',
        'privacy' => 'PUBLIC',
    ))
    ->getQuery();

    return $query->getResult();
}

【问题讨论】:

  • 用您的 dql 查询更新您的问题。它应该像对文档进行连接然后应用相同的 where 子句一样简单。
  • @Cerad 我已经用我目前已经实现的内容对其进行了更新,但这不是一个完整的解决方案。
  • 您需要添加 where 条件以将内容限制为仅一种产品。然后返回 $product->getDocuments();您还想添加一个 select('d') 以避免延迟加载文档。查看有关如何构建 dql 的文档。这是有效使用 Doctrine 2 的关键部分。值得花时间了解正在发生的事情。
  • 对不起,我没有关注。我可以在实体上调用$product->getDocuments(),但它会返回所有文档,而不是我想要过滤的文档。

标签: php sql symfony doctrine repository


【解决方案1】:

如果你想让它返回文档,你应该把它放在你的 DocumentRepository 中。

“createQueryBuilder”方法自动选择属于存储库的类型的实体。所以在你的情况下,这就是产品。如果您将相同的代码放在 DocumentRepository 中,您应该会获得 Document 实体。

我不知道是否有办法使用 QueryBuilder 来改变这一点。但是您可以像这样使用 DQL:

$this->getEntityManager()->createQuery('SELECT p FROM YourBundle:Document WHERE ...');

【讨论】:

  • 我会试一试,我最初确实尝试使用DocumentRepository,但在那里也遇到了麻烦。
  • 我已经做到了这一点:$this->getEntityManager()->createQuery('SELECT d FROM MyAppCmsBundle:Document d WHERE d.status = :status AND d.privacy = :privacy')->setParameters(array('status' => 'PUBLISHED', 'privacy' => 'PUBLIC')); - 不确定在哪里/如何指定产品关系。
  • 在 SELECT 语句之后:JOIN d.product p 但是您可能必须为此添加对产品的引用,或者使用“ON”子句。请参阅教义手册。
  • productdocument 上不存在,但这是问题之一。 Document has no association named product
  • K mate,我想现在明白了。我不得不将 ORM 映射的类型更改为 many-to-many bidirectional
猜你喜欢
  • 1970-01-01
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 2015-08-04
  • 2012-03-04
相关资源
最近更新 更多