A Simple PHP Renderer for Slim 3 (or any other PSR-7 project)

Related tags

Laravel PHP-View
Overview

Build Status

PHP Renderer

This is a renderer for rendering PHP view scripts into a PSR-7 Response object. It works well with Slim Framework 4.

Cross-site scripting (XSS) risks

Note that PHP-View has no built-in mitigation from XSS attacks. It is the developer's responsibility to use htmlspecialchars() or a component like laminas-escaper. Alternatively, consider Twig-View.

Installation

Install with Composer:

composer require slim/php-view

Usage with Slim 4

use Slim\Views\PhpRenderer;

include "vendor/autoload.php";

$app = Slim\AppFactory::create();

$app->get('/hello/{name}', function ($request, $response, $args) {
    $renderer = new PhpRenderer('path/to/templates');
    return $renderer->render($response, "hello.php", $args);
});

$app->run();

Note that you could place the PhpRenderer instantiation within your DI Container.

Usage with any PSR-7 Project

//Construct the View
$phpView = new PhpRenderer("path/to/templates");

//Render a Template
$response = $phpView->render(new Response(), "hello.php", $yourData);

Template Variables

You can now add variables to your renderer that will be available to all templates you render.

// via the constructor
$templateVariables = [
    "title" => "Title"
];
$phpView = new PhpRenderer("path/to/templates", $templateVariables);

// or setter
$phpView->setAttributes($templateVariables);

// or individually
$phpView->addAttribute($key, $value);

Data passed in via ->render() takes precedence over attributes.

$templateVariables = [
    "title" => "Title"
];
$phpView = new PhpRenderer("path/to/templates", $templateVariables);

//...

$phpView->render($response, $template, [
    "title" => "My Title"
]);
// In the view above, the $title will be "My Title" and not "Title"

Sub-templates

Inside your templates you may use $this to refer to the PhpRenderer object to render sub-templates. If using a layout the fetch() method can be used instead of render() to avoid appling the layout to the sub-template.

<?=$this->fetch('./path/to/partial.phtml', ["name" => "John"])?>

Rendering in Layouts

You can now render view in another views called layouts, this allows you to compose modular view templates and help keep your views DRY.

Create your layout path/to/templates/layout.php.

<html><head><title><?=$title?></title></head><body><?=$content?></body></html>

Create your view template path/to/templates/hello.php.

Hello <?=$name?>!

Rendering in your code.

$phpView = new PhpRenderer("path/to/templates", ["title" => "My App"]);
$phpView->setLayout("layout.php");

//...

$phpview->render($response, "hello.php", ["title" => "Hello - My App", "name" => "John"]);

Response will be

<html><head><title>Hello - My App</title></head><body>Hello John!</body></html>

Please note, the $content is special variable used inside layouts to render the wrapped view and should not be set in your view paramaters.

Exceptions

\RuntimeException - if template does not exist

\InvalidArgumentException - if $data contains 'template'

Comments
  • Handle exceptions and throwables in templates

    Handle exceptions and throwables in templates

    When an exception is thrown in the template, the output buffer should be cleaned up, so that a clean error message is shown to the user.

    This PR handles PHP7 Throwables as well as being PHP 5.6 compatible.

    enhancement 
    opened by jeremyVignelles 14
  • Bugfix: Infinite loop in fetch

    Bugfix: Infinite loop in fetch

    Resolves https://github.com/slimphp/PHP-View/issues/49

    Layout support added in v2.2.1 in this PR changed the way how fetch method works.

    When there is a layout set and it or other template file calls fetch method, it creates an infinite loop:

    • layout calls fetch method
    • fetch method renders layout
    • layout calls fetch method
    • ...

    which results in

    Fatal error: Uncaught Error: Maximum function nesting level of '512' reached, aborting! 
    

    While there is another attempt to fix the issue, https://github.com/slimphp/PHP-View/pull/52 it does so by introducing new method, while this PR introduces new argument in fetch method: $useLayout which defaults to false.

    opened by piotr-cz 12
  • Added minimal support for layouts

    Added minimal support for layouts

    This PR adds ability to wrap view templates inside layouts. This is very simple implementation that just renders templates inside other templates called layouts. This PR doesn't support advanced techniques like template inheritance and extending as it would make the package heavy and conflict the SLIM principle.

    Tests are in the tests directory and tests the same scenarios as original tests of the package. Hope you like it!

    opened by cholthi 9
  • Sub-templates and layouts

    Sub-templates and layouts

    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.

    opened by gdsmith 6
  • Need consistent naming to fix autoloading

    Need consistent naming to fix autoloading

    As it stands right now PHP-View doesn't work because the Composer autoloader doesn't match a PhpRenderer class name against a PHPRenderer.php file name.

    One of two things needs to happen:

    • Change the filename from PHPRenderer.php to PhpRenderer.php
    • Change the class name from PhpRenderer to PHPRenderer

    Both of these approaches fixed autoloading for me. I suspect the first option would be preferred, but I'd be fine with either one since I'm more concerned about it working than the naming style.

    opened by josephscott 6
  • Added layouts and automatic file extension

    Added layouts and automatic file extension

    Added a method to use layout template files. Also, the .php extension in template file names is optional. The trailing slash in the template path is optional too. And some CS fixes.

    opened by berarma 5
  • How can I include CSS in templates when using a layout

    How can I include CSS in templates when using a layout

    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?

    opened by samuelgfeller 4
  • the reserved $template key in data array

    the reserved $template key in data array

    Hi,

    Nice piece of code. Juste 2 questions :

    1. why do you keep a check on the "$template" key present in the data array, while in this variable is now protected because the function protectedIncludeScope use func_get_arg(0) so there is no risk to overwrite it with the extract() function.

    I think this check is useless : https://github.com/slimphp/PHP-View/blob/master/src/PhpRenderer.php#L149

    Am i missing something ????

    2a) Why not use a require instead of an include ? there is already a check if the file exist, so using require() is pretty safe from my point of view.

    2b) Are you sure there could have a throw exception/throwable from the extract() function ? are the try/catch really usefull ?

    Thank you for your clarifications. Keep up the good work.

    opened by ncou 4
  • Ability to specify data outside the render() function

    Ability to specify data outside the render() function

    It would be very helpful to have a variable from request ($request->getUri()->getBasePath();) always available on the templates e.g. with a middleware without having to pass the above as parameter to renderer->render on all routes each time (like so):

    $app->get(...
       ...
      $args['basepath']=$request->getUri()->getBasePath();
      return $this->renderer->render($response, 'test.php', $args);
    });
    
    enhancement 
    opened by sivann 4
  • Rendering sub-templates?

    Rendering sub-templates?

    How would you render sub-templates when working with PHP-View? For example, this simple code is not working ("Content" gets outputted last, after the header/footer templates)

    $app->get('/', function (Request $request, Response $response) {
        return $this->renderer->render($response, "/pages/main.php");
    });
    
    //In main.php
    <?php $this->render($response, "/header.php", []); ?>
    Content
    <?php $this->render($response, "/footer.php", []); ?>
    

    I do understand why it's not working (Only one response object), but not how to fix it in a proper way?

    opened by khromov 3
  • Inserting a path to a named route in a php-view template?

    Inserting a path to a named route in a php-view template?

    As far as I can tell, there is no (clean) way to insert a path to a named route, or am I missing something? I have create a workaround which I am happy to contribute, but since I only started using the Slim Framework yesterday I want to make sure I am not missing something.

    opened by pietmarcus 3
  • $_SESSION global variable is not available when rendering $content

    $_SESSION global variable is not available when rendering $content

    How to reproduce:

    $_SESSION['user_id'] = 'some_value';
    
    $phpView = new PhpRenderer("path/to/templates", ["title" => "My App"]);
    $phpView->setLayout("layout.php");
    
    //...
    
    $phpview->render($response, "hello.php", ["title" => "Hello - My App", "name" => "John"]);
    

    In hello.php:

    <?php var_dump($_SESSION); // Will not be set ?>
    Hello <?=$name?>! Your id is: <?= $_SESSION['user_id'] ?>
    

    In layout.php:

    <?php var_dump($_SESSION); // Will be filled as intended ?>
    <html><head><title><?=$title?></title></head><body><?=$content?></body></html>
    

    So, in both hello.php and layout.php you will be able to get $title var. But, in hello.php global $_SESSION var will be empty. Expected behavior would be leaving global variables intact.

    opened by scsmash3r 1
  • Can I access the slim properties from the templates?

    Can I access the slim properties from the templates?

    Through my API I already have a route that receives parameters and creates users, this works perfectly for me. However, I would like to implement an HTML form for the API to provide API clients, the form must be able to access the method (to the database model), so that from the same form you can create the users.

    I already have the simple form in HTML.

    The question is: How do I access the slim models, so that, once the values of the form have been obtained, I will be able to send them to the model to create the user.

    My route to create users:

    $this->post('crear', function ($req, $res, $args) {
            $r = CandidatoCrearValidation::validate($req->getParsedBody());
            if(!$r->response){
              return $res->withHeader('Content-type', 'application/json')
                        ->withStatus(422)
                        ->write(json_encode($r->setResponse(false,"Campos no validados.")));
            }else{
              return $res->withHeader('Content-type', 'application/json')
                      ->write(
                        json_encode($this->model->candidato->crear($req->getParsedBody()))
                      ); 
            }
          });
    

    My route to show the form:

    $this->get('crear/form', function ($req, $res, $args) {
          return $this->renderer->render($res, "form-signin.php", $args);
        });
    

    Ambos están dentro del mismo grupo de la ruta de slim. image

    opened by NeftaliAcosta 2
  • Error trying to load javascript scripts by it src attribute

    Error trying to load javascript scripts by it src attribute

    Hi!, I am new in PHP and I try to create an API with Slim, but when I try to load a javascript file inside a template by <script src="dist/file.js"></script>, it launch an error: Uncaught SyntaxError: Unexpected token <.

    My project structure is:

    slim-tutorial
    ├── public
    |    ├── dist
    |    |    └── learning.js
    |    └── index.php
    ├── templates
    |    └── index.html
    ├── vendor
    ├── composer.json
    └── composer.lock
    

    My public/index.php code is:

    <?php
    use \Psr\Http\Message\ServerRequestInterface as Request;
    use \Psr\Http\Message\ResponseInterface as Response;
    
    require __DIR__.'/../vendor/autoload.php';
    
    $app = new \Slim\App(['settings' => $config]);
    
    $container = $app->getContainer();
    
    $container['view'] = new \Slim\Views\PhpRenderer(__DIR__.'/../templates/');
    
    $app->get('/', function(Request $request, Response $response) {
        $response = $this->view->render($response, 'index.html');
        return $response;
    });
    
    $app->run();
    ?>
    

    My templates/index.html code is:

    <!DOCTYPE html>
    <html lang="es">
        <head>
            <base href="./">
            <meta charset="UTF-8">
            <title>Document</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
        </head>
        <body>
            <section id="root"></section>
            <script type="text/javascript" src="dist/learning.js"></script>
            <!-- <script type="text/javascript">
                // With this code it works, but if I use src attribute in script tag, it crash
                (function() {
                    var root = document.getElementById('root');
                    var chidlInput = document.createElement('input');
                    chidlInput.setAttribute('id', 'name');
                    root.appendChild(chidlInput);
                })();
            </script> -->
        </body>
    </html>
    

    And my public/dist/learning.js code is:

    (function() {
        var root = document.getElementById('root');
        var chidlInput = document.createElement('input');
        chidlInput.setAttribute('id', 'name');
        root.appendChild(chidlInput);
    })();
    

    My templates/index.html and public/dist/learning.js codes is to test, in my final project I will use Angular 5 to develop front-end.

    I checked this tutorial about Angular and Slim but it not works.

    I tried with PHP 5.6 and PHP 7.2 but both launch the same error.

    To run this project I use php -S localhost:8080 -t public public/index.php, because I have installed PHP without Apache or Nginx.

    I work on Windows 10.

    Regards.

    opened by ivanhdzd 4
  • Use same API as Twig-View for data/attributes

    Use same API as Twig-View for data/attributes

    hello

    the way to pass datas to the view renderer differs when using PHP-View and Twig-View I think this is not the right way maybe PhpRenderer should also implement \ArrayAccess like Twig class does

    regards

    enhancement help wanted 
    opened by aurmil 4
Releases(3.2.0)
Owner
Slim Framework
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
Slim Framework
A Laravel 8 Project Implement with GraphQL With Sanctum APIs Authentications Which utilized in Any Frontend or Any Mobile Application Programs.

A Laravel 8 Project Implement with GraphQL With Sanctum APIs Authentications Which utilized in Any Frontend or Any Mobile Application Programs.

Vikas Ukani 3 Jan 6, 2022
cybercog 996 Dec 28, 2022
Collection of agnostic PHP Functions and helpers with zero dependencies to use as foundation in packages and other project

Collection of agnostic PHP Functions and helpers This package provides a lot of very usefull agnostic helpers to use as foundation in packages and oth

padosoft 54 Sep 21, 2022
Laravel 2-Step Verification is a package to add 2-Step user authentication to any Laravel project easily.

Laravel 2-Step verification is a package to add 2-Step user authentication to any Laravel project easily. It is configurable and customizable. It uses notifications to send the user an email with a 4-digit verification code. Laravel 2-Step Authentication Verification for Laravel. Can be used in out the box with Laravel's authentication scaffolding or integrated into other projects.

Jeremy Kenedy 204 Dec 23, 2022
Simple PSR-7 compatible response sender

Simple PSR-7 compatible response sender

Lazzard 4 Nov 5, 2022
Blade is a simple, yet powerful templating engine provided for the Slim Framework

slim-blade Blade is the default template engine of Laravel. The main advantage of Blade is template inheritance whilst using plain PHP. This package a

Kevin Darren 32 May 24, 2021
A Laravel package that adds a simple image functionality to any Laravel model

Laraimage A Laravel package that adds a simple image functionality to any Laravel model Introduction Laraimage served four use cases when using images

Hussein Feras 52 Jul 17, 2022
Laravel Proxy Package for handling sessions when behind load balancers or other intermediaries.

Laravel Trusted Proxies Setting a trusted proxy allows for correct URL generation, redirecting, session handling and logging in Laravel when behind a

Chris Fidao 7.3k Jan 4, 2023
A laravel Livewire Dynamic Selects with multiple selects depending on each other values, with infinite levels and totally configurable.

Livewire Combobox: A dynamic selects for Laravel Livewire A Laravel Livewire multiple selects depending on each other values, with infinite levels of

Damián Aguilar 25 Oct 30, 2022
Base library for repeated layout fields, content builders and other collection components

laravel-flexible-content This package's only purpose is to build custom repeated layout components, such as Laravel Nova's Flexible Content field or y

Whitecube 5 May 31, 2022
A powerful form builder, for Laravel and other frameworks (stand-alone too)

Former A Laravelish way to create and format forms Former outputs form elements in HTML compatible with your favorite CSS framework (Bootstrap and Fou

null 1.3k Dec 22, 2022
A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro

Laravel Myanmar Tools A package for Myanmar Font, Phone and other Myanmar tools using Laravel Macro. Installation composer require pyaesoneaung/larave

Pyae Sone Aung 22 Dec 20, 2022
Laravel package for manage your URL redirects in database or other sources to get better SEO results

Laravel 8 and 9 package to manage URL redirections inside your Laravel application using different data sources. It allows a better SEO support for your Laravel site.

Siro Díaz Palazón 51 Sep 21, 2022
Open source for selling social media accounts or accounts on other platforms.

SELLACC - Open Source Selling Accounts SELLACC is open source for selling social media accounts or accounts on other platforms. ⚠️ We not update sourc

PHAM DUC THANH 6 Nov 17, 2022
Slim Framework custom views

Slim Views This repository contains custom View classes for the template frameworks listed below. You can use any of these custom View classes by eith

Slim Framework 308 Nov 7, 2022
Slim Jam is a demo application to provide examples for composer package, PHPSpreadsheet, Shopify API etc. usages.

SLIM JAM Slim Jam is a demo application to provide examples for composer package, PHPSpreadsheet, Shopify API etc. usages. This project aims to take a

Uğur ARICI 2 Jan 9, 2022
🖼️ Laravel Nova Field for uploading and cropping images using Slim Image Cropper

??️ Laravel Nova Field for uploading and cropping images using Slim Image Cropper

Marius 5 Apr 2, 2022
Service manager for Slim compatible with Laravel packages

SlimServices SlimServices is a service manager for the Slim PHP microframework based on Laravel 4 service providers and DI container, allowing you to

its 76 Jul 23, 2022
Validate your input data in a simple way, an easy way and right way. no framework required. For simple or large. project.

wepesi_validation this module will help to do your own input validation from http request POST or GET. INTEGRATION The integration is the simple thing

Boss 4 Dec 17, 2022