mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
QueryBuilder::setParameter() breaks if parameter name with ':' is set multiple times #6448
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @tom93 on GitHub (Apr 15, 2020).
Bug Report
3c91792dd, master @8c259ea5cSummary
QueryBuilder::setParameter()breaks if a parameter name that starts with:is set multiple times.(Parameter names that don't start with a colon can be set multiple times without issues, and normally it is allowed to prefix a parameter name with a colon.)
Current behavior
An exception is thrown when the query is executed:
How to reproduce
Expected behavior
The second snippet (with colon) should succeed and produce the same result as the first snippet.
Cause
setParameter($key, ...)checks if $key already exists usinggetParameter($key), which compares $key to the names of the existing Query\Parameter objects:8c259ea5cb/lib/Doctrine/ORM/QueryBuilder.php (L606)When $key starts with a colon, the comparison always fails because the names of the existing Query\Parameter objects are trimmed of colons in the constructor:
8c259ea5cb/lib/Doctrine/ORM/Query/Parameter.php (L49)Fix
getParameter()should trim colons from $key to match the behaviour of the Query\Parameter constructor.To avoid code duplication, the existing trimming code could be moved to a separate function such as
Query\Parameter::normalizeName().(Another approach is for
getParameter()create a dummy instance of Query\Parameter to normalize $key, but that's ugly and requires a dummy value and type.)Pull request
#8107
Background / original use case
When building complex queries with conditional parts, it can be useful to call
setParameter()multiple times with the same parameter.Here is a contrived example that lists users, optionally filtered by a pattern. It can be configured to search for users by first name, last name, or both:
Note that the
setParameter()calls cannot be combined and moved outside theifstatements, because then when both conditions are false the parameter would be unused, resulting in the following error:The QueryBuilder documentation doesn't use leading colons in parameter names passed to
setParameter(), but they are supported and are popular in some projects (maybe the practice has been adopted from PDO).