渴望用Sonata列表视图获取

时间:2014-12-11 17:38:24

标签: doctrine-orm sonata-admin

我使用SonataAdminSonataDoctrineORMAdmin捆绑来管理实体。

问题是我无法弄清楚如何在列表视图中急切获取相关实体,并且随着列出的实体数量的增加,执行的查询数量也会迅速增加。

我尝试添加`fetch =" EAGER"对于关系注释,但是配置文件显示Sonata无论如何都会执行单独的查询。

这是一段关系代码:

  • 发布

    <?php
    namespace Acme\AppBundle\Entity;
    
    use Doctrine\ORM\Mapping as ORM;
    use Doctrine\Common\Collections\ArrayCollection;
    
    /**
     * @ORM\Table()
     * @ORM\Entity
     */
    class Post
    {
        /**
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /**
         * @ORM\Column(name="name", type="string", length=255)
         **/
        private $name;
    
        /**
         * @ORM\ManyToMany(targetEntity="Acme\AppBundle\Entity\Tag", fetch="EAGER")
         * @ORM\JoinTable(name="join_post_to_tag",
         *      joinColumns={@ORM\JoinColumn(name="post_id", referencedColumnName="id")},
         *      inverseJoinColumns={@ORM\JoinColumn(name="tag_id",     referencedColumnName="id")}
         *      )
         **/
        private $tags;
    
        public function getId()
        {
            return $this->id;
        }
    
        public function setName($names)
        {
            $this->name = $name;
            return $this;
        }
    
        public function getName()
        {
            return $this->name;
        }
    
        public function setTags($tags)
        {
            $this->tags = $tags;
    
            return $this;
        }
    
        public function __toString()
        {
            return $this->getName();
        }
    }
    
  • 标签

    <?php
    namespace Acme\AppBundle\Entity;
    use Doctrine\ORM\Mapping as ORM;
    
    /**
     * @ORM\Table()
     * @ORM\Entity
     */
    class Tag
    {
        /**
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
    
        /**
         * @ORM\Column(name="value", type="string", length=255)
         */
        private $value;
    
        public function getId()
        {
            return $this->id;
        }
    
        public function setValue($value)
        {
            $this->value = $value;
            return $this;
        }
    
        public function getValue()
        {
            return $this->value;
        }
    
        public function __toString()
        {
            return ($this->getValue()) ? : '';
        }
    }
    

运行的第一个相关查询是获取所有帖子:

SELECT DISTINCT p0_.id AS id0, p0_.id AS id1 
FROM Post p0_ 
  LEFT JOIN join_post_to_tag j1_ ON p0_.id = j1_.post_id 
  LEFT JOIN Tag p1_ ON p1_.id = j1_.target_id 
ORDER BY p0_.id ASC

但这不会获取相关标签,即使它确实如此,它仍会再次查询:

SELECT t0.id AS id1, t0.value AS value2 
FROM Tag t0 
  INNER JOIN join_post_to_tag ON t0.id = join_post_to_tag.tag_id 
WHERE join_post_to_tag.post_id = ?

我试图弄乱管理类中的createQuery方法,但无法真正找到使相关实体正确获取的方法。

有没有办法强制列表视图急切地获取所需的相关实体?

1 个答案:

答案 0 :(得分:1)

您使用createQuery($ context)方法走在正确的轨道上。 我已经实现了以下的热切加载:

public function createQuery($context = 'list')
    {
        $query = parent::createQuery($context); // let sonata build it's default query for the entity

        $rootEntityAlias = $query->getRootAlias(); // get the alias defined by sonata for the root entity

        $query->join($rootEntityAlias.'.relationFieldName', 'relationFieldAlias'); // manualy define the join you need
        $query->addSelect('relationFieldAlias'); // this is the key line. It is not enough to join a table. You have to also add it to the select list of the query, so that it's actualy fetched

        // $query->join(...) // repeat the process of joining and selecting for each relation field you need
        // $query->addSelect(...)

        return $query; // return the altered query to sonata. this will only work for the "list" action.
    }

如果您在使用此功能时遇到问题,请与我联系:)

关于这个主题的进一步阅读:
SO question

docs