Reputation: 283
We have written us a script that allows us in Shopware 6 badges per categories. With many products crashes sometime after 5 minutes shopware crashes with the log message that the memory at php is not enough.
Have we done anything wrong here?
We have already packed the elements in an array (the graphics) and fetch them bundled from the server.
{# @var services \Shopware\Core\Framework\Script\ServiceStubs #}
{% set page = hook.page %}
{# @var page \Shopware\Storefront\Page\Product\ProductPage #}
{% set products = [] %}
{% if hook.page.cmsPage.type === 'product_list' %}
{% foreach hook.page.cmsPage.sections as section %}
{% foreach section.blocks as sectionBlock %}
{% if sectionBlock.type !== 'product-listing' %}
{% continue %}
{% endif %}
{% foreach sectionBlock.slots as slot %}
{% if slot.type !== 'product-listing' %}
{% continue %}
{% endif %}
{% foreach slot.data.listing.entities as product %}
{% set products = products|merge([product]) %}
{% endforeach %}
{% endforeach %}
{% endforeach %}
{% endforeach %}
{% endif %}
{% set categoryIds = products|reduce((carry, v) => carry|merge(v.categoryTree), []) %}
{% if categoryIds %}
{% set categories = services.repository.search('category', {'ids': categoryIds}) %}
{% set mediaIds = [] %}
{# Loop through all products and collect media ids #}
{% foreach products as product %}
{% set badgeList = [] %}
{% foreach categories.entities.getList(product.categoryTree) as category %}
{% if category.customFields.minds_cd_show_badge %}
{% set badgeList = badgeList|merge([{
'priority': category.customFields.minds_cd_badge_priority,
'mediaId': category.customFields.minds_cd_badge
}]) %}
{% endif %}
{% endforeach %}
{% set badge = (badgeList|sort((a, b) => a.priority <=> b.priority))|last %}
{% if badge %}
{% set mediaIds = mediaIds|merge([ badge.mediaId ]) %}
{% endif %}
{% endforeach %}
{# Get all badge media ids in a performant way #}
{% set mediaCollection = services.repository.search('media', {'ids': mediaIds}) %}
{# Loop through all products again and attach the badge #}
{% foreach products as product %}
{% set badgeList = [] %}
{% foreach categories.entities.getList(product.categoryTree) as category %}
{% if category.customFields.minds_cd_show_badge %}
{% set badgeList = badgeList|merge([{
'priority': category.customFields.minds_cd_badge_priority,
'mediaId': category.customFields.minds_cd_badge
}]) %}
{% endif %}
{% endforeach %}
{% set badge = (badgeList|sort((a, b) => a.priority <=> b.priority))|last %}
{% if badge %}
{% set badgeMedia = mediaCollection.get(badge.mediaId) %}
{% do product.addArrayExtension('mcb', {
'badge': badgeMedia
}) %}
{% endif %}
{% endforeach %}
{% endif %}
Upvotes: 0
Views: 99
Reputation: 13161
I think a real performance killer here might be that you potentially fetch a lot of categories. At least that could be the case if the category tree has many levels, with many categories on each level and products are assigned to multiple categories on different branches.
If I read this correctly you're really only interested in categories that have the custom field minds_cd_show_badge
set to true
. I assume those would potentially far less categories than the total number of entities you're fetching right now.
You could try setting a filter in your criteria targeting your custom field so you're only fetching the categories that are relevant in your case.
{% set criteria = {
'ids': categoryIds,
'filter': [
{ 'field': 'customFields.minds_cd_show_badge', 'type': 'equals', 'value': true }
]
} %}
{% set categories = services.repository.search('category', criteria) %}
Upvotes: 1