Cannot add structure items to parent structure

Hey there!

I am having data that is collected in larger parent structure objects that in itself each hold collections of smaller child struture objects.
Now I need to loop over each of these parent structure objects, filter the child structure objects of those and then collect the filtered child structure objects in a new structure object (let’s call that one collectedStructures).

What I am doing is this:

$collectedStructures = new Structure();

$parentStructures = $page->parentStructureField()->toStructure()->map(function($ps) use(&$collectedStructures) {
  
  // [...] do lots of mapping stuff here

  $childStructures = $ps->childStructureField()->toStructure()->filter(function($cs) {
    // filter these children by certain criteria
  })->map(function($cs) use(&$collectedStructures) {
    // this is where the collecting of the filtered children should happen
    $collectedStructures->add($cs);
  });

});

The problem is that with each iteration over a parent structure, the add() method seems to jump back to index 0 and starts adding them from there to the collectedStructures.
To demonstrate what that means lets say, I would try to collect strings, the parent structure field has three entries A, B and C. Let’s also say, the first of those parent structures has 4 children, the second one only 1 and the third one two. Then, when I loop over all structures, I would first collect AAAA, then B, then CC. Instead of ending up with AAAABCC I end up with CCAA though, because in each loop the add() method overwrites the previous stuff starting from index 0.

I have tried to first write everything to an array, then loop over that array and use the add() method, but it still extracts the ids from the underlying children somehow and starts to write anything from index 0.

I believe this is a bug in the add() (or rather in the underlying append()) method as I would expect it to always just add new entries to the end of the collection, no matter what. Or are there any plausible situations, where you would want the add() or append() method to not add something to the end of the collection?

I had a look at the source and if I change this method from

    public function append(...$args)
    {
        if (count($args) === 1) {
            // try to determine the key from the provided item
            if (is_object($args[0]) === true && is_callable([$args[0], 'id']) === true) {
                return parent::append($args[0]->id(), $args[0]);
            } else {
                return parent::append($args[0]);
            }
        }

        return parent::append(...$args);
    }

to

    public function append(...$args)
    {
        if (count($args) === 1) {
            return parent::append($args[0]);
        }

        return parent::append(...$args);
    }

it works.

So my questions:
Is this indeed a bug?
If not, how can I achieve adding structure items to collectedStructures() without restarting the index at 0 for each loop?

If it is a bug, how can I fix this for now? Add a plugin with its own method myAppend() or something?

Thanks!

I don’t quite understand your code structure, why don’t you add the filtered and mapped $childStructures before you return the parent element:

$collectedStructures = new Structure();

$parentStructures = $page->parentStructureField()->toStructure()->map(function($ps) use(&$collectedStructures) {
  
  // [...] do lots of mapping stuff here

  $childStructures = $ps->childStructureField()->toStructure()->filter(function($cs) {
    // filter these children by certain criteria
  })->map(function($cs) use(&$collectedStructures) {
   
  
  });
 // this is where the collecting of the filtered children should happen
  $collectedStructures->add($childStructures);
});

Well, you seem to understand my code structure better than I do: your suggestion works! :smiley:

However, I think the add() and append() method still behave buggy as it seems it only allows to add or append structure collections to a structure object and not other structure objects? When I collected all the child structure objects in an array and looped over that outside this entire chain I posted above, I had the same problem.

But I admit, I will probably have to come up with a better and more understandable example to demonstrate what I mean. For my specific case here, I can work with the solution you just posted. Thanks a lot!