slimphp / PHP-View

A Simple PHP Renderer for Slim 3 & 4 (or any other PSR-7 project)
MIT License
264 stars 60 forks source link

Sub-templates and layouts #49

Closed gdsmith closed 4 years ago

gdsmith commented 5 years ago

From the documentation:

Inside your templates you may use $this to refer to the PhpRenderer object to render sub-templates.

Including sub-templates (with fetch) when you are using layouts is problematic as sub-template content also includes the surrounding layout. Using a straight php include(template.file) is an effective workaround.

vasiliytkachenko commented 5 years ago

slim/php-view/src/PhpRenderer.php

method fetch

if ($this->layout !== null) {
    ob_start();
    $data['content'] = $output;
    $this->protectedIncludeScope($this->layout, $data);
    $output = ob_get_clean(); 
}

maybe the problem is here $this->layout == null if $this->layout == null - in this case object return only sub-template

kAlvaro commented 5 years ago

README explains you can render sub-templates but doesn't say how:

jaywilliams commented 5 years ago

Here's a potential patch I created which gives a workaround for template-less partials:

--- PhpRenderer.php.orig        Mon Aug 19 15:37:38 2019
+++ PhpRenderer.php     Mon Aug 19 15:39:37 2019
@@ -204,7 +204,7 @@
             $this->protectedIncludeScope($this->templatePath . $template, $data);
             $output = ob_get_clean();

-            if ($this->layout !== null) {
+            if ($data['layout'] !== false && $data['layout'] !== '' && $this->layout !== null) {
                 ob_start();
                 $data['content'] = $output;
                 $this->protectedIncludeScope($this->layout, $data);

Usage:

    echo $this->fetch('partials/test.phtml', [
        'layout'  => false,
    ]);

Another possibility would be to create a separate method which wouldn't include the layout, regardless (e.g.$this->fetchPartial('partials/test.phtml')).

jaywilliams commented 5 years ago

The cleanest way I came up with was extending the PhpRenderer class and adding a fetchPartial() method which is a copy of the partial() method with the layout code removed.

Ideally, I think a method like this should be added to the actual project, but this will work for my use case in the mean time.

piotr-cz commented 4 years ago

@jaywilliams Thanks, I just suggest changing the flag to skipLayout, so evaluation becomes easier:

- if ($this->layout !== null) {
+ if ($this->layout !== null && empty($data['skipLayout'])) {
piotr-cz commented 4 years ago

If anyone is wondering about the status, bugfix #53 was implied to be a B/C feature and merged into 3.x branch.