Doctrine 1
  1. Doctrine 1
  2. DC-329

Problem saving Self Referencing (Nest Relations)

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.2.0
    • Fix Version/s: None
    • Component/s: Relations
    • Labels:
      None
    • Environment:
      Mac OSX 10.5, Symfony 1.4 and MAMP

      Description

      There is a problem when you save Many to Many Self Referencing (Nest Relations).

      I used the same example that it's used on Doctrine 1.2 Self Referencing (Nest Relations) Documentation:

      My Schema:

      User:
      columns:
      name:

      Unknown macro: { type}

      relations:
      Parents:
      class: User
      local: child_id
      foreign: parent_id
      refClass: UserReference
      foreignAlias: Children

      UserReference:
      columns:
      parent_id:
      type: integer
      primary: true
      child_id:
      type: integer
      primary: true

      Fixtures:

      User:
      james:
      name: James
      alexander:
      name: Alexander
      david:
      name: David

      The problem happens with the Children. The first time I assigned children and saved the User, there is no problem; but when I saved the User again (without any change on him) the values in the UserReference? table changes: the "parent_id" takes the value of the "child_id".

      I test it with Sf 1.4 and with Sf 1.3 stable versions, and I've got the same error.

      If it not clear to understand what I'm saying, I put a "very ilustrative" image about the form and how change the values of the UserReference? table. Please see it, because it would be very usefull for understanding (explains better than my terrible English)

      Thanks for all your work!

      P. D.

      I forgot to to say that watching the stack trace I think that the problem is in:

      symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/UnitOfWork.php

      In the line 429:

      public function saveAssociations(Doctrine_Record $record)

      I would like to help more, but I couldn't figure out how this function works.

      1. schema.yml
        0.4 kB
        Filippo De Santis
      2. testEqualNestRelationsTest.php
        4 kB
        Filippo De Santis
      3. testNestedEqualRelationWithObjectsTest.php
        3 kB
        Filippo De Santis
      1. saving process.png
        63 kB

        Activity

        Hide
        Daniel Reiche added a comment - - edited

        after stumbling into the same pit as everyone, i created a fresh report as DC-958. Later I found out that it has been reported before, so please mark DC-958 as duplicate of this. (or at least related, as I was using a Non-Equal Nested Set) also DC-952 refers to the same problem, but also with Non-Equal nestet sets.

        My Case: Non-Equal-Nested-Set. Problems occur on saving Objects for 2nd or more time. Doctrine deletes all Child-Relations of the Object to be saved and updates Relations of the Childs to other Objects (other parents of the children objects) with references to the child itself!

        the proposed h2aEqualable extension does prevent the wrong update statements but not the initial delete of the child-relations.

        What exactly is missing on this bug to be fixed? It is now a year old, and clearly preventing people from using Self-Referencing relations with doctrine.

        How can we help? More sample data, schema definitions, test cases?

        Show
        Daniel Reiche added a comment - - edited after stumbling into the same pit as everyone, i created a fresh report as DC-958 . Later I found out that it has been reported before, so please mark DC-958 as duplicate of this. (or at least related, as I was using a Non-Equal Nested Set) also DC-952 refers to the same problem, but also with Non-Equal nestet sets. My Case: Non-Equal-Nested-Set. Problems occur on saving Objects for 2nd or more time. Doctrine deletes all Child-Relations of the Object to be saved and updates Relations of the Childs to other Objects (other parents of the children objects) with references to the child itself! the proposed h2aEqualable extension does prevent the wrong update statements but not the initial delete of the child-relations. What exactly is missing on this bug to be fixed? It is now a year old, and clearly preventing people from using Self-Referencing relations with doctrine. How can we help? More sample data, schema definitions, test cases?
        Hide
        Francesco Levorato added a comment - - edited

        Here is a better and simpler test case for the equal relation: https://gist.github.com/827414

        There is clearly a memory problem here. I'll leave it up to Jonathan to decide whether it's a scenario which can be avoided in Doctrine itself or must be handled by Symfony (http://trac.symfony-project.org/ticket/9398).

        In the Symfony context calls to refresh() might not be an option when modifying an object (aka saving a form).

        Show
        Francesco Levorato added a comment - - edited Here is a better and simpler test case for the equal relation: https://gist.github.com/827414 There is clearly a memory problem here. I'll leave it up to Jonathan to decide whether it's a scenario which can be avoided in Doctrine itself or must be handled by Symfony ( http://trac.symfony-project.org/ticket/9398 ). In the Symfony context calls to refresh() might not be an option when modifying an object (aka saving a form).
        Hide
        Yitzchak Schaffer added a comment -

        h2aEqualable seems to work for me.

        Show
        Yitzchak Schaffer added a comment - h2aEqualable seems to work for me.
        Hide
        Pavel Campr added a comment -

        h2aEqualable works only partly for me (same as Daniel Reiche wrote).

        I tried to identify the problem.

        My usecase was:
        1) I have an Article record in $article
        2) I called $article->RelatedArticles->getPrimaryKeys() , where RelatedArticles is a name of my self reference
        3) $article->save();

        The problem originates from step 2), during hydratation process for related articles, which are added to a collection of related articles, in Collection->add() method (line 465) here:

        if ($value !== null)

        { $record->set($this->referenceField, $value, false); }

        else {

        but, $this->referenceField contains wrong name of reference field. Self referenced model (Article) has two relations to the same class (one from "owning" side, second from "referencing" side). $this->referenceField in the collection is somewhere filled with the wrong relation name (not the"referencing" one, but the "owning" one).

        When I save the $article, all referenced records are saved too and this is the problem, why the Doctrine tries to save corrupted data:

        In my example, I have this data:

        in Doctrine_Collection->add on line 457: $record) is a RelatedArticle (
        article1 = string(1) "4"
        article2 = string(1) "9"
        )
        in Doctrine_Collection->add on line 458: $this->referenceField) = string(19) "article1"
        in Doctrine_Collection->add on line 459: $value) = string(1) "9"

        BUT expected data is:

        in Doctrine_Collection->add on line 458: $this->referenceField) = string(19) "article2"

        This wrong behavior modified my RelatedArticle into this: RelatedArticle (
        article1 = string(1) "9"
        article2 = string(1) "9"
        )

        I have no idea how to fix it, but maybe someone can, I hope

        (
        my schema is:

        Article
        relations:
        RelatedArticles:
        class: Article
        local: article1
        foreign: article2
        refClass: RelatedArticle
        )

        Maybe, when "refClassRelationAlias" option was invented to specifically point to a relation, instead of using "refClass", which can be used more times for one record and thus is not unambiguous, something for self referenced relations should be added as well. My "refClass: RelatedArticle" creates (probably) a relation from the foreign side too and Article contains two relations, which uses same refClass. Doctrine then doesn't know, which one should be used.

        Show
        Pavel Campr added a comment - h2aEqualable works only partly for me (same as Daniel Reiche wrote). I tried to identify the problem. My usecase was: 1) I have an Article record in $article 2) I called $article->RelatedArticles->getPrimaryKeys() , where RelatedArticles is a name of my self reference 3) $article->save(); The problem originates from step 2), during hydratation process for related articles, which are added to a collection of related articles, in Collection->add() method (line 465) here: if ($value !== null) { $record->set($this->referenceField, $value, false); } else { but, $this->referenceField contains wrong name of reference field. Self referenced model (Article) has two relations to the same class (one from "owning" side, second from "referencing" side). $this->referenceField in the collection is somewhere filled with the wrong relation name (not the"referencing" one, but the "owning" one). When I save the $article, all referenced records are saved too and this is the problem, why the Doctrine tries to save corrupted data: In my example, I have this data: in Doctrine_Collection->add on line 457: $record) is a RelatedArticle ( article1 = string(1) "4" article2 = string(1) "9" ) in Doctrine_Collection->add on line 458: $this->referenceField) = string(19) "article1" in Doctrine_Collection->add on line 459: $value) = string(1) "9" BUT expected data is: in Doctrine_Collection->add on line 458: $this->referenceField) = string(19) "article2" This wrong behavior modified my RelatedArticle into this: RelatedArticle ( article1 = string(1) "9" article2 = string(1) "9" ) I have no idea how to fix it, but maybe someone can, I hope ( my schema is: Article relations: RelatedArticles: class: Article local: article1 foreign: article2 refClass: RelatedArticle ) Maybe, when "refClassRelationAlias" option was invented to specifically point to a relation, instead of using "refClass", which can be used more times for one record and thus is not unambiguous, something for self referenced relations should be added as well. My "refClass: RelatedArticle" creates (probably) a relation from the foreign side too and Article contains two relations, which uses same refClass. Doctrine then doesn't know, which one should be used.
        Hide
        Pavel Campr added a comment -

        Non-equal nest relations work properly, when refClassRelationAlias undocumented option is used, e.g.

        Article:
        ...
        relations:
        RelatedArticles:
        class: Article
        local: article1
        foreign: article2
        refClass: RelatedArticle
        refClassRelationAlias: RelatedArticleAlias

        Anything can be used as a value for refClassRelationAlias.

        Unfortunately, this doesn't fix equal nest relations.

        Show
        Pavel Campr added a comment - Non-equal nest relations work properly, when refClassRelationAlias undocumented option is used, e.g. Article: ... relations: RelatedArticles: class: Article local: article1 foreign: article2 refClass: RelatedArticle refClassRelationAlias: RelatedArticleAlias Anything can be used as a value for refClassRelationAlias. Unfortunately, this doesn't fix equal nest relations .

          People

          • Assignee:
            Jonathan H. Wage
            Reporter:
            Jaime Suez
          • Votes:
            14 Vote for this issue
            Watchers:
            14 Start watching this issue

            Dates

            • Created:
              Updated: