Login to bookmark this video
Buy Access to Course
18.

Fetch the Object ID with Doctrine

|

Share this awesome video!

|

Lucky you! You found an early release chapter - it will be fully polished and published shortly!

This Chapter isn't quite ready...

Get Notified About this Course!

We will send you messages regarding this course only
and nothing else, we promise.
You can unsubscribe anytime by emailing us at:
privacy@symfonycasts.com

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!