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:
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