DDC-1975: Binding entities to query parameters throws exception on new entity #2494

Closed
opened 2026-01-22 13:55:09 +01:00 by admin · 4 comments
Owner

Originally created by @doctrinebot on GitHub (Aug 10, 2012).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user goetas:

I have this entities:

class User{
    /****
    * ...
    */
    protected $id;
    /****
     * @ManyToOne(targetEntity="Phone")
     * @JoinColumn(name="address_id", referencedColumnName="id")
     */
    protected $phone;
}

class Phone{
    /****
    * ...
    */
    protected $id;
}

when run this query:

$phone = new Phone();

$dql = $em->createQueryBuilder();
$dql->from("User", "u");
$dql->andWhere("u.phone = :phone");     
$dql->setParameter("phone", $phone);    

dql->getQuery()->getResult();   

i get the exception: Binding entities to query parameters only allowed for entities that have an identifier.

the expected query is:
SELECT * FROM user WHERE phone_id = NULL;

the involved ORM component is AbstractQuery::convertObjectParameterToScalarValue

changing this method, form


protected function convertObjectParameterToScalarValue($value)
{
    $class = $this->*em->getClassMetadata(get*class($value));

    if ($class->isIdentifierComposite) {
        throw new \InvalidArgumentException(
            "Binding an entity with a composite primary key to a query is not supported. " .
            "You should split the parameter into the explicit fields and bind them seperately."
        );
    }

    $values = ($this->*em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE*MANAGED)
        ? $this->_em->getUnitOfWork()->getEntityIdentifier($value)
        : $class->getIdentifierValues($value);

    $value = $values[$class->getSingleIdentifierFieldName()];

    if ( ! $value) {
        throw new \InvalidArgumentException(
            "Binding entities to query parameters only allowed for entities that have an identifier."
        );
    }

    return $value;
}

to

protected function convertObjectParameterToScalarValue($value)
{
    $class = $this->*em->getClassMetadata(get*class($value));

    if ($class->isIdentifierComposite) {
        throw new \InvalidArgumentException(
            "Binding an entity with a composite primary key to a query is not supported. " .
            "You should split the parameter into the explicit fields and bind them seperately."
        );
    }
    $state = $this->_em->getUnitOfWork()->getEntityState($value);

    $values = ($state === UnitOfWork::STATE_MANAGED)
        ? $this->_em->getUnitOfWork()->getEntityIdentifier($value)
        : $class->getIdentifierValues($value);

    $value = $values[$class->getSingleIdentifierFieldName()];

    if ( ! $value && $state !== UnitOfWork::STATE_NEW) {
        throw new \InvalidArgumentException(
            "Binding entities to query parameters only allowed for entities that have an identifier."
        );
    }

    return $value;
}

.

the modified method check if the 'phone' entity state is new, and if it is true return null.

Originally created by @doctrinebot on GitHub (Aug 10, 2012). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user goetas: I have this entities: ``` java class User{ /**** * ... */ protected $id; /**** * @ManyToOne(targetEntity="Phone") * @JoinColumn(name="address_id", referencedColumnName="id") */ protected $phone; } class Phone{ /**** * ... */ protected $id; } ``` when run this query: ``` java $phone = new Phone(); $dql = $em->createQueryBuilder(); $dql->from("User", "u"); $dql->andWhere("u.phone = :phone"); $dql->setParameter("phone", $phone); dql->getQuery()->getResult(); ``` i get the exception: **Binding entities to query parameters only allowed for entities that have an identifier.** the expected query is: SELECT \* FROM user WHERE phone_id = NULL; the involved ORM component is **AbstractQuery::convertObjectParameterToScalarValue** changing this method, form ``` java protected function convertObjectParameterToScalarValue($value) { $class = $this->*em->getClassMetadata(get*class($value)); if ($class->isIdentifierComposite) { throw new \InvalidArgumentException( "Binding an entity with a composite primary key to a query is not supported. " . "You should split the parameter into the explicit fields and bind them seperately." ); } $values = ($this->*em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE*MANAGED) ? $this->_em->getUnitOfWork()->getEntityIdentifier($value) : $class->getIdentifierValues($value); $value = $values[$class->getSingleIdentifierFieldName()]; if ( ! $value) { throw new \InvalidArgumentException( "Binding entities to query parameters only allowed for entities that have an identifier." ); } return $value; } ``` to ``` java protected function convertObjectParameterToScalarValue($value) { $class = $this->*em->getClassMetadata(get*class($value)); if ($class->isIdentifierComposite) { throw new \InvalidArgumentException( "Binding an entity with a composite primary key to a query is not supported. " . "You should split the parameter into the explicit fields and bind them seperately." ); } $state = $this->_em->getUnitOfWork()->getEntityState($value); $values = ($state === UnitOfWork::STATE_MANAGED) ? $this->_em->getUnitOfWork()->getEntityIdentifier($value) : $class->getIdentifierValues($value); $value = $values[$class->getSingleIdentifierFieldName()]; if ( ! $value && $state !== UnitOfWork::STATE_NEW) { throw new \InvalidArgumentException( "Binding entities to query parameters only allowed for entities that have an identifier." ); } return $value; } ``` . the modified method check if the 'phone' entity state is new, and if it is true return null.
admin added the Bug label 2026-01-22 13:55:09 +01:00
admin closed this issue 2026-01-22 13:55:10 +01:00
Author
Owner

@doctrinebot commented on GitHub (Aug 10, 2012):

Comment created by stof:

Returning null is wrong here. If you query for users related to your new phone object, it is not the same than querying for users without a phone (and btw, it would break in your database as u.phone_id = NULL will not be valid in SQL)

@doctrinebot commented on GitHub (Aug 10, 2012): Comment created by stof: Returning null is wrong here. If you query for users related to your new phone object, it is not the same than querying for users without a phone (and btw, it would break in your database as `u.phone_id = NULL` will not be valid in SQL)
Author
Owner

@doctrinebot commented on GitHub (Aug 10, 2012):

Comment created by goetas:

Ok, probably you are right.

Any idea to run this query without getting exceptions?
My intent is to extract users that have associated $phone as phone number.

If $phone is a new object, I expect to get an empty set after executing the query below.


$phone = new Phone();

$dql = $em->createQueryBuilder();
$dql->from("User", "u");
$dql->andWhere("u.phone = :phone");     
$dql->setParameter("phone", $phone);    

$users = $dql->getQuery()->getResult();

Currently it works because $phone->id is null and querying SELECT * FROM user WHERE phone_id = NULL will always return an empty set.

@doctrinebot commented on GitHub (Aug 10, 2012): Comment created by goetas: Ok, probably you are right. Any idea to run this query without getting exceptions? My intent is to extract users that have associated `$phone` as phone number. If `$phone` is a new object, I expect to get an empty set after executing the query below. ``` java $phone = new Phone(); $dql = $em->createQueryBuilder(); $dql->from("User", "u"); $dql->andWhere("u.phone = :phone"); $dql->setParameter("phone", $phone); $users = $dql->getQuery()->getResult(); ``` Currently it works because $phone->id is null and querying `SELECT * FROM user WHERE phone_id = NULL` will always return an empty set.
Author
Owner

@doctrinebot commented on GitHub (Aug 14, 2012):

Comment created by @asm89:

This is not a bug. See the explanation of Christophe.

You should do andWhere("u.phone IS NULL"). Note that IS NULL is not the same as = null.

@doctrinebot commented on GitHub (Aug 14, 2012): Comment created by @asm89: This is not a bug. See the explanation of Christophe. You should do andWhere("u.phone IS NULL"). Note that IS NULL is not the same as = null.
Author
Owner

@doctrinebot commented on GitHub (Aug 14, 2012):

Issue was closed with resolution "Invalid"

@doctrinebot commented on GitHub (Aug 14, 2012): Issue was closed with resolution "Invalid"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#2494