Search code examples
doctrine-ormzend-framework2zend-formzend-framework3hydration

Zend Framework child collection not hydrating properly


I have an issue with the values of a child collection not being hydrated properly. I'm using zend framework 3 with doctrine 2.

Since it's a lot of code that I would have to copy, I will describe what I'm doing and if needed I will update with code.

We have the following:

  • VillaForm which is a Form element
  • VillaFieldset which is a Fieldset element and is the base fieldset of VillaForm
  • FacilityCategoriesFieldset which is a Fieldset that is used for a Collection element in the VillaFieldset

        $this->add([
        'type' => 'Zend\Form\Element\Collection',
        'name' => 'facilityCategories',
        'options' => [
            'count' => 1,
            'allow_add' => true,
            'allow_remove' => true,
            'create_new_objects' => true,
            'target_element' => [
                'type' => FacilityCategoryFieldset::class,
            ],
        ],
    ]);
    
  • FacilitiesFieldset which is a a Fieldset that is used for a Collection element in the FacilityCategoriesFieldset

        $this->add([
        'type' => 'Zend\Form\Element\Collection',
        'name' => 'facilities',
        'options' => [
            'count' => 1,
            'allow_add' => true,
            'allow_remove' => true,
            'create_new_objects' => true,
            'target_element' => [
                'type' => FacilityFieldset::class,
            ],
        ],
    ]);
    

So viewing from above we have

VillaForm contains VillaFieldset that contains Collection of FacilityCategoriesFieldset which contains a Collection of FacilitiesFieldset

Let's say we have this example on the actual form page.

- Row A of FacilityCategoriesFieldset 
  - Row 1 of FacilitiesFieldset
  - Row 2 of FacilitiesFieldset
  - Row 3 of FacilitiesFieldset

- Row B of FacilityCategoriesFieldset 
  - Row x of FacilitiesFieldset
  - Row y of FacilitiesFieldset
  - Row z of FacilitiesFieldset

My issue is that after the form is submitted, although the post data is correct, after the hydration the result will be like so:

- Row A of FacilityCategoriesFieldset 
  - Row x of FacilitiesFieldset
  - Row y of FacilitiesFieldset
  - Row z of FacilitiesFieldset

- Row B of FacilityCategoriesFieldset 
  - Row x of FacilitiesFieldset
  - Row y of FacilitiesFieldset
  - Row z of FacilitiesFieldset

The rows of the FacilitiesFieldset of the very last row of the FacilityCategoriesFieldset are used for all the rows of FacilitiesFieldset.

This only happens when a have a fieldset with a collection with another collection. Does anyone have a hint of what I might be doing wrong? I will give you any other info/code if you need it.

Thanks a lot.


Solution

  • Your implementation of a Collection is slightly off. You shouldn't give the type of a Collection as the FQCN, but the actual object (Fieldset).

    Try this:

    /**
     * @var CustomFieldset
     */
    protected $customFieldset;
    
    public function __construct(CustomFieldset $customFieldset) {
        $this->customFieldset = $customFieldset;
    }
    
    // init()
    $this->add(
        [
            'type'     => Collection::class,
            'required' => true,
            'name'     => 'customFieldset',
            'options'  => [
                'label'                  => 'Custom fieldsets',
                'count'                  => 1,
                'allow_add'              => true,
                'allow_remove'           => true,
                'should_create_template' => true,
                'target_element'         => $this->customFieldset,
            ],
        ]
    );