Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-251

ArrayCollection::__construct() must be an array, object given

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-ALPHA4
    • Fix Version/s: 2.0-ALPHA4
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      Running index.php in the Doctrine2 sandbox results in a fatal error:
      PHP Catchable fatal error: Argument 1 passed to Doctrine\Common\Collections\ArrayCollection::__construct() must be an array, object given, called in /home/bjori/doctrine2/lib/Doctrine/ORM/UnitOfWork.php on line 468 and defined in /home/bjori/doctrine2/lib/Doctrine/Common/Collections/ArrayCollection.php on line 53

      Unsure what exactly is going on, but this is the smallest reproduce case I have managed to create.

      1. Collection.php
        0.9 kB
        Hannes Magnusson
      2. index.php
        2 kB
        Hannes Magnusson

        Activity

        Hide
        Roman S. Borschel added a comment -

        I think I've found the issue. Its a bug in the lazy-load code of OneToOneMapping (which is also used for ManyToOne).

        I am going to fix it.

        Note, however, that self-referencing association + inheritance on a base type is currently a very bad combination because it basically causes the whole object tree to be loaded (the whole table). Say we have a standard parent-child (one-to-many) without inheritance. Each object has 1 parent and many children. When you query for any object (without joining anything) the children field is set to an empty collection and the parent field is set to a proxy object, so only 1 database query as expected.

        Now comes inheritance into the game. More specifically, if the targetEntity of the "parent" field is not an outermost subtype. That causes Doctrine to not be able to use a proxy as the parent, because the proxy might have the wrong type! So it is forced to load the object.

        Show
        Roman S. Borschel added a comment - I think I've found the issue. Its a bug in the lazy-load code of OneToOneMapping (which is also used for ManyToOne). I am going to fix it. Note, however, that self-referencing association + inheritance on a base type is currently a very bad combination because it basically causes the whole object tree to be loaded (the whole table). Say we have a standard parent-child (one-to-many) without inheritance. Each object has 1 parent and many children. When you query for any object (without joining anything) the children field is set to an empty collection and the parent field is set to a proxy object, so only 1 database query as expected. Now comes inheritance into the game. More specifically, if the targetEntity of the "parent" field is not an outermost subtype. That causes Doctrine to not be able to use a proxy as the parent, because the proxy might have the wrong type! So it is forced to load the object.
        Hide
        Roman S. Borschel added a comment -

        I'll make this clear in an example.

        The following is unproblematic:

        class Category {
           private $parentCategory;
           private $childCategories;
        }
        

        The following is also unproblematic, where the parent always is an outermost subtype:

        class Category {
           private $parentCategory; // targetEntity="SpecialCategory"
           private $childCategories;
        }
        class SpecialCategory extends Category {
        }
        

        The following however is problematic:

        class Category {
           private $parentCategory; // targetEntity="Category"
           private $childCategories;
        }
        class SpecialCategory extends Category {
        }
        class AnotherSpecialCategory extends Category {
        }
        

        Doctrine cant put a CategoryProxy into "parent", because "parent" might be a subtype (SpecialCategory or AnotherSpecialCategory) thus it does not know which proxy to use.

        To better solve this it would require transparently joining at least the discriminator column of the parent entity but that is a quite tricky.

        Show
        Roman S. Borschel added a comment - I'll make this clear in an example. The following is unproblematic: class Category { private $parentCategory; private $childCategories; } The following is also unproblematic, where the parent always is an outermost subtype: class Category { private $parentCategory; // targetEntity= "SpecialCategory" private $childCategories; } class SpecialCategory extends Category { } The following however is problematic: class Category { private $parentCategory; // targetEntity= "Category" private $childCategories; } class SpecialCategory extends Category { } class AnotherSpecialCategory extends Category { } Doctrine cant put a CategoryProxy into "parent", because "parent" might be a subtype (SpecialCategory or AnotherSpecialCategory) thus it does not know which proxy to use. To better solve this it would require transparently joining at least the discriminator column of the parent entity but that is a quite tricky.
        Hide
        Roman S. Borschel added a comment -

        Should be fixed now.

        Show
        Roman S. Borschel added a comment - Should be fixed now.
        Hide
        Hannes Magnusson added a comment -

        Thanks for the explanation, and the fix!

        Show
        Hannes Magnusson added a comment - Thanks for the explanation, and the fix!

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            Hannes Magnusson
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: