Slim Framework view helper built on top of the Twig templating component

Overview

Slim Framework Twig View

Build Status Coverage Status License

This is a Slim Framework view helper built on top of the Twig templating component. You can use this component to create and render templates in your Slim Framework application.

Install

Via Composer

$ composer require slim/twig-view

Requires Slim Framework 4, Twig 3 and PHP 7.4 or newer.

Usage

use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;

require __DIR__ . '/vendor/autoload.php';

// Create Container
$container = new Container();
AppFactory::setContainer($container);

// Set view in Container
$container->set('view', function() {
    return Twig::create('path/to/templates', ['cache' => 'path/to/cache']);
});

// Create App
$app = AppFactory::create();

// Add Twig-View Middleware
$app->add(TwigMiddleware::createFromContainer($app));

// Define named route
$app->get('/hello/{name}', function ($request, $response, $args) {
    return $this->get('view')->render($response, 'profile.html', [
        'name' => $args['name']
    ]);
})->setName('profile');

// Render from string
$app->get('/hi/{name}', function ($request, $response, $args) {
    $str = $this->get('view')->fetchFromString(
        '<p>Hi, my name is {{ name }}.</p>',
        [
            'name' => $args['name']
        ]
    );
    $response->getBody()->write($str);
    return $response;
});

// Run app
$app->run();

Without container

use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;

require __DIR__ . '/vendor/autoload.php';

// Create App
$app = AppFactory::create();

// Create Twig
$twig = Twig::create('path/to/templates', ['cache' => 'path/to/cache']);

// Add Twig-View Middleware
$app->add(TwigMiddleware::create($app, $twig));

// Define named route
$app->get('/hello/{name}', function ($request, $response, $args) {
    $view = Twig::fromRequest($request);
    return $view->render($response, 'profile.html', [
        'name' => $args['name']
    ]);
})->setName('profile');

// Render from string
$app->get('/hi/{name}', function ($request, $response, $args) {
    $view = Twig::fromRequest($request);
    $str = $view->fetchFromString(
        '<p>Hi, my name is {{ name }}.</p>',
        [
            'name' => $args['name']
        ]
    );
    $response->getBody()->write($str);
    return $response;
});

// Run app
$app->run();

Custom template functions

TwigExtension provides these functions to your Twig templates:

  • url_for() - returns the URL for a given route. e.g.: /hello/world
  • full_url_for() - returns the URL for a given route. e.g.: http://www.example.com/hello/world
  • is_current_url() - returns true is the provided route name and parameters are valid for the current path.
  • current_url() - returns the current path, with or without the query string.
  • get_uri() - returns the UriInterface object from the incoming ServerRequestInterface object
  • base_path() - returns the base path.

You can use url_for to generate complete URLs to any Slim application named route and use is_current_url to determine if you need to mark a link as active as shown in this example Twig template:

{% extends "layout.html" %}

{% block body %}
<h1>User List</h1>
<ul>
    <li><a href="{{ url_for('profile', { 'name': 'josh' }) }}" {% if is_current_url('profile', { 'name': 'josh' }) %}class="active"{% endif %}>Josh</a></li>
    <li><a href="{{ url_for('profile', { 'name': 'andrew' }) }}">Andrew</a></li>
</ul>
{% endblock %}

Tests

To execute the test suite, you'll need to clone the repository and install the dependencies.

$ git clone https://github.com/slimphp/Twig-View
$ composer install
$ composer test

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Comments
  • How to generate URL for path?

    How to generate URL for path?

    The path_for returned string starts with a slash, this is inconvenient for applications inside a subdirectory.

    Example:

    Route definition

    $app->get('/{slug}', 'App\Action\ItemAction:dispatch');
    

    Template

    <a href="{{ path_for('item', {'slug': item.slug}) }}">
      {{ item.name }}
    </a>
    

    produces /itemslug, which is evaluated inside a browser to http://localhost:8000/itemslug on my dev server. As my application is within project/alpha subdirectory, I'd prefer some helper function which creates as string which evaluates to http://localhost:8000/project/alpha/itemslug.

    In the head of the document I'm using base element <base href="{{ base_url() }}/" /> so all links may be relative.

    I can use both: base_url() ~ path_for() but IMHO it's an overhead to list scheme, domain, port etc in each hyperlink - a relative or absolute path would be sufficient.

    So I wonder how the application URLs should be created in the Twig-View?

    Reintroduce the url_for function which would create URLs not paths, or trim starting slash in path_for? If so, should it happen it in the Twig-View or in the Slim::Router package?

    opened by piotr-cz 22
  • Twig doesn't show anything

    Twig doesn't show anything

    I'm using the twig view helper and it does not show anything... There is no error, nothing, just a blank white page. The server says "200"... I don't know what I'm doing wrong.

    For example if I use the php-view package or simply do $response->getBody()->write("foo") it works. But with the twig-view it doesn't work.

    app/
        cache/
        templates/
            home.twig
        src/
            App.php
            Twig.php
            Home.php
            ...
    public/index.php
    vendor/
    ...
    

    I have my own App class, which holds an object of Slim\App. Here I create an object of my own Twig class, which executes this code:

    $container = $app->getContainer();
    $container["view"] = function ($container) {
        $view = new Slim\Views\Twig("../app/templates", [
            "cache" => "../app/cache"
        ]);
    
        $view->addExtension(new Slim\Views\TwigExtension(
            $container["router"],
            $container["request"]->getUri()
        ));
    
        return $view;
    };
    

    And instantiate an object of the Home class, with this code:

    $app->get("/", function ($request, $response, $args) {
        return $this->view->render($response, "home.twig", []);
    });
    

    My template home.twig contains just <h1>Hello world!</h1>.

    Can someone help me? Or do you need more information?

    opened by be-ndee 17
  • Redirect from Controller

    Redirect from Controller

    Hi,

    I have controller and for example on Login post action, if there are errors or on success login, I'd want to user be redirected login page with errors or dashboard page. How can I do that?

    If I write $this->view->render(...); it opens up in the same url (/login/post)...

    Thanks

    opened by mquestionable 14
  • Question - Twig 3 Support

    Question - Twig 3 Support

    Hello everyone,

    as twig 3.x was released, are there plans to support the new version? However, there are some deprecations in 2.x.

    Had to fiddle a bit, when I tried to install twig-view into an project containing twig 3 in its lock file.

    Thanks in advance

    opened by GameplayJDK 10
  • twig->fetch() outputs to browser rather than return string

    twig->fetch() outputs to browser rather than return string

    I'm trying to use $output = $this->twig->fetch('template_file.twig', compact(...)); to return the generated HTML, but it only outputs straight to the browser.

    I even tried adding die('test'); to make sure I'm calling the right method, but it only works when called before twig->fetch.

    I've also tried ob_start() and ob_get_clean() before and after twig->render(), with the same results.

    I'm using the latest stable 3.x branch available to composer, if it makes any difference. Is there anything else I could try?

    opened by CarlosNegrao 8
  • How to get the basePath?

    How to get the basePath?

    I'm using Slim 4 + Twig-View v3.x and I try to set the Slim App basePath into my Twig template. At the moment I set a global Twig variable, but I know that there is a getBasePath() method available. Unfortunately there is no Twig function like base_path() for the getBasePath() method.

    I think it would make sense to add a new function like base_path into TwigExtension.php:

     new TwigFunction('base_path', [TwigRuntimeExtension::class, 'getBasePath']),
    

    Usage:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <base href="{{ base_path() }}/"/>
        </head>
        <body>
        </body>
    </html>
    
    opened by odan 8
  • 3.x - Cache busting

    3.x - Cache busting

    For cache busting see https://css-tricks.com/strategies-for-cache-busting-css/

    Personally I made a cache busting twig function that transforms the given path automatically. So if there is a file /public/image.jpg and in the template I write

    <img src="{{ cache_busting('image.jpg') }}">
    

    then that would be transformed into

    <img src="/base-path/image.1568637951.jpg">
    

    in case the base path is base-path.

    Of course the web server needs to be configured such that it redirects those cache busting urls.

    What do you think, should we implement that twig function or is this already beyond the slim philosophy?

    opened by adriansuter 8
  • Update the render method in the Twig class

    Update the render method in the Twig class

    I remind that the Slim allows to define a custom route invocation strategy that determines arguments coming into the callable request handler (see Slim's docs).

    And current implementation of the render() method assumes that the handler's arugments will necessarily contain the ResponseInterface object. But I, for example, use my own rout strategy that allows to omit unnecessary arguments, including the ResponseInterface object.

    So I offer to make the render() method flexible - so that the user can choose the most convenient form of the method:

    $view->render($response, 'example.html', ['name' => 'Josh'])
    
    // OR
    
    $view->render('example.html', ['name' => 'Josh'])
    

    i.e. the $response may or may not be among the arguments of the method.

    What was done:

    1) Moving psr/http-factory from the require-dev section to the require (for having ResponseFactoryInterface in the Twig class) in the composer.json

    2) Updating the render method (including the doc block)

    3) Adding the $responseFactory protected property and setResponseFactory method (we can't inject a response factory to/in the constructor because ResponseFactoryInterface assumes different PSR-17 implementatons used by users)

    4) The testRender() method was split into two methods: testRenderWithResponseFactory() and testRenderWithoutResponseFactory(). The code that initializes a $view, $mockBody, $mockResponse, $mockResponseFactory for the two test methods was put in a separate auxiliary method.

    5) Adding the testInvalidArgumentInRender() and testNotDefinedResponseFactoryInRender() test methods.

    6) Removing 2 unused class imports in 'use' section (Twig\Loader\FilesystemLoader and Slim\Views\TwigContext) in TwigTest

    7) Replacing deprecated setMethods() with onlyMethods() (https://github.com/sebastianbergmann/phpunit/pull/3687 and https://github.com/sebastianbergmann/phpunit/issues/3769) in testAddRuntimeLoader()

    8) Updating README.md

    opened by solventt 7
  • Don't let TwigMiddleware messing with container

    Don't let TwigMiddleware messing with container

    First the $this->view only works for Pimple with their __get() implementation. Second most container use the same instance as default or can be configured to. Third messing with container is considered a code smell. Fourth it's better to save the view in Request attribute rather than mess around with container.

    opened by bangzek 7
  • isCurrentPath() fails if $uri is a string

    isCurrentPath() fails if $uri is a string

    The is_current_path method introduced in #64 is really useful. 👍

    However, the method fails if the class is invoked with a string URI (see line #60) as demonstrated in the docs:

    // Instantiate and add Slim specific extension
    $basePath = rtrim(str_ireplace('index.php', '', $c['request']->getUri()->getBasePath()), '/');
    $view->addExtension(new Slim\Views\TwigExtension($c['router'], $basePath));
    

    It works fine when invoked using $c['request']->getUri():

    $view->addExtension(new \Slim\Views\TwigExtension($c['router'], $c['request']->getUri()));
    

    Curious — what's the advantage of using the docs approach over $c['request']->getUri()?

    opened by claviska 7
  • path_for not working

    path_for not working

    I am getting error Unknown "path_for" function in "/Templates/Partials/index.twig" at line 11. here is index .twig

    {% extends "Base.twig" %}

    {% block content %}

    <header class="main_menu_sec navbar navbar-default navbar-fixed-top">
        <div class="container">
            <div class="row">
                <div class="col-lg-3 col-md-3 col-sm-12">
                    <div class="lft_hd">
                        <div class="logo">
                        <a href="{{ path_for('home') }}">Gowarbaam</a>
                        </div>
                    </div>
                </div>
    

    here is view in container `$container['View'] = function ($container) { return new \Slim\Views\Twig( DIR . '/../App/Views',[ 'cache' => false //dirname(FILE) . '/../Caching' ]);

    $View->addExtension(new Slim\Views\TwigExtension(
         $container['router'],
         $container['request']->getUri()
    
     ));
    
    return $View;
    

    };`

    opened by Idreesshahzaib 7
  • Update twig/twig requirement from ^3.4 to ^3.5

    Update twig/twig requirement from ^3.4 to ^3.5

    Updates the requirements on twig/twig to permit the latest version.

    Changelog

    Sourced from twig/twig's changelog.

    3.5.0 (2022-12-27)

    • Make Twig\ExpressionParser non-internal
    • Add "has some" and "has every" operators
    • Add Compile::reset()
    • Throw a better runtime error when the "matches" regexp is not valid
    • Add "twig *_names" intl functions
    • Fix optimizing closures callbacks
    • Add a better exception when getting an undefined constant via constant
    • Fix if nodes when outside of a block and with an empty body

    3.4.3 (2022-09-28)

    • Fix a security issue on filesystem loader (possibility to load a template outside a configured directory)

    3.4.2 (2022-08-12)

    • Allow inherited magic method to still run with calling class
    • Fix CallExpression::reflectCallable() throwing TypeError
    • Fix typo in naming (currency_code)

    3.4.1 (2022-05-17)

    • Fix optimizing non-public named closures

    3.4.0 (2022-05-22)

    • Add support for named closures

    3.3.10 (2022-04-06)

    • Enable bytecode invalidation when auto_reload is enabled

    3.3.9 (2022-03-25)

    • Fix custom escapers when using multiple Twig environments
    • Add support for "constant('class', object)"
    • Do not reuse internally generated variable names during parsing

    3.3.8 (2022-02-04)

    • Fix a security issue when in a sandbox: the sort filter must require a Closure for the arrow parameter
    • Fix deprecation notice on round
    • Fix call to deprecated convertToHtml method

    3.3.7 (2022-01-03)

    • Allow more null support when Twig expects a string (for better 8.1 support)
    • Only use Commonmark extensions if markdown enabled

    ... (truncated)

    Commits

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 0
  • Update phpstan/phpstan requirement from ^1.9.2 to ^1.9.4

    Update phpstan/phpstan requirement from ^1.9.2 to ^1.9.4

    Updates the requirements on phpstan/phpstan to permit the latest version.

    Release notes

    Sourced from phpstan/phpstan's releases.

    1.9.4

    Improvements 🔧

    Bugfixes 🐛

    Internals 🔍

    • Implement getConstantStrings() on Type (#1979), thanks @​staabm!
    • Fix node PHPDoc type hints (#2053), thanks @​herndlm!
    • Refactor FilterVarDynamicReturnTypeExtension to pass around Types instead of Args and the Scope (#2109), thanks @​herndlm!
    Commits
    • d03bcce PHPStan 1.9.4
    • b22aa05 Updated PHPStan to commit 4025209062e31619077197006ce44b5d60a9f2c1
    • 811db85 Updated PHPStan to commit a7fed03bbf1bef545c8afcbf6c906ac93b34c876
    • 274d06e Infinite recursion regression test
    • ad9d3c7 Updated PHPStan to commit a8975b1800d6c5cb88a6af02e132b4e44e093fc3
    • 7a65fac Updated PHPStan to commit 2a61ebc7d07888dbb2836147edaa21b78a983065
    • c0086d9 output-format: add info about editorUrlTitle
    • 15377d9 Updated PHPStan to commit 901d789a45f0682bf6adbdfde516ec1011d873bb
    • 9a25ace Updated PHPStan to commit bc4b2fe0d83a0e601448dbdaa8b0a288342c23f3
    • 89c729c Updated PHPStan to commit 03786827d92df439c3a31760bcd98d560035a33f
    • Additional commits viewable in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 0
  • Rendering a template from a middleware

    Rendering a template from a middleware

    I am using Twig without a container. The Readme shows examples of rendering a template from index.php where Twig::fromRequest($request) is called. However, doing this inside a middleware throws this error:

    Fatal error: Uncaught RuntimeException: Twig could not be found in the server request attributes using the key "view". in C:\Users\arvindpdmn\Documents\workspace\slim\vendor\slim\twig-view\src\Twig.php:74

    How do I render a template from a middleware? In particular, there's one middleware that returns early when there's an error. The response will be rendered without calling the other middleware.

    opened by arvindpdmn 3
  • 3.x - Add `url` and `full_url` twig functions

    3.x - Add `url` and `full_url` twig functions

    Would it make sense to implement two twig functions than can be used to build a url given a path instead of a route name?

    See also https://github.com/slimphp/Slim/issues/2837

    Twig-View 3 
    opened by adriansuter 0
Releases(3.3.0)
Owner
Slim Framework
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
Slim Framework
Async HTTP proxy connector, tunnel any TCP/IP-based protocol through an HTTP CONNECT proxy server, built on top of ReactPHP.

clue/reactphp-http-proxy Async HTTP proxy connector, tunnel any TCP/IP-based protocol through an HTTP CONNECT proxy server, built on top of ReactPHP.

Christian Lück 43 Dec 25, 2022
Simple, async SOAP webservice client, built on top of ReactPHP.

clue/reactphp-soap Simple, async SOAP web service client library, built on top of ReactPHP. Most notably, SOAP is often used for invoking Remote proce

Christian Lück 62 Jul 5, 2022
FrankenPHP is a modern application server for PHP built on top of the Caddy web server

FrankenPHP: Modern App Server for PHP FrankenPHP is a modern application server for PHP built on top of the Caddy web server. FrankenPHP gives superpo

Kévin Dunglas 2.8k Jan 2, 2023
Provides TemplateView and TwoStepView using PHP as the templating language, with support for partials, sections, and helpers.

Aura View This package provides an implementation of the TemplateView and TwoStepView patterns using PHP itself as the templating language. It support

Aura for PHP 83 Jan 3, 2023
This extension provides a view renderer for Pug templates for Yii framework 2.0 applications.

This extension provides a view renderer for Pug templates for Yii framework 2.0 applications.

Revin Roman 9 Jun 17, 2022
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.

Slim Framework Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs. Installation It's recommended

Slim Framework 11.5k Jan 4, 2023
Slim Framework - Prerequisite Checker

Slim Framework - Server Configuration Checker Upload the file check.php to your webserver Browse to the file: https://example.com/check.php Check the

Daniel Opitz 6 Aug 30, 2022
REST APIs using Slim framework. Implemented all CRUD operations on the MySql database

PHP REST API using slim framework and CRUD operations ?? Hi there, this is a simple REST API built using the Slim framework. And this is for the folks

Hanoak 2 Jun 1, 2022
Slim Framework skeleton application with MVC Schema

Slim Framework skeleton application with MVC Schema

JingwenTian 9 Apr 29, 2021
This repository contains a library of optional middleware for your Slim Framework application

Slim Framework Middleware This repository contains a library of optional middleware for your Slim Framework application. How to Install Update your co

Slim Framework 47 Nov 7, 2022
A curated list of awesome tutorials and other resources for the Slim micro framework

Awesome Slim A curated list of awesome tutorials and other resources for the Slim micro framework Table of Contents Essentials Tutorials Packages and

Sawyer Charles 466 Dec 8, 2022
Slim Framework 3 Skeleton Application + PagSeguro Lib

Slim Framework 3 Skeleton Application + PagSeguro Lib Aplicação simples para geração do Token para pagamentos no PagSeguro (método transparente) e env

Raí Siqueira 1 Feb 26, 2018
My personal blog developed on the Slim Framework

nesbot.com I am making the source code of my personal site available publicly in case it helps anybody. It's developed using the Slim Framework. I am

Brian Nesbitt 56 Sep 14, 2022
Plates Template Integration for Slim micro framework 3

Plates Template Integration for Slim micro framework 3 Render your Slim 3 application views using Plates template engine. Install Via Composer $ compo

Projek XYZ 26 Feb 5, 2022
Juliangut Slim Framework Doctrine handler middleware

Juliangut Slim Framework Doctrine handler middleware Doctrine handler middleware for Slim Framework. Slim3 version Doctrine integration service for Sl

Julián Gutiérrez 6 Mar 23, 2021
This Slim Framework middleware will compile LESS CSS files on-the-fly using the Assetic library

This Slim Framework middleware will compile LESS CSS files on-the-fly using the Assetic library. It supports minification and caching, also via Asseti

Gerard Sychay 22 Mar 31, 2020
Strict PSR-7 implementation used by the Slim Framework

Strict PSR-7 implementation used by the Slim Framework, but you may use it separately with any framework compatible with the PSR-7 standard.

Slim Framework 96 Nov 14, 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 302 Feb 21, 2022