ArrayCollection::matching() : sorting collection by an Entity field is inconsistent. #5876

Open
opened 2026-01-22 15:20:57 +01:00 by admin · 0 comments
Owner

Originally created by @theredled on GitHub (Feb 11, 2018).

It is impossible to properly sort a collection by an Entity field, as 2 objects can't be compared.
To make it work, it should compare their IDs, __toString() or other.

Example:

// $a, $b, $c, $d are entities with a ->Contractor relation leading to different Contractor objects
$coll = new ArrayCollection([$a, $b, $c, $d]]);
$crit = Criteria::create();
$crit->orderBy(['Contractor' => Criteria::ASC]);
var_dump($coll->matching($crit));
// won't be properly sorted

What happens:

In ClosureExpressionVisitor

    public static function sortByField($name, $orientation = 1, \Closure $next = null)
    {
        if ( ! $next) {
            $next = function() {
                return 0;
            };
        }

        return function ($a, $b) use ($name, $next, $orientation) {
            $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);
            $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name);

            if ($aValue === $bValue) {
                return $next($a, $b);
            }

            return (($aValue > $bValue) ? 1 : -1) * $orientation;
        };
    }

$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name); returning object for an object relation, unequal objects are compared using > , always returning false.

Originally created by @theredled on GitHub (Feb 11, 2018). It is impossible to properly sort a collection by an Entity field, as 2 objects can't be compared. To make it work, it should compare their IDs, __toString() or other. Example: ``` // $a, $b, $c, $d are entities with a ->Contractor relation leading to different Contractor objects $coll = new ArrayCollection([$a, $b, $c, $d]]); $crit = Criteria::create(); $crit->orderBy(['Contractor' => Criteria::ASC]); var_dump($coll->matching($crit)); // won't be properly sorted ``` What happens: In ClosureExpressionVisitor ``` public static function sortByField($name, $orientation = 1, \Closure $next = null) { if ( ! $next) { $next = function() { return 0; }; } return function ($a, $b) use ($name, $next, $orientation) { $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name); $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name); if ($aValue === $bValue) { return $next($a, $b); } return (($aValue > $bValue) ? 1 : -1) * $orientation; }; } ``` `$aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name);` returning object for an object relation, unequal objects are compared using `>` , always returning false.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5876