php filter doctrine2 doctrine

php - Doctrine 2, consulta dentro de las entidades



filter doctrine2 (5)

¿Cómo realizo consultas en una entidad?

namespace Entities/Members; /** * @Entity(repositoryClass="/Entities/Member/MembersRepository") * @Table(name="Members") * @HasLifecycleCallbacks */ class Members extends /Entities/AbstractEntity { /** * @Id @Column(name="id", type="bigint",length=15) * @GeneratedValue(strategy="AUTO") */ protected $id; /** * @Column(name="userid", type="bigint", length=26, nullable=true) */ protected $userid; /** * @Column(name="fname", type="string", length=255,nullable=true) */ protected $fname; /** * @OneToMany(targetEntity="/Entities/Users/Wall", mappedBy="entry", cascade={"persist"}) */ protected $commententries; public function __construct() { $this->commententries = new /Doctrine/Common/Collections/ArrayCollection(); } }

Ejemplo Quisiera tener una función dentro de esta entidad llamada: filter() y quiero poder filtrar la colección commententries . Debería devolver una colección con cierta condición, como id=1 . Básicamente debería estar filtrando los datos recibidos de la consulta de unión.

Entonces algo como esto:

$this->commententries->findBy(array(''id'' => 1));

Pero obviamente esto no funciona.


En general, no deberías hacer esto.

Las entidades, como regla general, no deben saber sobre el entitymanager (directamente, o a través de algún objeto intermediario).

La razón de esto es principalmente la capacidad de prueba, pero en mi experiencia, ayuda a mantener las cosas organizadas de otras maneras.

Lo abordaría diseñando una clase de servicio que maneje las búsquedas para usted. Su controlador (o lo que sea) lo conduciría así:

<?php // create a new service, injecting the entitymanager. if you later wanted // to start caching some things, you might inject a cache driver as well. $member = $em->find(''Member'',$member_id); //get a member, some how. $svc = new MemberService($em); $favoriteCommentaries = $svc->getFavoriteCommentaries($member);

Como indico en el comentario, si luego decide que desea agregar el almacenamiento en caché (a través de memcached, por ejemplo) para evitar búsquedas frecuentes, lo haría en algún lugar cercano o en esta clase de servicio. Esto mantiene sus entidades agradables y simples, y fácilmente comprobables. Como usted inyecta su entidad administrador en el servicio en tiempo de construcción, puede simular eso según sea necesario.

getFavoriteCommentaries () podría usar varias implementaciones. Una cosa trivial sería la de proxy a Member :: getFavoriteCommentaries (), que en realidad cargaría todo, y luego filtraría los "favoritos". Eso probablemente no se escalará particularmente bien, por lo que podría mejorar utilizando el EM para obtener solo los datos que necesita.


Su pregunta fue realmente difícil de entender, intente trabajar sobre cómo estructurar sus preguntas en el futuro. Por ejemplo, dices "devuelve el mismo resultado" pero "filtra", lo que podría significar cualquier cosa. ¿Desea utilizar el mismo conjunto de resultados (por qué diablos elegiría hacer eso), y simplemente utiliza array_filter o array_walk para filtrar los resultados o realmente quiere usar una unión condicional? Es increíblemente ambiguo.

De todos modos .. respuesta (después de leer su pregunta 4 veces).

$q = $qb->select ( "m","w" ) ->from ( "Members", "m" ) ->leftJoin( "m.commententries","w",''WITH'', ''w.id = :id'') ->setParameter ( "id", $id ) ->getQuery ();


Estoy de acuerdo con "timdev". No debe definir la consulta en su clase de entidades. Mi manera de definir un soporte de clase de servicio es que las entidades son clases de repositorio. Por ejemplo: Usuario (entidad - YourBundle / Entity / User.php) tendrá UserRepository (clase de servicio - YourBundle / Repository / UserRepository.php). Su método de "filtro" debería estar aquí. Solo necesita asignar esta clase de servicio en su clase de entidad. En su controlador, siempre puede acceder al "filtro" a través de su repositorio. Está documentado con gran detalle en el libro de Symfony2


Use un repositorio personalizado para consultas

No debe escribir consultas en sus entidades, pero debe usar un repositorio para eso. Esto también se explica en la documentación de la doctrina 7.8.8 Repositorios personalizados . Le permitirá construir sus consultas personalizadas en un lugar central y mantener limpias las definiciones de su entidad.

Use criterios para filtrar colecciones:

Pero si desea filtrar dentro de su colección en un método get , puede usar Criteria . Puede leer sobre cómo usar Criteria en la documentación de Doctrine 8.8 Filtrar colecciones . Filtrar como desee hacer se vería así:

Declare en la parte superior de su clase de entidad la clase Criteria

use Doctrine/Common/Collections/Criteria

En su método getCommentEntries use la clase para filtrar:

public function getCommentEntries() { $criteria = Criteria::create() ->where(Criteria::expr()->eq(''id'', 1)); $filteredCommentEntries = $this->commententries->matching($criteria); return $filteredCommentEntries; }


Su ArrayCollection ya implementa un método de filtro (), necesita pasar un Cierre para que funcione sus entidades (aquí, las entradas de comentarios).

$idsToFilter = array(1,2,3,4); $member->getComments()->filter( function($entry) use ($idsToFilter) { if (in_array($entry->getId(), $idsToFilter)) { return true; } return false; } );

(no probado)

Tenga en cuenta que dicho método repetirá y deseará cargar todos sus comentarios, por lo que, en caso de que un usuario tenga mucho, puede ser un gran cuello de botella;

En la mayoría de los casos, desea utilizar repositorios personalizados, donde puede ubicar dicha lógica.

Como sugirió Timdev, puede crear un MemberService que ajustará dicha llamada al conocer el EntityManager.

Separar entidades de la capa de Peristance es una gran mejora sobre Doctrine 1, y no deberías romper esa regla.