Typical issues that only happens to me - #3
Probably for people coming from Magento...
Working in a feature for a Shopware instance I had to implement the order by position on a categories list.
Started looking at the code and I've quickly found the place where the collection was been used (there were some custom filters been applied > note this will be important later), so I though: - alright! here's the place where the sort should go.
Then looking for the sorting methods the first approach I've found was something like this:
$criteria->addSorting(new FieldSorting('afterCategoryId'));
Which looked pretty straight forward, but in a second test I've realize that we didn't have any field to really sort the categories like in the tree at that level.
Back to search and in a bit deep look found exactly what I was looking for: something as simple as the method "sortByPosition" in the CategoryCollection, what better than that, right?
The result:
$categories = $result->get('category_' . $identifier) ->getEntities() // this will return Shopware\Core\Content\Category\CategoryCollection ->sortByPosition() // which allow as to apply the sort by position ->getElements();
Obviously this worked perfectly LOCALLY, deployed to the TEST server and no matter what obviously this didn't worked.
The crazy weird issue was causing multiple weird behaviors (which all made the root of the issue difficult to find and fix), in summary:
- The first category in the tree was been removed (tried moving categories until I confirmed that only the first one was the one missing).
- The order of the categories was mixed.
At this point I had another a lot more experienced developer in Shopware with me also analyzing the issue (Brent Robert > if anyone asks me, this guy RULES!), just to make sure I wasn't missing anything really small and also because I wasn't able to reproduce the issue at all in my local environment.
In between I've got a new database dump from the TEST server and was able to reproduce the issue, but after reorder the categories everything started to work fine again and I wasn't able to reproduce the issue anymore.
Long story short: after some time debugging, of course Brent found the cause!
The problem was that one of the filters was to remove a single category we didn't wanted to display:
$criteria->addFilter(new NotFilter( NotFilter::CONNECTION_AND, [ new EqualsFilter('id', $removeCategory), ] ));
This was breaking the "sortByPosition" method from the CategoryCollection, the question is WHY??? > WHY TO ME??? > LOL
In more or less Brent's words, the "sortByPosition" was using the "afterCategoryId" field to do the job, so imagine you have a category collection with A, B, C, D where D is after C, C is after B, B is after A > now remove B and try to sort that!
That's what our $removeCategory filter was doing basically...
The fix:
Move the filter and apply it to the collection:
$categories = array_filter($categories, function ($item) use ($removeCategory) { return $item->getId() !== $removeCategory; });
For last: why this is probably for people coming from Magento? Well... I've assumed that the sort was been applied at query level before hit the database along with the criteria, but I couldn't be more wrong, when you work with a collection in Shopware and you see the getEntities method you already have an Iterator with an array of elements, so you are not preparing the collection like you used to do in Magento to later load the entities. Because of that I didn't deep checked what the sortByPosition was really doing and not getting to find the root of the issue.
Does this kind of issues only happens to me? Something as simple as a collection sort almost turned out in a nightmare...
Later Brent told me: don't bring this kind of issues to me on a Friday at 3pm or I'm going to get mad. - LOL
Thanks Brent! You are the best!