Fetching Images by ID in Shopware Storefront .twig files

Fetching images from the storefront .twig files can be done using the searchMedia function, or alternatively, by using an element resolver for your cms element.

99 views
d

By. Jacob

Created: 2023-10-08 21:26

{% set myMedia = searchMedia(['ed6d0b38ebd342rma634ha4ddef53559'], context.context) %}
{% set myMediaEntity = myMedia.first() %}

Sometimes you may need to fetch a media entity from Shopware's storefront .twig files. E.g. To use with other functions in the storefront. One such function is the sw_thumbnails function, which will automatically output an img element with the correct width, height, and srcset attributes. But, this function will only accept a media entity object (E.g. Of type Shopware\Core\Content\Media\MediaEntity). You will need to somehow obtain this first.

I learned two ways to fetch a media entity:

  1. Using the searchMedia() function (easiest).
  2. Creating a xxxCmsElementResolver.php

Hopefully this will be improved in the future, because I think it is too convoluted having to first fetch a media entity – developers should be able to just feed the ID directly.

Fetching a MediaEntity by ID

Creating an element resolver was the first solution I found; it was a simple hunch that led me in that direction. It is not super hard, but still adds a bit too much superfluous code for my liking.

In my opinion, this is not something developers should be bothered with, so I tried searching for a more simple solution; this brought me to the searchMedia() function. The advantage of this function is that we can use it directly within our .twig template files in the storefront, but unfortunately, it also adds extra "logic" to the template code, which is something I try to avoid.

Using the searchMedia function

The searchMedia() function needs two arguments:

  1. An array of media IDs (an array containing a single ID will also work)
  2. A context object.

You can fetch the media ID from your back-end; if you are creating a custom CMS element in Shopware's vue.js based administration, then you would typically store the ID for your image in a property of the element.config object. This is automatically saved when the user hits "save" in the administration backend after picking an image – assuming your element is working of course. But, once it is saved, it should automatically become available in the storefront .twig.

The context may be available in twig via context.context; if you are in doubt about what is available to you, try doing a {{ dump() }} from within your storefront .twig, then it should output a collapsible / expandable list of available objects and properties to you. Make sure caching is disabled, and also, you may need to hit update in your browser a few times to see the output.

To fetch the relevant media, you can simply do like this:

{% set myMedia = searchMedia(['ed6d0b38ebd342rma634ha4ddef53559'], context.context) %}}

Then, because we are only fetching a single image, you can use the first() method to return the result. If you had provided multiple IDs, you would instead have had to loop over the result object.

{% set myMediaEntity = myMedia->first() %}

Using the sw_thumbnails function

Using the sw_thumbnails function can be done like this:

{% sw_thumbnails 'cms-image-thumbnails' with { media: myMediaEntity } %}

If you also need to add a custom class name to your img element, you should do like this instead:

{% set attributes = {
    'class': 'nameOfMyClass',
    'alt': myMediaEntity.translated.alt,
    'title': myMediaEntity.translated.title
} %}
{% sw_thumbnails 'cms-image-thumbnails' with { media: myMediaEntity } %}

This way you can also get the translated alt attribute content.

However, this behaviour is a bit "magical", because there is no visible logical connection between the attributes variable we set above and sw_thumbnails. Presumably it is automatically accessed by the sw_thumbnails function – I hate behaviour like this, because it is not clear that it is connected to sw_thumbnails.

In addition to all of the above, I will recommend you take the time to implement the sw-media-upload-v2 component to select images rather than the sw-media-field selector, as it is way more user-friendly. I was initially using the latter, and eventually I just sat down to figure out how to use the "v2" component – it may have taken only a couple of hours to figure out. You can try looking at existing usage of the "v2" component in Shopware core.

In comparison, the amount of code to get sw-media-upload-v2 working is just horrendous, but maybe I am doing something wrong. Imo. I prefer using the sw-media-field for simplicity in my code, but the usability offered by the "v2" component is just miles ahead.

Links

  1. Shopware's twig functions - developer.shopware.com

Tell us what you think:

  1. Sometimes we may to manually clear cached Shopware files to fix namespace issues.
  2. How to obtain the currently selected API language from Shopware vue components.
  3. How to access file system paths from storefront twig files in Shopware.
  4. How to get or change the currently selected sales channel in an Shopware sw-sales-channel-switch component.
  5. In this tutorial you will learn how to work with Shopware entities in a generic way from PHP, without having to specifically inject the repository in your services.xml file.

More in: Shopware