slimphp / PHP-View

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

How can I include CSS in templates when using a layout #69

Closed samuelgfeller closed 3 years ago

samuelgfeller commented 3 years ago

How can I include template-specific stylesheet files individually when using a layout (without webpack or asset() function)?

I have a layout that I include $this->phpRenderer->setLayout('layout.html.php'); in which I link the default css files for the general page structure etc. that should be loaded on every request.
Now there are some styles that are specific to one and only one template. I don't want to include this CSS file every time. Only when this template is rendered. (For e.g. when error-page is rendered, I want that error.css is loaded, otherwise error.css should not be linked)
Each template content is added via the $content var in the layout inside the <body>-tag and to properly add a CSS file I would need to access the <head> segment.

In Twig, we can use the handy block css

{% block stylesheets %}
    {{ parent() }}

    <link href="{{ asset('user/user.css') }}" rel="stylesheet">
{% endblock %}

How would I do this with PHP-View? Maybe use Javascript to modify the head after the page loaded? Or include the content in a <style></style> tag?

odan commented 3 years ago

Such a "block" function is not directly supported.

samuelgfeller commented 3 years ago

@odan I'm aware of this but why not a workaround like you suggested in your first edit? Isn't it a good solution to the issue?

odan commented 3 years ago

Update: My first answers was about how to to include assets within the global "layout", but not how to define specific assets per page.

Sections or “blocks” can be rendered using the addAttribute and fetch method. This example shows how to define the assets within a specific page and how to render it into the layout page:

<?php $this->addAttribute('js', ['page.js']); ?>
<head>
    <?= $this->fetch('js.php', ['assets' => $js ?? []]) ?>
</head>

The section template for the JavaScript assets, js.php:

<?php
foreach ($assets ?? [] as $asset) {
    echo sprintf('<script type="text/javascript" src="%s"></script>', $asset);
}

More details:

https://odan.github.io/2020/12/09/slim4-php-view.html#sections

samuelgfeller commented 3 years ago

Wow, this is brilliant I love this solution!

I didn't know the fetch() function, this creates so much new functionality for complex layouts (like you awesomely described on your blog). Maybe a mention in the readme of this repo would make sense? I'm not imagining that most devs will look in PhpRenderer.php to check the functions out. It makes PHP-View quite powerful too right?.