DDC-1277: BasicEntityPersister::expandParameters() will check associations #1607

Open
opened 2026-01-22 13:19:46 +01:00 by admin · 0 comments
Owner

Originally created by @doctrinebot on GitHub (Jul 14, 2011).

Originally assigned to: @guilhermeblanco on GitHub.

Jira issue originally created by user jasper@nerdsweide.nl:

When executing a EntityRepository::findBy() or EntityRepository::findOnyBy() with criteria that contain a field/value pair where the field is an association-name and the value is an array, some (for me) unexpected behavior occurs.

First an example to make my statement a bit more clear:
I have an entity User and Group where Group has many Users (User many-to-one Group).

When I call UserRepository->findBy( array( 'group' => 1 )), all goes well.
When I call UserRepository->findBy( array( 'group' => array( 1, 2, 3 ))), I get an notice and no results (Notice: Array to string conversion in /opt/local/www/doctrine2/lib/vendor/doctrine-dbal/lib/Doctrine/DBAL/Connection.php on line 613)

I've tracked the "problem" down to the BasicEntityPersister:

BasicEntityPersister::*getSelectEntitiesSQL(), which uses BasicEntityPersister::_getSelectConditionSQL(), correctly creates a query containing something like WHERE t0.group*id IN ( ? ).
But BasicEntityPersister::expandParameters() doesn't implode the array to some string that can be bound to the query. This is because it doesn't take into account that the field could be an association.

I don't know if this is intended behavior, but I would think not. I've therefor altered the BasicEntityPersister::expandParameters() a bit:

private function expandParameters($criteria)
    {
        $params = $types = array();

        foreach ($criteria AS $field => $value) {
            if ($value === null) {
                continue; // skip null values.
            }

            $type = null;
            if (isset($this->_class->fieldMappings[$field])) {
                $type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType();
            // BEGIN: Jasper N. Brouwer (14-07-2011)
            } else if (isset($this->_class->associationMappings[$field])) {
                if ($this->_class->associationMappings[$field]['isOwningSide']) {
                    $targetClass = $this->*em->getClassMetadata($this->*class->associationMappings[$field]['targetEntity']);
                    $targetField = $this->_class->associationMappings[$field]['joinColumns'][0]['referencedColumnName'];
                    if (isset($targetClass->fieldMappings[$targetField])) {
                        $type = Type::getType($targetClass->fieldMappings[$targetField]['type'])->getBindingType();
                    }
                }
            // END: Jasper N. Brouwer (14-07-2011)
            }
            if (is_array($value)) {
                $type += Connection::ARRAY*PARAM*OFFSET;
            }

            $params[] = $value;
            $types[] = $type;
        }
        return array($params, $types);                                                                                  
    }

I hope this bit of code also clarifies what I'm trying to explain a bit more...

Originally created by @doctrinebot on GitHub (Jul 14, 2011). Originally assigned to: @guilhermeblanco on GitHub. Jira issue originally created by user jasper@nerdsweide.nl: When executing a `EntityRepository::findBy()` or `EntityRepository::findOnyBy()` with criteria that contain a field/value pair where the field is an association-name and the value is an array, some (for me) unexpected behavior occurs. First an example to make my statement a bit more clear: I have an entity `User` and `Group` where `Group` has many `Users` (`User` many-to-one `Group`). When I call `UserRepository->findBy( array( 'group' => 1 ))`, all goes well. When I call `UserRepository->findBy( array( 'group' => array( 1, 2, 3 )))`, I get an notice and no results (Notice: Array to string conversion in /opt/local/www/doctrine2/lib/vendor/doctrine-dbal/lib/Doctrine/DBAL/Connection.php on line 613) I've tracked the "problem" down to the `BasicEntityPersister`: `BasicEntityPersister::*getSelectEntitiesSQL()`, which uses `BasicEntityPersister::_getSelectConditionSQL()`, correctly creates a query containing something like `WHERE t0.group*id IN ( ? )`. But `BasicEntityPersister::expandParameters()` doesn't implode the array to some string that can be bound to the query. This is because it doesn't take into account that the field could be an association. I don't know if this is intended behavior, but I would think not. I've therefor altered the `BasicEntityPersister::expandParameters()` a bit: ``` none private function expandParameters($criteria) { $params = $types = array(); foreach ($criteria AS $field => $value) { if ($value === null) { continue; // skip null values. } $type = null; if (isset($this->_class->fieldMappings[$field])) { $type = Type::getType($this->_class->fieldMappings[$field]['type'])->getBindingType(); // BEGIN: Jasper N. Brouwer (14-07-2011) } else if (isset($this->_class->associationMappings[$field])) { if ($this->_class->associationMappings[$field]['isOwningSide']) { $targetClass = $this->*em->getClassMetadata($this->*class->associationMappings[$field]['targetEntity']); $targetField = $this->_class->associationMappings[$field]['joinColumns'][0]['referencedColumnName']; if (isset($targetClass->fieldMappings[$targetField])) { $type = Type::getType($targetClass->fieldMappings[$targetField]['type'])->getBindingType(); } } // END: Jasper N. Brouwer (14-07-2011) } if (is_array($value)) { $type += Connection::ARRAY*PARAM*OFFSET; } $params[] = $value; $types[] = $type; } return array($params, $types); } ``` I hope this bit of code also clarifies what I'm trying to explain a bit more...
admin added the Improvement label 2026-01-22 13:19:46 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#1607