Filtering a Collection using Criteria targeting an Embeddable object

Viewed 158

Let's say you have a class Title, and the title is translated in multiple languages using TitleTranslation classes. To indicate which language the title is translated in, each translation has a Locale value object.

For readability, I am attempting to provide the Title class with a getTitle(Locale $locale) method, returning the correct translation. The easy way to do this would be to loop over all translations, and check each translation's locale. However, I would like to accomplish this using Criteria, so only a single TitleTranslation will be fetched and hydrated.

To illustrate the case, a simplified version of the classes I'm working with:

Title:

/** @ORM\Entity @ORM\Table */
class Title
{
    /**
     * @ORM\OneToMany(targetEntity="TitleTranslation", mappedBy="element")
     */
    private $translations;
}

TitleTranslation:

/** @ORM\Entity @ORM\Table */
class TitleTranslation
{
    /**
     * @ORM\ManyToOne(targetEntity="Title", inversedBy="translations")
     */
    private $title;
    /**
     * @ORM\Column(type="string")
     */
    private $translation;
    /**
     * @ORM\Embedded(class="Locale")
     */
    private $locale;

    public function getTranslation() : string
    {
        return $this->translation;
    }
}

Locale:

/** @Embeddable */
class Locale
{
    /** @ORM\Column(type="string")
    private $locale;

    public function __toString()
    {
        return $this->locale;
    }
}

I have made the following attempts, all of which are unsuccessful:

public function getTitle(Locale $locale)
{
    $localeCriteria = Criteria::create()->where(Criteria::expr()->eq('locale', $locale));
    /** @var TitleTranslation | bool $translation */
    $translation = $this->translations->matching($translationCriteria)->first();

    return $translation ? $translation->getTranslation() : null;
}

This approach fails with an ORMException "Unrecognized field: locale", which seems normal, as Embeddables should be queried as "locale.locale" (field in containing class.field in VO). However, using this notation:

$localeCriteria = Criteria::create()->where(Criteria::expr()->eq('locale.locale', $locale));

Fails with Undefined property: TitleTranslation::$locale.locale

Am I missing something, or is this approach simply not possible?

0 Answers
Related