Obtener el ID de objeto con Doctrine
Lucky you! You found an early release chapter - it will be fully polished and published shortly!
This Chapter isn't quite ready...
Rest assured, the gnomes are hard at work
completing this video!
Actualmente, nuestros datos de traducción al francés se muestran correctamente en la página. Sin embargo, nuestro método actual de obtención del ID mediante$object->getId()
es un poco inestable. Supone que el usuario siempre tiene un método getId()
en sus entidades, lo que no siempre es el caso. Podemos hacerlo mejor... ¡y Doctrine nos cubre las espaldas!
Obtener el gestor de objetos
En nuestro método ObjectTranslator::translationsFor()
, encima de obtener las traducciones, haz algo de espacio. En primer lugar, obtén el gestor de objetos de Doctrine:$om = $this->doctrine->getManagerForClass()
. Esto necesita un nombre de clase, así que utiliza la clase del objeto pasado: $object::class
:
// ... lines 1 - 9 | |
final class ObjectTranslator | |
{ | |
// ... lines 12 - 37 | |
private function translationsFor(object $object, string $locale): array | |
{ | |
// ... lines 40 - 46 | |
$om = $this->doctrine->getManagerForClass($object::class); | |
// ... lines 48 - 76 | |
} | |
} |
Cuando utilices el ORM, habrás utilizado algo llamado gestor de entidades. Esto es lo que tenemos aquí: el gestor de objetos es una interfaz más general para él. De nuevo, utilizar estas interfaces abstractas hace que nuestro bundle sea más flexible.
getManagerForClass()
puede devolver null, así que compruébalo:if (!$om) { throw new \LogicException(sprintf('No object manager found for class "%s".', $object::class)); }
:
// ... lines 1 - 9 | |
final class ObjectTranslator | |
{ | |
// ... lines 12 - 37 | |
private function translationsFor(object $object, string $locale): array | |
{ | |
// ... lines 40 - 48 | |
if (!$om) { | |
throw new \LogicException(sprintf('No object manager found for class "%s".', $object::class)); | |
} | |
// ... lines 52 - 76 | |
} | |
} |
Obtener el ID del gestor de objetos
A continuación, $id = $om->getClassMetadata($object::class)
. Esto devuelve un objeto especial que lo sabe todo sobre el mapeo Doctrine para esta clase. ->getIdentifierValues()
es lo que queremos. Pasa la instancia $object
:
// ... lines 1 - 9 | |
final class ObjectTranslator | |
{ | |
// ... lines 12 - 37 | |
private function translationsFor(object $object, string $locale): array | |
{ | |
// ... lines 40 - 52 | |
$id = $om->getClassMetadata($object::class) | |
->getIdentifierValues($object) | |
; | |
// ... lines 56 - 76 | |
} | |
} |
Esto recupera el ID del objeto pasado, independientemente de cómo esté implementado.
dd($id)
para ver de qué se trata. En el navegador, actualiza. Hmm... Es una matriz de valores... Doctrine admite ID compuestos, lo que básicamente significa múltiples campos de ID para una entidad. Se trata de una función bastante avanzada, y nuestro bundle, al menos inicialmente, no la admite.
Aunque tu entidad sólo tenga un campo ID, Doctrine lo devuelve como una matriz. Elimina el dd()
y añade una comprobación: if (count($id) > 1)
. Dentro,throw new \LogicException(sprintf('Class "%s" must have a single identifier to be translatable', $object::class))
:
// ... lines 1 - 9 | |
final class ObjectTranslator | |
{ | |
// ... lines 12 - 37 | |
private function translationsFor(object $object, string $locale): array | |
{ | |
// ... lines 40 - 56 | |
if (1 !== count($id)) { | |
throw new \LogicException(sprintf('Class "%s" must have a single identifier to be translatable.', $object::class)); | |
} | |
// ... lines 60 - 76 | |
} | |
} |
Coge el primer elemento del array con $id = reset($id)
:
// ... lines 1 - 9 | |
final class ObjectTranslator | |
{ | |
// ... lines 12 - 37 | |
private function translationsFor(object $object, string $locale): array | |
{ | |
// ... lines 40 - 60 | |
$id = reset($id); | |
// ... lines 62 - 76 | |
} | |
} |
dd()
y actualiza el navegador. Perfecto, ¡un solo valor!
Elimina el dd()
y abajo en nuestra matriz findBy()
, sustituye $object->getId()
por$id
:
// ... lines 1 - 9 | |
final class ObjectTranslator | |
{ | |
// ... lines 12 - 37 | |
private function translationsFor(object $object, string $locale): array | |
{ | |
// ... lines 40 - 63 | |
$translations = $this->doctrine->getRepository($this->translationClass)->findBy([ | |
// ... lines 65 - 66 | |
'objectId' => $id, | |
]); | |
// ... lines 69 - 76 | |
} | |
} |
Pruébalo en el navegador... ¡y funcionó!
Nuestro ObjectTranslator
funciona, y es bastante sólido. A continuación, ¡creemos un filtro Twig para él!