IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

"Composants" et css/js


Sujet :

Symfony PHP

  1. #1
    Membre expérimenté
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2009
    Messages : 420
    Points : 1 471
    Points
    1 471
    Par défaut "Composants" et css/js
    Bonjour,

    Je commence à regarder comment fonctionne Symfony2 (j'ai déjà travaillé avec Symfony1) et je n'arrive pas à trouver la réponse à la question suivante:

    Dans Symfony1, pour ajouter une feuille CSS ou un fichier Javascript, on avait les helper de type use_...
    Ca permettait par exemple de placer le helper dans la vue d'un composant et ainsi, lorsqu'une page devait inclure le composant, le composant lui-même ajoutait ses ressources à la pile qui était donc rendue globalement via les include_stylsheets() dans la layout de base.

    Ex:
    Code layout.php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <!doctype html>
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <head>
            <?php include_title() ?>
            <?php include_stylesheets() ?>
        </head>
        <body>
            <?php include_component('base','example') ?>
     
            <?php include_javascripts(); /* rend les balises <script> */ ?>
        </body>
    </html>
    Code .../module/base/templates/_example.php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?php
    use_javascript("lien/vers/mon/fichier.js"); // ajoute le fichier à la pile
    ?>
    <div id="mondiv"></div> <!-- mon JS travail sur cet élément par exemple -->

    La question est donc: comment reproduire ce comportement avec Symfony2 ?

    Si j'ai:

    Code layout.php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    <!doctype html>
    <html lang="{{ 'fr' }}"> 
    {% block body %}
        <head>
            <title>{% block title %}Test{% endblock %}</title>
            {% block stylesheets %}
                {% stylesheets filter='cssrewrite'
                    'bundles/monbundle/css/fichier.css' %}
                    <link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
                {% endstylesheets %}
            {% endblock %}
     
        </head>
        <body>
            {{ render(controller("monbundle:base:example")) }}
     
            {% block javascripts %}
                {% javascripts
                    'bundles/monbundle/jquery.js' %}
                    <script type="text/javascript" src="{{ asset_url }}"></script>
                {% endjavascripts %}
            {% endblock %}
        </body>
    {% endblock %}
    </html>

    Comment faire en sorte que si j'inclue mon action monbundle:base:example, les CSS et JS dont dépend l'action soit ajoutés au {% block javascripts %} ?

  2. #2
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    Hello,

    Tu peux surcharger les blocs css et js en les redéclarant dans ton fichier monbundle:base:example.html.twig de cette manière

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {% block stylesheets %}
        {{ parent() }}
        <link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
    {% endblock %}
     
    {% block javascripts %}
        {{ parent() }}
        <script type="text/javascript" src="{{ asset_url }}"></script>
    {% endblock %}

  3. #3
    Membre expérimenté
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2009
    Messages : 420
    Points : 1 471
    Points
    1 471
    Par défaut
    Mais mon "composent", n'est pas censé hériter du layout du coup, le layout n'est pas censé être son "parent".
    Je me trompe ?

    Si je test j'ai ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Calling "parent" on a template that does not extend nor "use" another template is forbidden in

  4. #4
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    Si ton template n'étend ou n'utilise aucun layout de base, il ne possède aucun css ni aucun js. Donc effectivement l'appel de parent() n'a pas de sens : mais si ce que tu veux c'est rajouter un fichier à la pile de css et de js il faut bien qu'il y ait un layout qui possède cette pile au départ.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2009
    Messages : 420
    Points : 1 471
    Points
    1 471
    Par défaut
    Citation Envoyé par Nico_F Voir le message
    Si ton template n'étend ou n'utilise aucun layout de base, il ne possède aucun css ni aucun js.
    Pourquoi un template qui n'étends pas le layout ne pourrait avoir besoin de ressources spécifiques ?

    Citation Envoyé par Nico_F Voir le message
    Donc effectivement l'appel de parent() n'a pas de sens
    On est bien d'accord sur ce point.

    Citation Envoyé par Nico_F Voir le message
    mais si ce que tu veux c'est rajouter un fichier à la pile de css et de js il faut bien qu'il y ait un layout qui possède cette pile au départ.
    Non, mon template a beau ne pas étendre le layout, il est malgré tout inclue dans celui-ci. Le layout et ce template de composant ne sont rien de plus que 2 morceau d'un même résultat HTML. A ce titre, il n'y a aucune raison de ne pas pouvor mettre en commun leurs ressources JS et CSS.

    Comme je l'ai dit, l'idée est de créer un composant qui puisse être inclue ensuite dans n'importe quelle page, donc dans n'importe quel template.
    Si mon composant à besoin de ressources spécifiques CSS ou JS, il n'est pas question de systématiquement ajouter l'appel de ces ressources à chaque fois que j'ai besoin d'utiliser mon composant (duplication inutile de code).
    Faire simplement un appel à ce composant doit suffire. C'était le comportement standard de Symfony1.

    Ajouter en bourrin un tag <javascript> directement dans le template du composant serait bien évidemment sale, et poserai de toute façon des problèmes de dépendance éventuelle (si le JS en question a besoin de jQuery, qui est lui chargé en toute fin de page, ça va planter).

    Ce que je veux est plutôt simple (mais j'ai peut-être du mal à l'expliciter): je veux qu'au rendu de ma page, 100% des Ressources utilisées par chaque partie et chaque composant soit appelées au même endroit, et compressées (chose de base dans Symfony1 encore une fois, il n'y a rien de révolutionnaire dedans).

  6. #6
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Septembre 2009
    Messages : 875
    Points : 1 313
    Points
    1 313
    Par défaut
    qui était donc rendue globalement via les include_stylsheets() dans la layout de base.
    Il y'a bien l'air d'avoir une dépendance au layout de base, je ne comprend pas pourquoi refuser de faire cette même dépendance dans twig

  7. #7
    Membre expérimenté
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2009
    Messages : 420
    Points : 1 471
    Points
    1 471
    Par défaut
    Il n'est pas possible de faire étendre le template du composant du layout de base puisque que le layout de base inclue lui-même ce composant via:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {{ render(controller("monbundle:base:example")) }}
    Pour être plus clair, si je fais ceci:
    Code monbundle/Resources/views/base/example.html.twig : Sélectionner tout - Visualiser dans une fenêtre à part
    {% extends '::base.html.twig' %}
    Ça plante (normal donc).

    Dans example.html.twig, je n'ai donc ni accès au {% block javascripts %} ni au {{ parent() }}.

    Je ne refuse rien, au contraire, c'est que je cherche à obtenir !

  8. #8
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    Le problème vient de l'include d'un template à priori totalement indépendant et qui peut ne rien étendre du tout.

    Spontanément comme ça je ne vois pas d'autres solutions que de placer tes ressources dans le(s) template(s) qui fait l'include.

    Si c'est le layout de base fait cet include (comme dans ton exemple), alors tu rajoutes bêtement tes ressources dans les blocks stylesheets et javascripts du layout de base et ces ressources seront disponibles sur toutes les pages qui l'étendent.
    Si tu ne veux inclure les assets que là ou tu fais les include de ce composant, ce sont dans chacun des templates qui possèdent cet include qu'il faut surcharger les blocks d'assets.

    Dans le second cas, tu auras par exemple un fichier index.html.twig qui étendra de layout, qui surchargera les blocks stylesheets et javascripts, et qui fera également l'include.

    Je ne crois pas qu'il soit possible de rajouter des assets comme tu le désires directement à l'intérieur du composant inclus.




    Par contre, arrête moi si je me trompe, mais je pense que l'erreur vient surtout du fait que tu essayes de faire fonctionner le système de templating de la même manière que tu le faisais avec symfony 1.x.
    Tu as repris la même structure en remplaçant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <?php include_component('base','example') ?>
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    {{ render(controller("monbundle:base:example")) }}
    or je pense qu'il est plus judicieux à cet endroit de faire un block pour ton composant et de le surcharger dans les templates ou tu en as besoin, quitte à faire ce même render dans la surcharge du block component. Tu peux aussi lui mettre un contenu par défaut, et l'écraser ou rajouter des éléments dans les templates filles : selon tes besoins tu pourras alors déclarer tes assets directement dans le base layout, ou surcharger les blocks d'assets dans les templates qui modifient ton block component.

  9. #9
    Membre expérimenté Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Points : 1 310
    Points
    1 310
    Par défaut
    Voilà ce que je te propose si tu veux inclure ton component dans divers templates :

    Layout de base
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!doctype html>
    <html lang="{{ 'fr' }}"> 
    {% block body %}
        <head>
            <title>{% block title %}Test{% endblock %}</title>
            {% block stylesheets %}
                {# Whatever you want #}
            {% endblock %}
     
        </head>
        <body>
            {% block custom_component %}{% end block %}
     
            {% block javascripts %}
                {# Whatever you want #}
            {% endblock %}
        </body>
    {% endblock %}
    </html>
    Template d'une action quelconque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {% extends '::base.html.twig' %}
     
    {% block javascripts %}
        {{ parent() }}
        <script type="text/javascript" src="{{ myCustomComponent.js }}"></script>
    {% endblock %}
     
    {% block stylesheets %}
        {{ parent() }}
        <link rel="stylesheet" href="{{ myCustomComponent.css }}" type="text/css" />
    {% endblock %}
     
    {% block custom_component %}
        {{ render(controller("monbundle:base:example")) }}
    {% end block %}

  10. #10
    Membre expérimenté
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2009
    Messages
    420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2009
    Messages : 420
    Points : 1 471
    Points
    1 471
    Par défaut
    Citation Envoyé par Nico_F Voir le message
    Le problème vient de l'include d'un template à priori totalement indépendant et qui peut ne rien étendre du tout.
    C'est bien ça.

    Citation Envoyé par Nico_F Voir le message
    Spontanément comme ça je ne vois pas d'autres solutions que de placer tes ressources dans le(s) template(s) qui fait l'include.

    Si c'est le layout de base fait cet include (comme dans ton exemple), alors tu rajoutes bêtement tes ressources dans les blocks stylesheets et javascripts du layout de base et ces ressources seront disponibles sur toutes les pages qui l'étendent.
    Si tu ne veux inclure les assets que là ou tu fais les include de ce composant, ce sont dans chacun des templates qui possèdent cet include qu'il faut surcharger les blocks d'assets.
    Dans le second cas, tu auras par exemple un fichier index.html.twig qui étendra de layout, qui surchargera les blocks stylesheets et javascripts, et qui fera également l'include.
    Ces deux solutions ne me paraissent pas suffisamment satisfaisantes. En effet, soit je dois déclarer et donc charger des ressources qui ne seront pas forcément utilisées, soit je dois déclarer mes ressources spécifiques à chaque fois que j'en ai besoin (et donc ça crée de la duplication de code -le jour où ces ressources changent, ça va pas être l'idéal)


    Citation Envoyé par Nico_F Voir le message
    Je ne crois pas qu'il soit possible de rajouter des assets comme tu le désires directement à l'intérieur du composant inclus.
    Personnellement je trouve ça dommage. Surtout si on considère que c'était le comportement standard de la version précédente.

    Citation Envoyé par Nico_F Voir le message
    Voilà ce que je te propose si tu veux inclure ton component dans divers templates :
    Je comprends la solution, cela dit, on se retrouverait à devoir finalement écrire du code à deux endroits différents pour chaque inclusion de composant (dans ton exemple, on a la ligne 12 du 1er fichier + la ligne 14 du second).
    De plus à chaque fois que je voudrais inclure ce même composant dans différentes pages, j'aurai à réécrire les lignes 3 à 11 du second fichier, ce que je cherche à éviter.
    Au final, en terme de lisibilité et de maintenabilité, j'ai un doute sur un projet de grande envergure (mais je précise comme dans mon 1er poste, je manque énormément de recul sur Sf2 pour le moment puisque je démarre l'étude du framework).

    En tout cas, merci de vous être penché sur la question. Etant donné qu'il ne semble pas possible de base d'obtenir le comportement que je souhaite, je vais me pencher sur comment ajouter ce comportement via la structure en services de Sf2 et les possibilité d'étendre Twig.

    Si j'arrive à un résultat, je posterai ici ce que j'ai fait. De toute façon, je continue à creuser

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo