1

So I'm using a skeleton I found online....

The "boostrap.php" looks like


use DI\ContainerBuilder;
use Slim\App;

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

$containerBuilder = new ContainerBuilder();

// Add DI container definitions
$containerBuilder->addDefinitions(__DIR__ . '/container.php');

// Create DI container instance
$container = $containerBuilder->build();

// Create Slim App instance
$app = $container->get(App::class);

// Register routes
(require __DIR__ . '/routes.php')($app);

// Register middleware
(require __DIR__ . '/middleware.php')($app);

return $app;

In the container I'm adding TWIG I think correctly...

return [
    'settings' => function () {
        return require __DIR__ . '/settings.php';
    },

    App::class => function (ContainerInterface $container) {
        AppFactory::setContainer($container);

        return AppFactory::create();
    },

    ErrorMiddleware::class => function (ContainerInterface $container) {
        $app = $container->get(App::class);
        $settings = $container->get('settings')['error'];

        return new ErrorMiddleware(
            $app->getCallableResolver(),
            $app->getResponseFactory(),
            (bool)$settings['display_error_details'],
            (bool)$settings['log_errors'],
            (bool)$settings['log_error_details']
        );
    },

    Twig:class => function (ContainerInterface $container){
        return new Twig(__DIR__.'/../views',[
            'cache' => __DIR__ . '/../cache',
            'auto_reload' => true
        ]);
    },
     TwigMiddleware::class => function (ContainerInterface $container){
        return TwigMiddleware::createFromContainer($container->get(App::class));
    },

 etc etc etc

So I'm thinking this is correct however I also need to setup the middleware for the Twig and also be able to use it in the Classes/Controller/Routes....

In my Middleware

<?php

use Selective\BasePath\BasePathMiddleware;
use Slim\App;
use Slim\Middleware\ErrorMiddleware;
use Slim\Views\TwigMiddleware;
use Slim\Views\Twig;
 

return function (App $app) {
    // Parse json, form data and xml
    $app->addBodyParsingMiddleware();
    $app->add(TwigMiddleware::class));

    // Add the Slim built-in routing middleware
    $app->addRoutingMiddleware();

    $app->add(BasePathMiddleware::class);

    // Handle exceptions
    $app->add(ErrorMiddleware::class);
};

The Current error is

Message: The specified container key does not exist: view
File: /home/webuser/testsite/genapp/vendor/slim/twig-view/src/TwigMiddleware.php

So I'm not sure how to set the key I guess of for Twig instance/class.

I'm new to this format of DI so I'm unsure how to add the middleware and then use it throughout the app...

Thanks

BostonMacOSX
  • 1,369
  • 2
  • 17
  • 38

2 Answers2

1

I guess you have installed the slim/twig-view component.

I would change the DI container TwigStart::class to Twig::class.

Instead of creating the Twig instance manually, better use the Twig::create method to build it.

Then you could also add a DI container definition for \Slim\Views\TwigMiddleware\TwigMiddleware::class that uses the TwigMiddleware::createFromContainer method to create and return the middleware instance.

This allows you to load the middlware only when its realy needed (lazy).

use Slim\Views\TwigMiddleware;
// ...

$app->add(TwigMiddleware::class);
odan
  • 4,757
  • 5
  • 20
  • 49
  • Updated the code...almost there.. ;) – BostonMacOSX Feb 11 '22 at 14:15
  • Any ideas about what I've changed? – BostonMacOSX Feb 13 '22 at 02:10
  • Your DI container definition for `TwigMiddleware::class` already gets the `$container` object. So pass this $container variable to the TwigMiddleware::createFromContainer method instead. – odan Feb 13 '22 at 12:47
  • Argument 1 passed to Slim\Views\TwigMiddleware::createFromContainer() must be an instance of Slim\App, ---createfromContainer needs an instance of App thus why I passed what I passed.... – BostonMacOSX Feb 13 '22 at 18:49
0

When using TwigMiddleware::createFromContainer(), you need to pass the container key of the Twig dependency as a second parameter. In both my case and yours, that key is Twig::class, whereas the method has a default value of view. Since there is no item in the container called view, this causes an error.

The following container definitions seem to work for me:

use Psr\Container\ContainerInterface;
use Slim\App;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;

return [
  App::class => static function(ContainerInterface $container) {
    return AppFactory::create($container);
  },
  
  Twig::class => static function(ContainerInterface $container) {
    return Twig::create(PROJECT_ROOT . '/views', [
      'cache' => PROJECT_ROOT . '/storage/cache/templates',
      'debug' => true,
    ]);
  },

  // Note how dependency injection already works here
  // No need to call $container->get(App::class) :)
  TwigMiddleware::class => static function(App $app) {
    return TwigMiddleware::createFromContainer($app, Twig::class);
  },
];
Steen Schütt
  • 1,355
  • 1
  • 17
  • 31