Schugs
Schugs

Reputation: 89

Doctrine ArrayCollection Criteria with OneToMany Relationship

I have a OneToMany Unidirectional relationship between an "Employee" and "Status". There is then also a ManyToMany biderectional relationship between "Employee" and "Documents". When I have my a Document, i am trying to find all related employees ($Document->getEmployees()) and then "filter" (using ->matching(Criteria)) by the "Status"

I keep getting the below error:

    2018-04-05T14:35:19+00:00 [error] Error thrown while running command "app:expiration-check". Message: "Notice: Undefined index: Status"

In DefaultQuoteStrategy.php line 39:

  Notice: Undefined index: Status

Here is the Code i am using:

$Employees = $Document->getEmployees()->matching(
                Criteria::create()
                    ->andWhere(Criteria::expr()->eq('Status',$this->GlobalSettings->getApprovedEmployeeStatus()))
            );

Interestingly enough, the exact same criteria works if i am using the Employee Repository

$Employees = $this->em->getRepository(Employee::class)->matching(
                Criteria::create()
                    ->andWhere(Criteria::expr()->eq('Status',$this->GlobalSettings->getApprovedEmployeeStatus()))
            );

Matching static fields also works fine.

$Employees = $Document->getEmployees()->matching(
                Criteria::create()
                    ->andWhere(Criteria::expr()->eq('FirstName',"Keven"))
            );

Here is the Status Column defintion

/**
 * @ORM\ManyToOne(targetEntity="Entity\Accounts\EmployeeStatus")
 * @ORM\JoinColumn(name="StatusId", referencedColumnName="id", nullable=false)
 */
private $Status;

Here is the Employees Defintion (on Document Entity)

/**
 * @ORM\ManyToMany(targetEntity="Entity\Accounts\Employee", mappedBy="Documents")
 */
private $Employees;

/**
 * Constructor
 */
public function __construct()
{
    parent::__construct();
    $this->Employees = new \Doctrine\Common\Collections\ArrayCollection();
}

and Here is the getEmployees() (also on Document)

/**
 * Get employees.
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getEmployees()
{
    return $this->Employees;
}

Upvotes: 0

Views: 3169

Answers (1)

Jannes Botis
Jannes Botis

Reputation: 11242

To manage ManyToMany relations, doctrine uses Doctrine\ORM\Persisters\Collection\ManyToManyPersister class. You can see it being used here

Unfortunately, currently in the latest release, v2.6.1, method loadCriteria of this class is lacking the feature to use relation fields. Only static fields are supported.

Looking at the master branch currently, this support has been added: Doctrine\ORM\Persisters\Collection\ManyToManyPersister as of today but it is not part of a release yet. Also having a quick look at 2.7 branch it does not look it will be there.

I am not sure whether you could use the master branch with symfony `s doctrine bundle. I think it will be difficult to get this to work now.

What you could do, is initialize the ManyToMany collection $Document->getEmployees() and then use the matching function, which means that you load all employees and then filter, not lazy load as you would expect.

So do:

$employees = $Document->getEmployees();
$employees->initialize();
$employees->matching(
            Criteria::create()
                ->andWhere(Criteria::expr()->eq('Status',$this->GlobalSettings->getApprovedEmployeeStatus()))
        );

and put a note to change the code, when the new changes are released.

Upvotes: 4

Related Questions