Search code examples
phpslimslim-4

how to add twig-view in slimframework v4


I'm trying to add twig-view in slim v4

In slim v3, we add twig-view in container

$container['view'] = function ($c) {
    $view = new \Slim\Views\Twig('path/to/templates', [
        'cache' => 'path/to/cache'
    ]);

    // Instantiate and add Slim specific extension
    $router = $c->get('router');
    $uri = \Slim\Http\Uri::createFromEnvironment(new \Slim\Http\Environment($_SERVER));
    $view->addExtension(new \Slim\Views\TwigExtension($router, $uri));

    return $view;
};

but I can't add twig like that in slim v4


Solution

  • Update: Twig-View has reached a stable version and the docs are updated to address Slim 4 integration.
    If you are still using an unstable version of Twig-View, please consider upgrading.

    First, you need to add Twig-View package to your project:

    composer require slim/twig-view
    

    And assuming the following directory structure:

    composer.json
    cache/
    public/
      |--index.php
    templates/
      |--hello.twig
    vendor/
      |--autoload.php
    

    The followings are two working examples:

    If you use a container (which is optional according to Slim 4 docs), you can add Tiwg creation definition to the container and use it when required. (I'm using php-di/php-di in this example, but you can use any PSR compatible dependency container.)

    index.php, using a container:

    <?php
    
    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(__DIR__ . '/../templates',
            ['cache' => __DIR__ . '/../cache']);
    });
    
    // Create App
    $app = AppFactory::create();
    
    // Add Twig-View Middleware
    $app->add(TwigMiddleware::createFromContainer($app));
    
    // Example route
    $app->get('/hello/{name}', function ($request, $response, $args) {
        return $this->get('view')->render($response, 'hello.twig', [
            'name' => $args['name']
        ]);
    });
    
    // Run the app
    $app->run();
    

    You can also skip the container creation, but in that case you need to create the Twig instance before trying to render a template.

    index.php, without a container:

    <?php
    
    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(__DIR__ . '/../templates',
        ['cache' => __DIR__ . '/../cache']);
    
    // Add Twig-View Middleware
    $app->add(TwigMiddleware::create($app, $twig));
    
    // Example route
    // Please note how $view is created from the request
    $app->get('/hello/{name}', function ($request, $response, $args) {
        $view = Twig::fromRequest($request);
        return $view->render($response, 'hello.twig', [
            'name' => $args['name']
        ]);
    });
    
    // Run the app
    $app->run();
    

    hello.twig:

    Hello {{ name }}
    

    Now try visiting /hello/slim4 in your browser and the output will be:

    Hello slim4