Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-16

DQL Ignores properties of subclasses

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: 2.0-ALPHA2
    • Fix Version/s: None
    • Component/s: DQL
    • Security Level: All
    • Labels:
      None

      Description

      I have a classes B and C which inherit from superclass A. I would like
      to get a list of all A's but filter the list to ignore those in C
      which have a property d set to 2.

      select a from A where a.d == 2 fails because "d" is not a property of A.

        Issue Links

          Activity

          Hide
          Glen Ainscow added a comment -

          Yes I know that, I'm just making sure that I understand the syntax.

          Show
          Glen Ainscow added a comment - Yes I know that, I'm just making sure that I understand the syntax.
          Hide
          Jaka Jancar added a comment -

          I just ran into a similar problem and am not sure the above cast solution would do.

          I'm trying to do:

          SELECT
              s
          FROM
              Superclass s
          WHERE
              s INSTANCE OF SubclassA OR
              s INSTANCE OF SubclassB AND s.foo = 'bar';
          

          So I'd need to use CAST in a WHERE condition, not in the FROM/JOIN clause, e.g:

          SELECT
              s
          FROM
              Superclass s
          WHERE
              s INSTANCE OF SubclassA OR
              s INSTANCE OF SubclassB AND (CAST s AS SubclassB).foo = 'bar';
          
          Show
          Jaka Jancar added a comment - I just ran into a similar problem and am not sure the above cast solution would do. I'm trying to do: SELECT s FROM Superclass s WHERE s INSTANCE OF SubclassA OR s INSTANCE OF SubclassB AND s.foo = 'bar'; So I'd need to use CAST in a WHERE condition, not in the FROM/JOIN clause, e.g: SELECT s FROM Superclass s WHERE s INSTANCE OF SubclassA OR s INSTANCE OF SubclassB AND (CAST s AS SubclassB).foo = 'bar';
          Hide
          Wladimir Coka added a comment -

          Is there any workaround? Would be perfect if I could just:

           SELECT a, p FROM Article a JOIN CAST(a.person AS User) p 

          (+1 for Guilherme Blanco possible solution)

          Show
          Wladimir Coka added a comment - Is there any workaround? Would be perfect if I could just: SELECT a, p FROM Article a JOIN CAST(a.person AS User) p (+1 for Guilherme Blanco possible solution)
          Hide
          Wladimir Coka added a comment -

          I was trying a workaround:

          Before executing the dql query, I change the mapping info of the association to the concrete type that I was going to use. Like this:

                  $cmf = $this->em->getMetadataFactory();
                  $class = $cmf->getMetadataFor("Article");
                  $class->associationMappings["person"]["targetEntity"]="User";
          

          But now my problem is that I'm actually using an inverse side (in query where this is needed), so when I change the targetEntity, the sql join that is generated, is using the table of the concrete class (User in this case) and not the base class (Person)

          class Person {
          ...
          	/**
          	 * @OneToOne(targetEntity="Order",cascade={"persist"})
          	 * @JoinColumn(name="order_id", referencedColumnName="orden_id")
          	 */
          	private $order;
          ...
          }
          
          class Order {
          ...
              /**
               * @OneToOne(targetEntity="Person", mappedBy="order")
               */
              private $person;
          ...
          }
          
          

          The SQL generated is joining as if the "user" table has orden_id field

          Show
          Wladimir Coka added a comment - I was trying a workaround: Before executing the dql query, I change the mapping info of the association to the concrete type that I was going to use. Like this: $cmf = $this->em->getMetadataFactory(); $class = $cmf->getMetadataFor("Article"); $class->associationMappings["person"]["targetEntity"]="User"; But now my problem is that I'm actually using an inverse side (in query where this is needed), so when I change the targetEntity, the sql join that is generated, is using the table of the concrete class (User in this case) and not the base class (Person) class Person { ... /** * @OneToOne(targetEntity="Order",cascade={"persist"}) * @JoinColumn(name="order_id", referencedColumnName="orden_id") */ private $order; ... } class Order { ... /** * @OneToOne(targetEntity="Person", mappedBy="order") */ private $person; ... } The SQL generated is joining as if the "user" table has orden_id field
          Hide
          Marco Pivetta added a comment -

          I am closing this one.

          The requirement of this issue is basically violating OO principles.

          If you really need to filter across multiple child-entities in your inheritance, then try something as following instead:

          SELECT
              r
          FROM
              Root r
          WHERE
              r.id IN (
                  SELECT
                      c.id
                  FROM
                      Child c
                  WHERE
                      c.field = :value
              )
          

          Up-casting is not really a viable solution anyway, since it would be even more weird to cast in DQL and then have hydration still retrieve the root entity type.

          Show
          Marco Pivetta added a comment - I am closing this one. The requirement of this issue is basically violating OO principles. If you really need to filter across multiple child-entities in your inheritance, then try something as following instead: SELECT r FROM Root r WHERE r.id IN ( SELECT c.id FROM Child c WHERE c.field = :value ) Up-casting is not really a viable solution anyway, since it would be even more weird to cast in DQL and then have hydration still retrieve the root entity type.

            People

            • Assignee:
              Marco Pivetta
              Reporter:
              Avi Block
            • Votes:
              6 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: