Doctrine 1
  1. Doctrine 1
  2. DC-1050

Doctrine_Relation_ForeignKey ignores ATTR_COLL_KEY attribute

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Critical Critical
    • Resolution: Unresolved
    • Affects Version/s: 1.2.3
    • Fix Version/s: None
    • Component/s: Attributes, Relations
    • Labels:
      None
    • Environment:
      Windows 7 64Bit
      PHP 5.3
      Symfony 1.4

      Description

      Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

      $coll = $this->getTable()>getConnection()>query($dql, $id);
      $related = $coll[0];

      As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

      $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

      Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

      // program 1:

      $m = new Main();
      $m->name = 'M1';
      $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
      $m->setForeignB(new ForeignB());
      $m->save();

      // program 2:

      $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
      $m->getForeignA()->exists(); // false
      $m->getForeignB()->exists(); // true

      -------------------------

      The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

      You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

      -------------------------

      Edit:

      Doctrine_Connection::queryOne() is affected as well!

      A solution is to replace

      $coll = $this->getTable()>getConnection()>query($dql, $id);
      $related = $coll[0];

      by

      $related = $this->getTable()>getConnection()>query($dql, $id)->getFirst();

        Activity

        Uli Hecht created issue -
        Uli Hecht made changes -
        Field Original Value New Value
        Description Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        Now consider you run functional tests in a Symfony project: The problem disappears since you only have a single sfContext for multiple requests. I.e. this issue causes an inconsistent behavior. This is why I wrote "program 1" and "program 2" above.
        Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

        You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

        -------------------------

        Edit:

        Doctrine_Connection is affected as well.

        A solution is to replace
        Uli Hecht made changes -
        Description Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

        You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

        -------------------------

        Edit:

        Doctrine_Connection is affected as well.

        A solution is to replace
        Doctrine_Relation_ForeignKey::fetchRelatedFor() executes the following code at line 70:

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        As you can see it accesses the first element by using index "0" in $coll and hence ignores a modified ATTR_COLL_KEY-setting, for instance:

        $this->setAttribute(Doctrine_Core::ATTR_COLL_KEY, 'id');

        Fortunately I had two models (ForeignA and ForeignB) in my project which both have an one-to-one relation to a third model (Main). That helped me finding this bug which causes the following strange behavior:

        // program 1:

        $m = new Main();
        $m->name = 'M1';
        $m->setForeignA(new ForeignA()); // has ATTR_COLL_KEY changed to 'id'
        $m->setForeignB(new ForeignB());
        $m->save();

        // program 2:

        $m = Doctrine_Core::getTable('M1')->findOneBy('name', 'M1');
        $m->getForeignA()->exists(); // false
        $m->getForeignB()->exists(); // true

        -------------------------

        The big problem about this issue is that behavior is inconsistent. If you don't split the example above into two separate programs/processes you won't have problems, since Doctrine accesses the reference which was stored when calling save().

        You will get into trouble using functional tests in Symfony. Since there is only a single process for all requests I wasn't able to reproduce a problem caused by this bug which appeared in the production environment.

        -------------------------

        Edit:

        Doctrine_Connection::queryOne() is affected as well!

        A solution is to replace

        $coll = $this->getTable()->getConnection()->query($dql, $id);
        $related = $coll[0];

        by

        $related = $this->getTable()->getConnection()->query($dql, $id)->getFirst();
        Uli Hecht made changes -
        Attachment ForeignKey.php.patch [ 11167 ]
        Guilherme Blanco made changes -
        Fix Version/s 1.2.4 [ 10063 ]

          People

          • Assignee:
            Jonathan H. Wage
            Reporter:
            Uli Hecht
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: