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.
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:
- Using the searchMedia() function (easiest).
- 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:
- An array of media IDs (an array containing a single ID will also work)
- 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
- Shopware's twig functions - developer.shopware.com
Tell us what you think: