query many generate from foreign create php symfony doctrine many-to-many database-relations

php - generate - Usar EntityRepository:: findBy() con relaciones Many-To-Many dará lugar a un E_NOTICE en Doctrine



symfony 3.4 doctrine query (3)

Es muy posible, pero Stock Doctrine Repository no funciona de esta manera.

Tienes dos opciones, dependiendo de tu contexto:

Escriba un método personalizado en el Repositorio.

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

O use los métodos getter predeterminados en el objeto de la plataforma.

$posts = $platform->getPosts();

Usted "se despojó de las partes interesantes" por lo que no es obvio si tiene este método, pero normalmente se hace en

app/console doctrine:generate:entities

Para un proyecto Symfony2 tuve que crear una relación entre una publicación de blog y las llamadas plataformas. Una plataforma define un filtro específico basado en el dominio que usa para ver el sitio. Por ejemplo: si se une al sitio por url first-example.com, el sitio solo proporcionará publicaciones de blog, que están conectadas a esta plataforma específica.

Para hacerlo, creé dos entidades Post y Plataforma. Después los mapeé junto con una relación Muchos a Muchos. Estoy tratando de recuperar datos a través de esta relación Muchos a Muchos a partir de la función integrada findBy() en el 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));

Donde $postRepo es el Repositorio correcto para la entidad Post y $platform un objeto Platform existente.
De cualquier manera: termino recibiendo el siguiente error:

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

¿Es posible recuperar entidades relacionadas en una relación Muchos a Muchos de esta manera, o me veo obligado a escribir estas funciones yo solo? Lo extraño es que Doctrine no lanzará ningún error como: "No es posible", sino un E_NOTICE interno. Es por eso que creo que debería ser posible, pero me faltan algunos puntos aquí.

Reducidos a las partes interesantes, las dos Entidades se ven así.

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

Y, por supuesto, el archivo composer.json (también desglosado en las líneas correspondientes)

{ [...] "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", [...] }, [...] }


Esta pregunta parece un problema con una relación ManyToMany que desea BIDIRECCIONAL (y ahora es UNIDIRECTRIONAL). Usa MappedBy para crear bidireccionalidad:

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

Práctico:

Una de tus entidades es AL LADO, el otro lado INVERSO. En su entidad de ejemplo llamada Poste es propietaria, y la entidad llamada Plataforma es inversa.

Configuración de 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; } }

CONFIGURACIÓN DEL LADO INVERSO:

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

EJEMPLO recuperar una matriz de entidades, empezando por uno de los lados:

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


Otra forma, tal vez un poco OO / cleaner sin usar ID:

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

Un mejor nombre de método sería findPostsByPlatform