简体   繁体   中英

Alternative to template_from_string for processing strings with calls to custom Twig functions

Is there an alternative to using template_from_string() for evaluating strings that contain calls to custom Twig functions (or any other complex Twig code for that matter)?

This is a simplified version of the code I have right now.

{% set content = {
    'item_1' : {
        'images' : {
            'src': 'assets/images/img_1-600.jpg',
            'srcset': "{{ assets('assets/images/img_1-600.jpg') }} 600w, {{ assets('assets/images/img_1-1200.jpg') }} 1200w",
        }
    }
    # additional items follow
}

{% for data in content %}
    <img src="{{ data.images.src }}" srcset="{{ include(template_from_string(data.images.srcset)) }}" alt="">
{% endfor %}

The assets() function simply returns a revisioned version of the static asset for the given path (ie assets('assets/images/img_1-600.jpg) renders as something like 'assets/images/img_1-600-a4c2254a6d.jpg) .

The problems start with img srcset attribute which can become pretty complex and usually contains references to multiple assets that need to return revisioned values for static assets.

Now I know that I could modify the assets() function to support that kind of complex scenario but I'd like to keep things simple and let assets() only handle 1:1 transformations.

The only way to achieve this by using functionality provided by Twig seems to be template_from_string() combined with include, which in itself is not terrible but it does kind of look bulky for a simple operation as evaluating and rendering a string.

Not to mention that template_from_string requires StringLoaderExtension() to be loaded by default, which again I'd like to avoid using for performance reasons.

To avoid any extra plugins, you could just concat the variables

{% set content = {
    'item_1' : {
        'images' : {
            'src': 'assets/images/img_1-600.jpg',
            'srcset': assets('assets/images/img_1-600.jpg')~'  600w,'~assets('assets/images/img_1-1200.jpg')~' 1200w',
        }
    }
} %}

While the concatenation approach is not a bad idea, after much consideration I came to the conclusion that this is one of those places where having a custom Twig function makes much more sense.

The main argument in favor of using a function compared to simple concatenation is that with a function there is no need to worry about properly formating the template code (ie forget a space between the asset and the size descriptor in the srcset attribute value).

This approach also completely eliminates any need to use template_from_string() or additional extension dependencies.

Here is the final solution.

The template code, plain and simple, with plenty of overview.

{% set content = {
    'item_1' : {
        'images' : {
            'src': 'assets/images/img-600.jpg',
            'srcset': srcset([
                [ assets('assets/images/img-600.jpg'), '600w' ],
                [ assets('assets/images/img-800.jpg'), '800w' ],
                [ assets('assets/images/img-1000.jpg'), '1000w' ],
                [ assets('assets/images/img-1200.jpg'), '1200w' ]
            ]),
        }
    }
    # additional items follow
}

{% for data in content %}
    <img src="{{ data.images.src }}" srcset="{{ data.images.srcset }}" alt="">
{% endfor %}

The actual Twig function called srcset , that is used to generate a value for the srcset attribute from provided data in the above template.

public function srcset(array $srcset)
{
    $output = [];
    foreach ($srcset as $set) {
        // Both parameters need to exist or the set isn't added to the output...
        if (!(isset($set[0]) && isset($set[1]))) {
            // ... just some exception handling that isn't of relevance for the question
            // ...
            continue;
        }
        $output[] = sprintf('%s %s', $set[0], $set[1]);
    }

    return implode(', ', $output);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM