У меня есть 2 сущности – авторы и книги, у одного автора может быть много книг. Я хочу показать в таблице, сколько книг у КАЖДОГО автора (разное количество на каждого автора). Я уже видел этот вопрос, и это , и это, и пробовал это, поскольку я думал, что это будет более элегантное решение:
<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();
EDIT: моя петля
<tbody> {% for authors in author %} <tr> <td>{{ authors.name }}</td> <td>{{ authors.isactive }}</td> <td>{{ books.authorid|length}}</td> </tr> {% endfor %} </tbody>
EDIT 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: { }
Вам не нужно брать все книги для этого, поэтому, если вы не используете массив всех книг в системе где-то еще на этой странице, я бы удалил этот запрос (и посмотрел параметр).
Тогда я начну чистить некоторые названия.
AB\ProjectBundle\Entity\Books: ... manyToOne: authorid: targetEntity: Author
Сущность – это рецепт того, как ваше приложение будет обрабатывать одну вещь, поэтому мы пойдем с уникальными именами
Когда вы создаете отношения в Доктрине, вам (обычно) не нужно настраивать свои собственные таблицы соединений или вообще не думать о внешних ключах (ids). Отношения имеют гораздо больший смысл для обозначения сущностью (как и в документах)
Таким образом, вышеизложенное должно быть
AB\ProjectBundle\Entity\Book: ... manyToOne: author: targetEntity: Author
У вашего автора отсутствует связь с объектом Book
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 – опять же, поскольку мы получаем авторов, а не массив идентификаторов. Мы присоединяемся к книгам (через отношение в объекте Author, называемом «books»), чтобы не допустить, чтобы Doctrine запускал один или несколько отдельных запросов позже (отношения lazy загружаются, если они не объединены).
Тогда в 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 %}
был просто неправильным. Может показаться тривиальным или глупым указать, но писать чистый и понятный код очень важно, чтобы помочь другим (и самому себе) понять, что происходит на самом деле. Если я прочитаю «авторы», то я ожидаю массив авторов, а не объект, содержащий информацию одного автора.