Doctrine2 Mejor Práctica, en caso de utilizar los servicios de las entidades?
-
11-10-2019 - |
Pregunta
Me hizo una pregunta similar hace un tiempo: Uso del patrón de datos Mapper, en caso de las entidades (objetos de dominio) saben sobre el Mapper? Sin embargo, era genérico y estoy realmente interesado en cómo llevar a cabo algunas cosas con Doctrine2 específicamente .
Esto es un modelo simple ejemplo: Cada Thing
puede tener un Vote
de un User
, un User
puede emitir más de un Vote
pero sólo los últimos recuentos Vote
. Debido otros datos (Msssage
, etc) está relacionada con la Vote
, cuando el segundo Vote
se coloca el Vote
originales pueden no sólo ser actualizado, que necesita ser reemplazado.
Actualmente Thing
tiene esta función:
public function addVote($vote)
{
$vote->entity = $this;
}
Y Vote
se encarga de establecer la relación:
public function setThing(Model_Thing $thing)
{
$this->thing = $thing;
$thing->votes[] = $this;
}
Me parece que para asegurar un User
sólo ha contado la última Vote
es algo que el Thing
debe garantizar, y no una capa de servicio .
Así que para mantener que en el modelo, la nueva función Thing
:
public function addVote($vote)
{
foreach($this->votes as $v){
if($v->user === $vote->user){
//remove vote
}
}
$vote->entity = $this;
}
¿Cómo puedo eliminar el Vote
desde dentro del modelo de dominio? ¿Debo relajarme Vote::setThing()
a aceptar un NULL
? Debería implicar algún tipo de capa de servicios que Thing
puede utilizar para eliminar el voto? Una vez que los votos empezar a acumular, que foreach
va a ser lento? - se debe utilizar una capa de servicio para permitir Thing
para buscar un Vote
sin tener que cargar toda la colección
Definitivamente estoy inclinando hacia el uso de una capa de servicio de luz; Sin embargo, hay una mejor manera de manejar este tipo de cosas con Doctrine2, o estoy yendo en la dirección correcta?
Solución
Yo voto por la capa de servicio. A menudo me he luchado con el intento de agregar tanto la lógica de la propia entidad, y simplemente yo frustrado. Sin acceso a la EntityManager, eres simplemente no son capaces de realizar la consulta lógica, y se encontrará utilizando una gran cantidad de O (n) operaciones o perezoso de carga conjuntos de toda relación cuando sólo necesita unos pocos registros (que es super cojo en comparación con todas las ventajas DQL ofertas).
Si necesita algún tipo de asistencia superando la idea de que el modelo de dominio anémico es siempre un anti-patrón, véase esta presentación por Matthew Weier O'Phinney o esta pregunta .
Y si bien podría estar malinterpretando la terminología, no estoy totalmente convencido de que las entidades tienen que ser los únicos objetos permite en su modelo de dominio. Yo consideraría fácilmente que la suma de Entidad objetos y sus servicios constituye el modelo. Creo que surja la anti-patrón cuando se termina de escribir una capa de servicio que presta poca o ninguna atención a la separación de las preocupaciones.
He menudo coqueteó con la idea de tener todo mi entidad de objetos proxy algunos métodos para la capa de servicio:
public function addVote($vote)
{
$this->_service->addVoteToThing($vote, $thing);
}
Sin embargo, desde Doctrina no tiene ningún sistema de eventos de devolución de llamada clase en la hidratación objeto, no he encontrado una manera elegante de inyectar el objeto de servicio.
Otros consejos
Mi consejo sería poner toda la lógica de consulta en un EntityRepository y luego hacer una interfaz de ella algo así como:
class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}
Se requiere esa manera se puede utilizar la interfaz en su unidad de pruebas para los objetos de servicio y ninguna dependencia en el EntityManager.