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

时间:2016-03-27 17:15:11

标签: php symfony

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

<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.orm.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.orm.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: {  }

1 个答案:

答案 0 :(得分:3)

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

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

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()等方法,这些方法可以正确描述它们的作用以及您可以期望返回的内容。< / p>

有了这种关系,这应该就像:

选择您想要的作者:

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

注意$ authors而不是$ authorids - 因为我们得到了作者而不是一组id。我们加入书籍(通过作者实体中的关系称为&#34; books&#34;)以避免强迫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 %}只是错误的方法。可能看起来似乎微不足道或愚蠢,但编写干净且易于理解的代码对于帮助其他人(以及您自己)理解实际发生的事情是非常重要的。如果我读过&#34;作者&#34;然后我期待一组作者,而不是一个包含一位作者信息的对象。