1
votes

I'm trying to filter a list of "Client" entities based on properties of an associated entity called Account. The problem is that the Account entity it's just a base class and the actual properties for filtering lives in their child entities (PersonalAccount and EnterpriseAccount) but doctrine only let my access properties of the Account base class.

To summarize, here's my situation:

The Client entity:

class Client 
{
    /** @ORM\OneToMany(targetEntity="Account", mappedBy="client") */
    protected $accounts;
}

The base Account entity:

class Account 
{
    /** @ORM\ManyToOne(targetEntity="Client", inversedBy="accounts") */
    protected $client;
}

PersonalAccount entity (child of Account)

class PersonalAccount extends Account
{
    /** @ORM\Column() */
    protected $name;
}

In my controller I tried:

$qb = $em->getRepository('MyBundle:Client')->createQueryBuilder('cl');

$query = $qb->select('cl')
            ->innerJoin('cl.accounts', 'acc')
            ->where('acc.name = :name')
            ->setParameter('name', 'Jhon')
            ->getQuery();

But it throws an exception because the base class Account doesn't have a property called "name".

How can I filter the Client entity using properties of the inherited PersonalAccount class?

2

2 Answers

3
votes

First, you should add some inheritance annotations in your parent class. You should read this article from the Doctrine doc : 6. Inheritance Mapping.

In fact, inheritance is ascending, not descending.

"Accessing a Superclass and checking for a property that exists on a certain child is not possible in any strict OO language without specific casting into the type beforehand."

The feature you need is being discussed here.

BUT : what you can do for the moment is using Class Table Inheritance and something like this :

$qb = $em->getRepository('MyBundle:Client')->createQueryBuilder('cl');
$qb2 = $em->getRepository('MyBundle:PersonalAccount')->createQueryBuilder('persoAcc');

$query = $qb->select('cl')
            ->where(
                $qb->expr()->in(
                    'cl.id',
                    $qb2->select('persoAcc.id')
                        ->where('persoAcc.name = :name')
                        ->setParameter('name', 'Jhon')
                        ->getDql()
                )
            )
            ->getQuery();

And I would recommend that you use a Repository Class.

1
votes

Add an association on Client:

/** @ORM\OneToMany(targetEntity="PersonalAccount", mappedBy="client") */
protected $personalAccounts;

and do the join on it:

->innerJoin('cl.personalAccounts', 'acc')