Markus Michalski FAQ

CDN Product Images: Installation

Installing the Sylius plugin CDN Product Images: Composer via Packeton, bundle, routes, setup command and the product-image template override.

Deutsche Version

Back to overview

CDN Product Images: Installation

This documentation always describes the latest published version.

Live Demo: Try this and other plugins live — no installation, no risk: demo.markus-michalski.net

Composer

Private repositories are managed via Packeton (https://packeton.markus-michalski.net). Credentials are provided after license purchase/approval.

{ "repositories": [{ "type": "composer", "url": "https://packeton.markus-michalski.net" }] }
composer require mmd/sylius-cdn-product-images-plugin

After composer require:

  1. Register the bundle in config/bundles.php:

    Mmd\SyliusCdnProductImagesPlugin\MmdSyliusCdnProductImagesPlugin::class => ['all' => true],
    
  2. Import the Admin routes - this is what makes the route the "CDN Integration" sidebar entry links to actually exist:

    # config/routes/mmd_sylius_cdn_product_images.yaml
    mmd_sylius_cdn_product_images:
        resource: '@MmdSyliusCdnProductImagesPlugin/config/routes/admin.yaml'
    
  3. Run the setup command:

    bin/console mmd:cdn-product-images:setup
    

    The command executes only this plugin's own still-open migrations - never those of the app or of other plugins - and is idempotent, so running it again after every composer update does nothing when there's no new migration. It also checks that the routes from step 2 are imported and prints the snippet above if not, without ever writing into config/ itself. If Sylius' own core migrations are still open, it stops and asks for doctrine:migrations:migrate to run first. It asks for interactive confirmation; add --no-interaction in scripts. Plain doctrine:migrations:migrate remains usable as an alternative.

  4. Install assets if not already done:

    bin/console assets:install
    

No config/packages/*.yaml entry needed - see Configuration.

Product images: making the field visible

Taxon images work right after installation (the plugin ships its own Twig Hook for that). Product images need one extra step, because Sylius' product-image form template has no hook point and no form_rest() fallback - the cdnUrl field exists on the form object either way, but nothing renders it without this override:

{# templates/bundles/SyliusAdminBundle/product/form/sections/media/images.html.twig #}
{# Full copy of @SyliusAdmin/product/form/sections/media/images.html.twig, with one added
   block for image_form.cdnUrl. Re-check against the vendor original on every Sylius minor -
   Symfony's template override replaces the whole file, it doesn't merge. #}
{% set images = hookable_metadata.context.form.images %}
{% set product = hookable_metadata.context.product %}

<div class="row" {{ sylius_test_html_attribute('images') }} {{ sylius_test_html_attribute('image-subforms') }}>
    {% for image_form in images %}
        <div class="col-12 col-md-6 row mb-4"
            {{ sylius_test_html_attribute('image-subform')}}
            {{ sylius_test_html_attribute('type', image_form.type.vars.value) }}
            {{ sylius_test_html_attribute('image-url', image_form.vars.value.path ? image_form.vars.value.path|imagine_filter('sylius_small') : null) }}
        >
            <div class="col-auto">
                <div>
                    {% if image_form.vars.value.path is not null %}
                        <span class="avatar avatar-xl" style="background-image: url('{{ image_form.vars.value.path|imagine_filter('sylius_small') }}')"></span>
                    {% else %}
                        <span class="avatar avatar-xl"></span>
                    {% endif %}
                </div>
                <div class="mt-3 d-flex items-center">
                    {{ form_widget(image_form.vars.button_delete, { label: 'sylius.ui.delete'|trans, attr: { class: 'btn btn-outline-danger w-100','data-test-image-delete': '' }}) }}
                </div>
            </div>
            <div class="col">
                <div class="mb-3">
                    {{ form_row(image_form.type, sylius_test_form_attribute('type')) }}
                </div>
                <div class="mb-3">
                    {% if product.id is not null and 0 != product.variants|length and not product.simple %}
                        {{ form_row(image_form.productVariants, sylius_test_form_attribute('product-variant', image_form.productVariants.vars.value|join(','))) }}
                    {% endif %}
                </div>
                <div class="mb-3">
                    {{ form_row(image_form.file, sylius_test_form_attribute('file')) }}
                </div>
                {% if image_form.cdnUrl is defined %}
                    <div class="mb-3">
                        {{ form_row(image_form.cdnUrl) }}
                    </div>
                {% endif %}
                {% if image_form.position is defined %}
                    <div class="mb-3">
                        {{ form_row(image_form.position, sylius_test_form_attribute('position')) }}
                    </div>
                {% endif %}
            </div>
        </div>
    {% endfor %}
</div>

Place the file in the consuming application at templates/bundles/SyliusAdminBundle/product/form/sections/media/images.html.twig (Symfony's classic bundle-template-override path) - a plugin cannot ship this override from inside its own package, only the app itself can override a vendor bundle's template.

A proper fix directly in the plugin (its own Twig Hook, the same way taxon images already have one) is in progress - once Sylius makes this template hookable, the manual override goes away.

Update

composer update mmd/sylius-cdn-product-images-plugin
bin/console mmd:cdn-product-images:setup
bin/console cache:clear

Older installations configured cdn_domain/signing_api_url/signing_api_token/cdn_scheme via environment variables and config/packages/mmd_sylius_cdn_product_images.yaml. That file must be deleted after updating - any leftover key makes the container build fail loudly instead of silently doing nothing. Re-enter the four values once via Sylius Admin afterwards, see Configuration.

Uninstallation

  1. Remove the template override and Twig Hooks from your own app (see above)
  2. Roll back the migration while the bundle is still registered:
    bin/console doctrine:migrations:execute --down "Mmd\SyliusCdnProductImagesPlugin\Migrations\Version20260911140000"
    
  3. Remove the route import (config/routes/mmd_sylius_cdn_product_images.yaml) and the bundle entry in config/bundles.php
  4. Remove the package:
    composer remove mmd/sylius-cdn-product-images-plugin