Laravel 5

Conflit, mais où ?

  • Avatar de SamuelBranthomme
    Membre depuis :
    29/11/2017
    Messages :
    4

    Hello,

    Je débute dans Laravel, c'est mon premier framework, je ne suis ni habitué à la POO ni à l'architecture MVC aussi stricte... soyez indulgent. :p

    Je cherche à faire quelque chose de simple : envoyer une variable dans une vue pour l'afficher. Pour le faire proprement à la sauce Laravel@MVC :

    • J'ai une vue, en l'ocurrence la "racine" de mon application (layouts.app) dans laquelle je veux afficher ma variable
    • J'ai un Controller dans lequel je déclare une méthode qui retourne cette vue avec ma variable en paramètre
    • J'ai une Route get qui fait appel à la méthode du Controller en question

    Jusque là tout va bien.

    Ce qui ne fonctionne pas, c'est quand j'essaie d'accéder à une autre vue (construite par un @yield depuis layouts.app). J'ai une ErrorException qui me dit que ma variable n'est pas définie.

    Il y a un truc qui m'échappe. D'un côté ça me semble logique puisque je fais appel à une route qui ne définit pas ma variable, mais de l'autre côté ça me semble assez loufoque puisque layouts.app c'est la base de mon application dans laquelle tout devrait se charger...

    Alors je sais pas, qu'est-ce qui m'échappe ? Je n'emploie pas la bonne méthode ?
    Après tout je pourrai déclarer ma variable directement dans ma vue, mais c'est moins propre. Et ça me bloque car l'idée derrière c'est que cette variable soit issue d'une requete avec Eloquent (que je ne peux définitivement pas faire directement dans ma vue).

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    1673

    Salut,

    Lorsque tu envoies une variable dans une vue elle est disponible dans cette vue et toutes les autres vues incluses, par contre elle n'est pas spontanément disponible dans un template (@extends) qui sert pour cette vue. Il me semble que c'est très logique.

    Si toutefois l'organisation de tes vues exige un passage de la vue à sa parente tu peux l'envoyer de façon explicite :

    @extends('layout', ['title' => $title])

    Il faut quand même voir si tu envoies la même variable systématiquement par plusieurs vues, dans ce cas il faudrait peut-être réorganiser le code.

  • Avatar de SamuelBranthomme
    Membre depuis :
    29/11/2017
    Messages :
    4

    Re,

    Ca me donne la même erreur. En fait ça ne récupère pas la variable $title qui existe dans la vue layout. Mais ça fonctionne si je définie directement la valeur du genre

    @extends('layout', ['title'] => 'hello'])

    A moins qu'il faille aussi retourner la variable sur la vue étendue depuis un controleur, mais là on en finit pas.
    Mais comme tu le dis, c'est surement plus un problème d'organisation du code parce qu'en soit, ce que je veux faire me semble très commun. Mais n'étant pas habitué avec tout ça... Tu peux peut-être me guider ?

    J'ai un template app.blade.php qui est le "point d'entrée" de l'application et qui contient basiquement :

    • un menu fixe sur toute l'application (qui est dans une vue à part, insérée dans app.blade.php avec un @include)
    • un @yield lié à différentes vues pour insérer du contenu spécifique (en allant sur www.monsite.fr/contact par exemple)

    La variable que je veux conserver peu importe où on se trouve sur l'application, elle se trouve donc dans le menu fixe. J'ai un controleur qui renvoie ma variable sur app.blade.php et je peux l'appeler sans soucis. Et pour reprendre mon exemple, si je veux aller sur www.monsite.fr/contact ça plante car la variable n'existe pas ici. Où est-ce que j'ai faux ? Dans mon utilisation de yield/extends ?

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    1673

    Bonjour,

    Soit la variable est spécifique à la vue et alors on doit la trouver dans la vue, soit elle est plus globale et alors on peut :

    • partager une (ou plusieurs) variable avec toutes les vues : View::share('key', 'value');
    • envoyer une (ou plusieurs) variable à une ou plusieurs vues avec un composeur de vues.

    Dans ton cas tu peux par exemple envoyer systématiquement les variables du menu dans app.blade.php avec un composeur de vues. Ainsi ta vue de contact aura le menu. Tu peux regarder comment j'ai procédé pour le menu dans mon exemple, que je décris un peu dans cet article, avec un composeur de vues couplé à une configuration.

  • Avatar de gAb09
    Membre depuis :
    28/07/2014
    Messages :
    89

    Salut,
    Si je te suis bien, tu demande l'url “www.monsite.fr/contact“ qui est routée vers un controller (disons “ContactController“) qui lui même appelle une vue (disons la vue “Contact”) qui étend la vue "layout". Cette vue "Layout", fait appel à une variable "$mavariable".

    Si tu veux que $mavariable soit disponible dans Layout il faut la lui transmettre.

    1) Par exemple via "contact" comme proposé par Bestmomo, mais alors il faut que ton ContactController la fournisse à la vue Contact.
    Mais tu as raison "on en finit pas" car chaque sous vue devra fournir les variables pour la vue layout…, et donc chaque controller devra contenir le code qui assure cette fourniture…

    En fait, on limite les données dynamiques (donc les variables) dans le layout…
    les données dynamiques spécifiques à chaque page étant prises en charge par un couple vue/controller spécifique.
    Mais ce n'est pas toujours possible… il y a même un cas qui se pose très souvent : celui d'un menu !!!

    2) Alors il faut faire appel à unviewComposer qui, à l'image d'un controller te permet de définir des variables et les faire passer à une vue, et qui est automatiquement sollicité dès qu'une vue donnée est appellée, par ex. la vue du menu appellée par @include() dans le layout.

    3) Il y a une variante à cela c'est de passer par un middleware qui te permettra lui, de disposer d'un ensemble de données composé lors de chaque requête. C'est le choix fait par exemple par ce package (qui a l'air pas mal, mais je n'ai pas testé) destiné à la construction de menu.

    Voila, j'espère que cela éclaircira les choses pour toi…

  • Avatar de gAb09
    Membre depuis :
    28/07/2014
    Messages :
    89

    Oups !!! J'ai mis au moins 29 mn à rédiger mon post !! ;-))) Bestmomo m'a précédé du coup !!

  • Avatar de SamuelBranthomme
    Membre depuis :
    29/11/2017
    Messages :
    4

    Ah bah voilà parfait, c'est ça qu'il me manquait, le composeur de vues !
    Merci, problème résolu :)

  • Avatar de F.M.
    Membre depuis :
    10/07/2017
    Messages :
    32

    Salut,

    Petite précision : le layout n'est pas une vue si on veut parler propre, c'est une mise en page qui va service de 1 à n vues.

    Attention si tu utilises le composeur de vue avec * , ce n'est pas le meilleur moyen d'optimiser ton appli. Fais un log dans ton composer, si t'as divisé tes vues en partials fractionnés tu seras étonné du nombre de fois où il est appelé.

  • Avatar de SamuelBranthomme
    Membre depuis :
    29/11/2017
    Messages :
    4

    Oui je m'en suis rendu compte avec la DebugBar car certaines variables sont issues de query qui se répétent sur autant de vues que j'affiche. Pas génial. :)

    Du coup dans la progression de mon application et de mon apprentissage du framework, je suis confronté à l'utilisation de variables de session. Au login de l'application, j'ai besoin de stocker des variables en session à partir de requêtes. Et je veux pouvoir faire appel à ces variables sur n'importe quelle vue. Mes requêtes utilisent Auth::id() pour déterminer la 1ère base de relation entre mes tables.

    Auth::id() n'étant pas accessible dans la fonction boot() d'un ServiceProvider, ça ne convient pas.
    Pour l'instant, je fais ça dans une fonction authenticated() du LoginController. Solution que j'ai trouvé ailleurs sur le net. Ca fonctionne mais la mise à jour d'une variable n'est visible qu'en déco/reco de l'application, ce qui est logique mais pas idéal niveau intéraction/dynamisme...

    Où est-ce qu'elles seraient le mieux placer ?
    Je pensais à Controller puisqu'il est injecté dans tous les autres contrôleurs, mais :

    • Je n'y arrive pas, peut-être un problème de route...
    • Je vais avoir le même problème de répétition des requêtes non ?
  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    1673

    Salut,

    Si tu veux actualiser tes données en session à chaque accès alors passe par un middleware. Mais du coup l'intérêt de mettre des infos en session perd son sens...

Vous ne pouvez pas répondre à ce sujet.