thephpleague / plates

Native PHP template system
https://platesphp.com
MIT License
1.47k stars 180 forks source link

Do I need to pass template variables to layout each time? #117

Closed martynbiz closed 8 years ago

martynbiz commented 8 years ago

Hi, I'm using layouts in my templates like so:

<?php $this->layout('layouts/main', [
    'title' => 'Homepage',
    'messages' => $messages,
    'currentUser' => $currentUser,
]) ?>

Do I really need to pass the template variables for every single template that uses this layout? What if I want to pass a new variable to the layout... I need to update every template. Is this correct? Otherwise, can future versions be modified to automatically make all variables available in all templates and inherited templates/ layouts etc

reinink commented 8 years ago

Yeah this is intentional with Plates. Each template only has access to it's own variables. This is meant to prevent conflicts between variables, and generally works out pretty well.

There are some techniques to help with this. For example, preassigned and shared data make it easy to assign data to a template each time it's rendered:

$templates->addData(['name' => 'Jonathan'], ['login', 'template']);

If you're using layouts, you can assign data when you call the layout function:

<?php $this->layout('template', ['title' => 'User Profile']) ?>

And in a similar way, if you're using nesting, you can assign data when you call the insert function:

<?php $this->insert('partials/header', ['name' => 'Jonathan']) ?>

I hope that helps!

Smolky commented 8 years ago

Hi. One chance to do this is to set the layout this way in your templates <?php $this->layout('layouts::base', $this->data) ?>

But this is a trap for doing something that is unintentional of the behaviour of Plates

Anyway, I think that the "layout" data should be escaped, but, always having preference the local scope

Something like this

// If array merge gives priority for the first array, layoutData will prevail (I think)
if (isset($this->layoutName)) {
   $layout = $this->engine->make($this->layoutName);
   $layout->sections = array_merge($this->sections, array('content' => $content));

   // Array merge between the data
   $content = $layout->render(array_merge ($this->layoutData, $this->data));
}

What do you think?