Fetch the Object ID with 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!
Currently, our French translation data is being successfully displayed on
the page. However, our current method of fetching the ID using
$object->getId()
is a bit shaky. It assumes that the user always has a getId()
method on their entities, which isn't always the case. We can do better...
and Doctrine has our back!
Fetching the Object Manager
Over in our ObjectTranslator::translationsFor()
method, above fetching the translations,
make some space. First, grab the object manager from Doctrine:
$om = $this->doctrine->getManagerForClass()
. This needs a class name, so use
the passed object's class: $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 | |
} | |
} |
When using the ORM, you've used something called the entity manager. This is what we're getting here - object manager is a more general interface for it. Again, using these abstract interfaces makes our bundle more flexible.
getManagerForClass()
might return null so check for that:
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 | |
} | |
} |
Fetching the ID from the Object Manager
Next, $id = $om->getClassMetadata($object::class)
. This returns a special object
that knows all about the Doctrine mapping for this class. ->getIdentifierValues()
is what we want. Pass the $object
instance:
// ... 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 | |
} | |
} |
This retrieves the ID for the passed object, regardless of how it's implemented.
dd($id)
to see what we are dealing with here. In the browser, refresh. Hmm... It's
an array of values... Doctrine supports composite IDs, which basically means multiple
ID fields for an entity. This is a pretty advanced feature, and our bundle, at
least initially, won't support this.
Even if your entity only has a single ID field, Doctrine still returns it
as an array. Remove the dd()
and add a check: if (count($id) > 1)
. Inside,
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 | |
} | |
} |
Grab the first element of the array with $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()
that... and refresh the browser. Perfect, just a single value!
Remove the dd()
and down in our findBy()
array, replace $object->getId()
with
$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 | |
} | |
} |
Test it out in the browser... and it worked!
Our ObjectTranslator
is working, and pretty solid. Next, let's create a Twig filter
for it!