8768 sujets

Développement web côté serveur, CMS

Bonjour,
Je travaille actuellement sur un projet d’application web d’une certaine envergure. Pour clarifier le code, je souhaiterais externaliser le code. J’ai opté pour la solution du twig car le système d’inclusion de template me semble très intéressant. Mais je me trouve face à un problème technique et bizarrement aucun site / tuto n’aborde celui-ci.

Je m’explique : je voudrais utiliser le modèle « triple héritage » et travailler avec un système de routing qui devrait me conduire au différentes pages. Chaque page devrait extends du layout.html.twig (template père). Jusqu’à la, tout fonctionne.

Seulement mon layout contient un nombre important de variables provenant du php et intégrées au twig via la fonction render(). De même pour chaque « contenu central de page » (chaque template fils). Et c’est là qu’est mon problème, comment s’organiser ?

Dois-je rajouter mes variables de layout au tableau de paramètre à chaque render() de chaque template fils ? de cette façon j’aurais un array avec l’ensemble de mes variables (les variables du template père et fils). Cette méthode me semble fonctionnelle mais j’ai l’impression que ce n’est pas la plus propre.

Pourriez-vous me renseigner sur la façon dont vous abordez cette problématique ?
Merci d'avance
Salut..

Je ne connais pas twig, pour ma part j'utilise le templating natif de php avec une class qui gère tout ça...

Du coup les variables sont construites selon chaque page...

Pou rton cas je ne sais pas si c'es tle plus propre mais ce n'ets pas déconnant.
je viens de regarder un peu la doc de twig... il est assez simple de ce que je vois.

Avec mon système un peu équivalent.
J'ai une structure simple.
Un skull.tpl
qui fait les includes des heads, header et footer
puis des content.tpl (home.tpl, contact.tpl, etc)
en accord avec tout ça j'ai des cores (home.php, contact.php etc) et ce sont les cores qui sont utilisé avec mon loader (index.php) et qui complète les variables propre à chaque tpl..

une logique mvc quoi Smiley lol
Modérateur
Et l'eau,

J'attendais un peu avant de répondre. Je vais donner un exemple assez simple sur 2 fichiers :
- le layout
- la vue

layout :

<!doctype html>
<html class="no-js" lang="fr">
    <head>
        <meta charset="UTF-8">
        <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <title>{% block title %}{% endblock title %}</title>
    </head>
    <body>
        {% block content %}{% endblock content %}
    </body>
</html>


la vue :

{% extends 'layouts/default.twig' %}
{% block title %}le titre de la page{% endblock title %}
{% block content %}
        <h1>ma vue principale</h1>
{% endblock content %}


Dans le layout, tu vas remarquer que j'ai ouvert 2 blocks :
- title
- content

Dans la vue, tu vas remarquer :
- je lui dis que ma vue est un extends du layout default
- je définis le contenu du block titre !
- j'affiche le contenu de ma vue (content)

Je pense que c'est assez explicite.

À noter que Twig est une pâle copie de Jinja2.

@pchlj : Avant, j'étais réfractaire aux moteurs de template en php (surtout Smarty ==> beurk !). Pourquoi ? PHP est un moteur de template par nature (d'où sa création initiale). Force est constaté que Twig apporte un vrai plus Smiley cligne . Par exemple de base, tu n'as pas besoin de faire des htmlentities() ou autres manières d'échapper les chaînes de caractères...
Modifié par niuxe (28 Feb 2018 - 23:20)
@niuxe : J'utilise HylaTPL (un model proche de smarty) jamais eu aucun problème et pas besoin d'htmlentities Smiley hum . Je vois pas où twig apporte quelque chose Smiley smile (enfin par rapport à Hyla Smiley cligne )
Salut,


Seulement mon layout contient un nombre important de variables provenant du php et intégrées au twig via la fonction render(). De même pour chaque « contenu central de page » (chaque template fils). Et c’est là qu’est mon problème, comment s’organiser ? 

Dois-je rajouter mes variables de layout au tableau de paramètre à chaque render() de chaque template fils ? de cette façon j’aurais un array avec l’ensemble de mes variables (les variables du template père et fils). Cette méthode me semble fonctionnelle mais j’ai l’impression que ce n’est pas la plus propre.


De mon point de vue il est préférable d'avoir un tableau avec tous tes render plutôt que de rendre tes vues directement dans twig.

En effet faire "un" render directement dans la vue est lourd et chronophage, alors plusieurs ...
Modifié par biduletruck (01 Mar 2018 - 10:31)
Bonjour,
Merci pour vos réponses.
@pchlj Les alternatives que tu me proposes sont intéressantes, je vais les étudier cela d’avantage même si je suis actuellement dans l’optique de continuer avec twig.
@niuxe Merci pour la réponse.
L’exemple que tu me montres correspond au système de block, ça c’est ok.
Mon interrogation ne se situe pas exactement là.
Pour reprendre ton exemple :
layout

<!doctype html>
<html class="no-js" lang="fr">
    <head>
        <meta charset="UTF-8">
        <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <title>{% block title %}{% endblock title %}</title>
    </head>
    <body>
	<div>{{ Layout.variable1}}</div>
        {% block content %}{% endblock content %}
	<a>{{ Layout.variable2}}</a>
    </body></html>


Vue 1
{% extends 'layouts/default.twig' %}
{% block title %}le titre de la page{% endblock title %}
{% block content %}
        <h1>ma vue {{ Vue.variable1_vue_1}}principale{{ Vue.variable2_vue_1}}</h1>
{% endblock content %}


Vue 2
{% extends 'layouts/default.twig' %}
{% block title %}le titre de la page{% endblock title %}
{% block content %}
        <h1>ma vue {{Vue.variable1_vue_2}}principale{{ Vue.variable2_vue_2}}</h1>
{% endblock content %}


On peut voir ici un layout dans lequel je dois insérer des variable (ici variable1 et variable2, mais il faut imaginer que j’en ai en fait au moins 100).
Et deux vues avec la aussi des variables (sauf que là encore j’ai en fait des dizaines de vues avec des dizaines de variables).
Les variables du layout sont à insérer à chaque visualisation.
En toute logique, on ne peut utiliser que une fois la fonction render() qui permet d’afficher la page.
Ma stratégie est la suivante : j’ai d’abord mon array avec les variables du layout.

$array = array(
‘Layout’ => [
  ' variable1' => variable1,
  ' variable2' => variable2
]
);


Et j’insert mon array de variables de la vue à ce tableau avec les variables de la vue, par exemple :

$array_global = array(
‘Layout’ => [
  ' variable1' => variable1,
  ' variable2' => variable2
],
‘Vue’ => [
  ' variable1_vue_1' => variable1_vue_1,
  ' variable1_vue_2' => variable2_vue_1
]
);


Puis j’utilise render() avec mon array global.
return $this->render('index.html.twig', $array_global);


Je me demandais si cette façon de faire était la façon conventionnelle lorsque l’on désire avoir un code propre.

@biduletruck je ne suis pas sur de comprendre ton post, mais il me semble que ce que tu proposes correspond à ce que je viens de développer. peux tu me le confirmer stp
Modifié par agcea (01 Mar 2018 - 11:04)


je ne suis pas sur de comprendre ton post, mais il me semble que ce que tu proposes correspond à ce que je viens de développer. peux tu me le confirmer stp 

Oui en effet cela correspond à ce que tu viens de faire.

2 cas:

1- le render directement dans ta vue avec twig :
{{ render(controller('AppBundle:MyController')) }}

Mais cela est clairement un faux ami pour moi, du fait que tu commences par rendre ton premier controller, puis la vue se charge et tu refais un render ...
(sans parler des problème d'affichage que cela peux apporter)

2- Faire un render de toutes tes vues et envoyer un tableau de valeurs à twig: (ta façon)

ci-joint un exemple d'un controller


public function validateAction(Request $request, Observation $observation)
    {
        $deleteForm = $this->createDeleteForm($observation);
        $validateForm = $this->createForm('AppBundle\Form\ValidateType', $observation);
        $validateForm->handleRequest($request);

        if ($validateForm->isSubmitted() AND $validateForm->isValid()){
            $observation->setActive(true);
            $this->getDoctrine()->getManager()->flush();

            return $this->redirectToRoute('observation_index');
        }

        return $this->render('observation/validate.html.twig', array(
            'observation' => $observation,
            'validate_form' => $validateForm->createView(),
            'delete_form' => $deleteForm->createView(),
        ));
    }


Clairement cela reste une bonne pratique à avoir, le render directement dans la vue doit être utiliser à titre exceptionnel (pour moi)
Meilleure solution