Использование EntityRepository:: findBy() с отношениями "многие ко многим" приведет к E-уведомлению в доктрине

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

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

// 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 существующей

3 ответов


Это очень возможно, но хранилище доктрины запаса не работает таким образом.

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

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

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;
  }
}

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

$posts = $platform->getPosts();

вы "раздели до интересных частей", так что это не очевидно, если у вас есть этот метод, но он обычно сделан на

app/console doctrine:generate:entities

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

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, которые вы хотите двунаправленными (и теперь однонаправленными). Используйте MappedBy для создания двунаправленности:

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

практика :

одна из ваших сущностей владеет стороной, другая обратная сторона. В вашем примере сущность с именем Post является владельцем side, а сущность с именем Platform обратная сторона.

иметь бортовую установку:

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();