orm icon indicating copy to clipboard operation
orm copied to clipboard

Matching criteria on the InverseSide of a ManyToMany relation fails

Open guaycuru opened this issue 9 years ago • 16 comments

I'm using DBAL and ORM 2.5.4, with PHP 5.5.15.

I have two classes (Asset and Process) which are linked by a ManyToMany relation as follows:

class Asset extends Base {
    /**
     * @Doctrine\ORM\Mapping\Id
     * @Doctrine\ORM\Mapping\Column(type="integer", options={"unsigned"=true})
     * @Doctrine\ORM\Mapping\GeneratedValue
     **/
    protected $id;

    /**
     * @Doctrine\ORM\Mapping\ManyToMany(targetEntity="Process", mappedBy="assets")
     **/
    protected $processes;
}

class Process extends Base {
    /**
     * @Doctrine\ORM\Mapping\Id
     * @Doctrine\ORM\Mapping\Column(type="integer", options={"unsigned"=true})
     * @Doctrine\ORM\Mapping\GeneratedValue
     **/
    protected $id;

    /**
     * @Doctrine\ORM\Mapping\ManyToMany(targetEntity="Asset", inversedBy="processes")
     * @Doctrine\ORM\Mapping\OrderBy({"id" = "ASC"})
     **/
    protected $assets;

    /**
     * @Doctrine\ORM\Mapping\Column(type="string")
     **/
    protected $status;

Now I'm trying to filter Active's Processes by a field (status) as follows:

$expr = \Doctrine\Common\Collections\Criteria::expr();
$criteria = \Doctrine\Common\Collections\Criteria::create()
    ->where($expr->eq("status", 'finished'));

$this->getProcesses()->matching($criteria);

If I understand correctly, this should work, but instead I'm getting a bunch of exceptions:

Notice: Undefined index: relationToSourceKeyColumns in vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Collection\ManyToManyPersister.php on line 234

And

Notice: Undefined index: name in vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultQuoteStrategy.php on line105

I've walked through the code and the problem seems to be that on ManyToManyPersister::loadCriteria() $joinTable is not loading correctly (it's returning an empty string):

$joinTable    = $this->quoteStrategy->getJoinTableName($mapping, $ownerMetadata, $this->platform);

Which creates this SQL query:

SELECT te.id AS id, te.status AS status FROM processes te JOIN  t ON t.process_id = te.id WHERE te.status = ?' with params ["finished"]

Note how the JOIN table is missing from the query (JOIN t).

Setting JoinTable excplicitly on the Owning side (Process) does not make any difference, but setting it on the Inverse side (Asset) makes the SQL query be built correctly, but those 2 errors still happen:

Notice: Undefined index: relationToSourceKeyColumns in vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Collection\ManyToManyPersister.php on line 234

And

Notice: Undefined index: name in vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultQuoteStrategy.php on line105

Now, if I understand correctly, setting the JoinTable should not be necessary, and everything should work with no errors... Is this a bug, or did I misunderstand something?

guaycuru avatar Feb 02 '16 17:02 guaycuru

I'm having exactly the same problem. There are other bugs in the Criteria functionality too (#5687 for example). The more I use it the more I think it's not very well tested or ready for release.

jaikdean avatar Mar 04 '16 12:03 jaikdean

Same issue here.

gnutix avatar Apr 27 '16 07:04 gnutix

More than a year has passed but it's still not fixed, weird

AlexeyKosov avatar Apr 26 '17 19:04 AlexeyKosov

@AlexeyKosov it's still not clear that this is a bug. It's just that the maintainers don't have enough time to investigate every single of them. If you want to make it, create a reproducible scenario and submit a PR.

theofidry avatar Apr 26 '17 21:04 theofidry

Just got the same issue. Undefined index: relationToSourceKeyColumns

Relation on inversed side

/**
     * @var Collection
     * @ORM\ManyToMany(targetEntity="AppBundle\Domain\Speaker\Speaker", mappedBy="conventions")
     */
    protected $speakers;

And method with issue

public function getSpeakersByIds(array $speakerIds)
    {
        $criteria = Criteria::create()
                            ->where(Criteria::expr()->in("id", $speakerIds));

        return $this->speakers->matching($criteria);
    }

seyfer avatar May 29 '17 10:05 seyfer

Still not working :(

mikemix avatar Jul 10 '17 09:07 mikemix

@mikemix My advice is to ignore the Criteria feature exists; it has too many huge functionality holes and nothing has been addressed for years. Unless the Doctrine project gets some serious investment I don't foresee this ever being fixed.

jaikdean avatar Jul 10 '17 13:07 jaikdean

I agree with @mikemix here. I'm trying to avoid Criteria and prefer to use Repository methods while developing. But sometimes use of Criteria looks good.

seyfer avatar Jul 10 '17 13:07 seyfer

@seyfer well it works well with OneToMany relations, I gave up with ManyToMany though.

mikemix avatar Jul 10 '17 13:07 mikemix

@mikemix It works for OneToMany relations using only equals comparators. "Not equals" being interpreted as "equals" is perhaps a better example than this issue of why I don't touch Criteria anymore.

jaikdean avatar Jul 10 '17 14:07 jaikdean

I would love to contribute however I'm totally out of time, so are the authors I guess. No knowledge about Doctrine's internals does not help as well. There are already 162 pull requests pending! lol. It would be nice if any organization thrown some money to the contributors to help maintain this project. Beside Composer I find Doctrine to be one of the most important libraries out there driving the PHP world.

mikemix avatar Jul 10 '17 16:07 mikemix

@jaikdean It's not so good. Equals also has a bug. When you do "count" right before "matching" it's not searching on by non JoinColumn fields(only by parent_id, but not parent_id+name pair for example).

permiakov avatar Nov 05 '17 21:11 permiakov

I am experiencing this issue aswell. The ManyToManyPersister receive a list of parameters which yields the result if the criteria I'm passing along. The DefaultQuoteStrategy class then goes looking in the fieldmappings, however the property I'm requesting in my criteria resides within the associations list of the ClassMetadata object.

Can this be addressed please?

ricohumme avatar Nov 22 '18 16:11 ricohumme

Me too. Can someone give an example of using a repository instead of Criteria for the exact same purpose? Thanks.

phtmgt avatar Jun 27 '19 07:06 phtmgt

It is much appreciated if a PR with a failing test is contributed. PRs with a fix is also welcome.

SenseException avatar Jun 27 '19 08:06 SenseException

Could you guys please check if this is still an issue? I believe it has been fixed over the course of the last nine years.

While I was working on #11985 I added test cases for this, and at least for the eq expression they seemed to pass even without the changes I made.

mpdude avatar Mar 30 '25 20:03 mpdude

Still exists..

// Position

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
    public ?Project $project = null;

    #[ORM\ManyToMany(targetEntity: Profile::class, inversedBy: 'positions')]
    private Collection $profiles;


// Profile

    #[ORM\ManyToMany(targetEntity: Position::class, mappedBy: 'profiles')]
    private Collection $positions;


    public function getPositonsForProject(Project $project): Collection
    {
        $criteria = Criteria::create()->where(Criteria::expr()?->eq('project', $project));

        return $this->positions->matching($criteria);
    }
ErrorException
Warning: Undefined array key "project"

in [vendor/doctrine/orm/src/Mapping/DefaultQuoteStrategy.php ](.../vendor/doctrine/orm/src/Mapping/DefaultQuoteStrategy.php#L33)(line 33)
in [vendor/doctrine/orm/src/Persisters/Collection/ManyToManyPersister.php ](.../vendor/doctrine/orm/src/Persisters/Collection/ManyToManyPersister.php#L246)-> getColumnName (line 246)
in [vendor/doctrine/orm/src/PersistentCollection.php ](.../vendor/doctrine/orm/src/PersistentCollection.php#L589)-> loadCriteria (line 589)
PersistentCollection->matching()
doctrine/collections                 2.3.0           PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common                      3.5.0           PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.
doctrine/data-fixtures               2.1.0           Data Fixtures for all Doctrine Object Managers
doctrine/dbal                        4.3.2           Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations                1.1.5           A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.
doctrine/doctrine-bundle             2.15.1          Symfony DoctrineBundle
doctrine/doctrine-fixtures-bundle    4.1.0           Symfony DoctrineFixturesBundle
doctrine/doctrine-migrations-bundle  3.4.2           Symfony DoctrineMigrationsBundle
doctrine/event-manager               2.0.1           The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector                   2.0.10          PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/instantiator                2.0.0           A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer                       3.0.1           PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations                  3.9.2           PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to i...
doctrine/orm                         3.5.1           Object-Relational-Mapper for PHP
doctrine/persistence                 4.0.0           The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.
doctrine/sql-formatter               1.5.2           a PHP SQL highlighting library

1ed avatar Aug 07 '25 12:08 1ed