Comment organiser les skins dans Symfony

Ceci est une courte note sur la façon dont vous pouvez organiser l'utilisation des skins pour les pages de marque dans Twig en utilisant l'exemple de Symfony. Cette solution n'est pas liée à Symfony. Par analogie, vous pouvez implémenter des skins dans n'importe quel projet en utilisant Twig.


Vous avez une boutique en ligne, une salle de cinéma en ligne, une affiche pour les événements, un catalogue d'émissions de télévision, etc. Un beau jour, vous obtenez la tâche de marquer une page de catalogue pour attirer les utilisateurs et augmenter les ventes pour une sorte d'action. Comment faire si tous les produits du catalogue sont équivalents au moteur?


La solution la plus simple consiste à coder en dur l'ID produit à partir du catalogue. Vous pouvez ajouter une condition au modèle et imposer bodyune classe CSS supplémentaire à la balise, selon laquelle vous pouvez ensuite styliser la page dans des styles généraux.


{% block body_class -%}
    {{ parent () }} product-{{ product.id }}
{%- endblock %}

body.product-12345 {
   # custom style
}

Les styles peuvent faire beaucoup, surtout si vous utilisez flex, mais les styles ne sont pas omnipotents. Parfois, les possibilités de styles ne suffisent pas pour marquer une page et vous devez changer le balisage HTML (mise en page) de la page, et cela se fait par analogie avec les styles.


{% if product.id == 12345 %}
    {# custom code #}
{% else %}
    {# original code #}
{% endif %}

, , , (YAGNI KISS). — . , , .


, , — . , . . , . , . , - (DRY).


. , , , . , , .


product/show.html.twig. product/skin/<skin_name>/, <skin_name> — . default product/skin/default/show.html.twig. , .


public function show(Product $product): Response
{
    return $this->render(sprintf('product/skin/%s/show.html.twig', $product->skin), [
        'product' => $product,
    ]);
}

, , .


{# product/skin/custom_skin/show.html.twig #}

{% extends 'product/skin/default/show.html.twig' %}

{% blocksome_block %}
    {{ parent() }}
    {# customise something #}
{% endblock %}

, . , , , , . . , . , .


{# product/skin/default/show.html.twig #}

{% extends 'product/skin/' ~ product.skin ~ '/layout.html.twig' %}

{# ... #}

{# product/skin/custom_skin/layout.html.twig #}

{% extends 'product/skin/default/layout.html.twig' %}

{# ... #}

:


  • product/skin/<skin_name>/show.html.twig ️▼
  • product/skin/default/show.html.twig ️▼
  • product/skin/<skin_name>/layout.html.twig ️▼
  • product/skin/default/layout.html.twig ️▼
  • ...

— .


  • default
    • layout.html.twig
    • show.html.twig
    • qa.html.twig
    • similar.html.twig
  • first_skin
    • layout.html.twig
    • show.html.twig
    • qa.html.twig
    • similar.html.twig
  • second_skin
    • layout.html.twig
    • show.html.twig
    • qa.html.twig
    • similar.html.twig

, . Twig.


public function show(Product $product, Twig $twig): Response
{
    $template = $twig->resolveTemplate([
        sprintf('product/skin/%s/show.html.twig', $product->skin),
        'product/skin/default/show.html.twig',
    ]);
    $content = $template->render([
        'product' => $product,
    ]);

    return new Response($content);
}

resolveTemplate() . , , — . , Symfony , .


product/skin/default/show.html.twig , layout.html.twig. , Twig extends , extends resolveTemplate() . - .


{# product/skin/default/show.html.twig #}

{% extends [
    'product/skin/' ~ product.skin ~ '/layout.html.twig',
    'product/skin/default/layout.html.twig',
] %}

{# ... #}

Une autre bonne solution serait de placer les styles de skins spécifiques dans des fichiers séparés et de se connecter uniquement sur une page de marque. Nous ne jetterons donc pas les styles principaux avec des ordures, qui ne sont utilisées que sur quelques pages. Si quelqu'un est intéressé, alors dans un article séparé, je peux vous dire comment configurer gulp pour construire un grand nombre de skins ensemble et séparément. Nous avons plus de 300 skins de ce type sur le projet.


All Articles