Symfony2统计与另一个实体相关的实体字段


Symfony2 count entity fields that relate to another entity

我有两个实体——作者和图书,一个作者可能有很多书。我想在表格中显示每个作者有多少本书(每个作者有不同的数量)。我已经看到了这个问题,这个,这个,并尝试了这个,因为我认为这将是一个更优雅的解决方案:

<td>{{books|length}}</td>

但每次我都会得到所有作者的书籍总数。在我的控制器中,我得到了这样的书:

$query = $em->createQuery('SELECT b FROM AB'ProjectBundle'Entity'Books u WHERE b.authorid in (:authorids)');
$query->setParameter('authorid',$authorids);
$books = $query->getResult();

作者是这样选择的:

$query = $em->createQuery('SELECT a FROM AB'ProjectBundle'Entity'Authors a');
$authorids = $query->getResult();

编辑:我的树枝环

<tbody>
            {% for authors in author %}
        <tr>
            <td>{{ authors.name }}</td>
            <td>{{ authors.isactive }}</td>         
            <td>{{ books.authorid|length}}</td>
        </tr>
            {% endfor %}
</tbody>

编辑2我的作者实体

class Author
{
    /**
     * @var integer
     */
    private $id;
    /**
     * @var string
     */
    private $name;
    /**
     * Set name
     *
     * @param string $name
     * @return string
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }
    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }
    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
}

编辑3图书实体

<?php
namespace AB'ProjectBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
/**
 * 
 */
class Books
{
    /**
     * @var integer
     */
    private $id;
    /**
     * @var string
     */
    private $name;
    /**
     * @var 'AB'ProjectBundle'Entity'Author
     */
    private $authorid;
    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set Authorid
     *
     * @param 'AB'ProjectBundle'Entity'Author $authorid
     * @return Author
     */
    public function setAuthorid('AB'ProjectBundle'Entity'Author $authorid = null)
    {
        $this->authorid = $authorid;
    return $this;
    }
    /**
     * Get Authorid
     *
     * @return 'AB'ProjectBundle'Entity'Author
     */
    public function getAuthorid()
    {
        return $this->authorid;
    }
    /**
     * Set name
     *
     * @param string $name
     * @return string
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }
    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
}

没有注释,实体映射在*.orm.yml文件中。Book.org.yml:

AB'ProjectBundle'Entity'Books:
type: entity
table: Books
id:
    id:
        type: integer
        nullable: false
        unsigned: false
        id: true
        generator:
            strategy: IDENTITY
fields:
    name:
        type: text
        nullable: false
manyToOne:
    authorid:
        targetEntity: Author
        cascade: {  }
        mappedBy: null
        inversedBy: null
        joinColumns:
            authorid:
                referencedColumnName: id
        orphanRemoval: false
lifecycleCallbacks: {  }

Author.orgm.yml

AB'ProjectBundle'Entity'Author:
type: entity
table: Author
id:
    id:
        type: integer
        nullable: false
        unsigned: false
        id: true
        generator:
            strategy: IDENTITY
fields:
    name:
        type: text
        nullable: false
lifecycleCallbacks: {  }

您不需要为此获取所有书籍,因此如果您不在此页面的其他位置使用系统中所有书籍的数组,我会删除该查询(并查看参数)。

然后我会开始清理一些命名。

AB'ProjectBundle'Entity'Books:
...
manyToOne:
    authorid:
        targetEntity: Author

实体是你的应用程序如何处理一件事的配方,所以我们将使用单数名称

当你在Doctrine中创建关系时,你(通常)根本不需要建立自己的联接表或考虑外键(id)。按实体命名关系更有意义(就像在文档中一样)

所以上面应该是

AB'ProjectBundle'Entity'Book:
...
manyToOne:
    author:
        targetEntity: Author

您的作者实体缺少与图书实体的关系

AB'ProjectBundle'Entity'Author:
...
oneToMany:
    books:
        targetEntity: Book

注意,我们在一个实体中与单数名称有关系,而在另一个实体上与复数名称有关系。这些名字很有道理,因为一个作者可以有很多书,但一本书只能属于一个作者。

因此,在你的应用程序中(如果你从这些映射中生成实体),你会得到像$book->getAuthor()$author->getBooks()这样的方法,它们正确地描述了它们的作用以及你可以期望返回的内容。


有了关系,这应该很简单:

选择您想要的作者:

$query = $em->createQuery('SELECT a, b FROM AB'ProjectBundle'Entity'Authors a JOIN a.books b');
$authors = $query->getResult();

注意$authors而不是$authorids——同样,因为我们得到的是authors,而不是id数组。我们加入书籍(通过Author实体中名为"书籍"的关系),以避免迫使Doctrine稍后运行一个或多个单独的查询(如果不加入关系,则关系将延迟加载)。

然后在Twig中,我们只需进行

 <tbody>
        {% for author in authors %}
    <tr>
        <td>{{ author.name }}</td>
        <td>{{ author.isactive }}</td>         
        <td>{{ author.books|length}}</td>
    </tr>
        {% endfor %}
 </tbody>

这里最后一点命名更改{% for authors in author %}只是错误的方式。指出这一点可能显得微不足道或愚蠢,但编写干净易懂的代码对于帮助他人(和你自己)了解实际情况是至关重要的。如果我读"authors",那么我期待的是一组作者,而不是一个包含一个作者信息的对象。