Intereting Posts
Использование javascript history.back () не работает в Safari .. как мне сделать его кросс-браузер? Как сделать маршрут Catch-All в Laravel 5.2 Как изменить пароль для отправки сообщения электронной почты в laravel? Отправка больших пакетов с использованием php с помощью socket_write Автоматическое увеличение на 1 в MySQL с помощью clearDB Как развернуть RFC 822 php проверяет несколько дат в массиве в пределах диапазона дат Чтение определенной строки файла в PHP Обнаружение мобильного или настольного браузера и перенаправление на соответствующую веб-страницу Как установить PHP для загрузки файла в конкретный каталог? Предотвращение прямого доступа к изображениям с использованием URL-адреса браузера TokenMismatchException в строке VerifyCsrfToken.php 67 при загрузке видео Объединить несколько строк HTML в одном с PHP? Линейные разрывы, вызванные метками P и BR PHP curl_getinfo ($ ch, CURLINFO_CONTENT_TYPE) не возвращает кодировку Включить проект github в плагин wordpress

Использование EntityRepository :: findBy () с отношениями «многие-ко-многим» приведет к E_NOTICE в Доктрине

Для проекта Symfony2 мне пришлось создать связь между сообщением в блоге и так называемыми платформами. Платформа определяет определенный фильтр на основе домена, который вы используете для просмотра сайта. Например: если вы присоединитесь к сайту по url first-example.com, сайт будет предоставлять только сообщения в блогах, которые связаны с этой конкретной платформой.

Для этого я создал два объекта Post и Platform. Впоследствии я сопоставил их вместе со многими отношениями «многие-ко-многим». Я пытаюсь получить данные через это отношение «Многие ко многим» из встроенной функции findBy() в EntityRepository Doctrines.

 // every one of these methods will throw the same error $posts = $postRepo->findBy(array('platforms' => array($platform))); $posts = $postRepo->findByPlatforms($platform); $posts = $postRepo->findByPlatforms(array($platform)); 

Где $postRepo – это правильный репозиторий для объекта Post и $platform – существующий объект Platform .
В любом случае: я получаю следующую ошибку:

 ErrorException: Notice: Undefined index: joinColumns in [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1495 [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1495 [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1452 [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1525 [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:1018 [...]/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:842 [...]/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:157 [...]/src/Foobar/BlogBundle/Tests/ORM/PostTest.php:102 

Возможно ли вообще получить связанные связи в отношениях «многие-ко-многим», или я вынужден самостоятельно написать эти функции? Странная вещь: Doctrine не будет делать никаких ошибок, таких как: «Это невозможно», но внутренний E_NOTICE . Вот почему я палач, чтобы думать, что это должно быть возможно, но я упускаю некоторые моменты здесь.

Разделенные на интересные части, эти Сущности выглядят так.

 <?php namespace Foobar\CommunityBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; // [...] other namespace stuff /** * @ORM\Entity(repositoryClass="Foobar\CommunityBundle\Entity\Repository\PlatformRepository") * @ORM\Table(name="platforms") */ class Platform { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; // [...] other field stuff } 
 <?php namespace Foobar\BlogBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; // [...] other namespace stuff /** * @ORM\Entity(repositoryClass="Foobar\BlogBundle\Entity\Repository\PostRepository") * @ORM\Table(name="posts") */ class Post implements Likeable, Commentable, Taggable, PlatformAware { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @ORM\ManyToMany(targetEntity="Foobar\CommunityBundle\Entity\Platform", cascade={"persist"}) * @ORM\JoinTable(name="map_post_platform", * joinColumns={@ORM\JoinColumn(name="post_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="platform_id", referencedColumnName="id")} * ) */ protected $platforms; // [...] other fields /** * Constructor */ public function __construct() { // [...] $this->platforms = new ArrayCollection(); } } 

И, конечно же, файл composer.json (также разделенный на соответствующие строки)

 { [...] "require": { "php": ">=5.3.3", "symfony/symfony": "2.1.*", "doctrine/orm": ">=2.2.3,<2.4-dev", "doctrine/doctrine-bundle": "1.0.*", "doctrine/doctrine-fixtures-bundle": "dev-master", [...] }, [...] } 

Это очень возможно, но хранилище Doctrine Repository не работает таким образом.

У вас есть два варианта, в зависимости от вашего контекста:

Напишите пользовательский метод в репозитории.

 class PostRepository extends EntityRepository { public function getPosts($id) { $qb = $this->createQueryBuilder('p'); $qb->join('p.platform', 'f') ->where($qb->expr()->eq('f.id', $id)); return $qb; } } 

Или используйте методы getter по умолчанию в объекте платформы.

 $posts = $platform->getPosts(); 

Вы «разделились до интересных частей», поэтому это не очевидно, если у вас есть этот метод, но он обычно делается на

 app/console doctrine:generate:entities 

Другой способ, возможно, немного OO / очиститель без использования идентификаторов:

 public function getPosts(Platform $platform) { $qb = $this->createQueryBuilder("p") ->where(':platform MEMBER OF p.platforms') ->setParameters(array('platform' => $platform)) ; return $qb->getQuery()->getResult(); } 

Лучшим именем метода будет findPostsByPlatform

Этот вопрос кажется проблемой с отношениями ManyToMany, которые вы хотите получить BIDIRECTIONAL (и теперь UNIDIRECTRIONAL). Используйте MappedBy для создания двунаправленной:

http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#many-to-many-bidirectional

Практически:

Одна из ваших образований – ОСНОВНАЯ СТОРОНА, другая ОБРАТНАЯ СТОРОНА. В вашем примере объект с именем Post является стороной-владельцем, а объект с именем Platform – обратная сторона.

Настройка OWNING SIDE:

 Class Post { ... /** * @ManyToMany(targetEntity="Platform") * @JoinTable(name="map_post_platform", * joinColumns={@JoinColumn(name="post_id", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="platform_id", referencedColumnName="id", unique=true)} ) **/ protected $platforms; ... public function Post() { $this->platforms= new ArrayCollection(); } ... public function assignToPlatform($platform) { $this->platforms[] = $platform; } ... public function getPlatforms() { return $this->platforms; } } 

ОБРАТНАЯ СВЯЗЬ Настройка:

 Class Platform { ... /** * @ManyToMany(targetEntity="Post", mappedBy="platforms") **/ protected $posts; ... public function Platform() { $this->posts= new ArrayCollection(); } ... public function getPosts() { return $this->posts; } } 

ПРИМЕР получения массива объектов, начиная с одной из сторон:

 $post->getPlatforms(); $platform->getPosts();