Here is my current code, the relevant bits at least.
Composer dependencies:
"slim/slim": "4.3",
"slim/psr7": "0.6.0",
"slim/twig-view": "3.0.0-beta",
"php-di/php-di": "6.0",
"vlucas/phpdotenv": "^4.0",
"slim/csrf": "^1.0",
"slim/php-view": "^2.2"
Main app class:
<?php
declare(strict_types=1);
namespace Example\Main;
use DI\ContainerBuilder;
use Dotenv\Dotenv;
use Dotenv\Repository\Adapter\EnvConstAdapter;
use Dotenv\Repository\Adapter\ServerConstAdapter;
use Dotenv\Repository\RepositoryBuilder;
use Slim\Csrf\Guard;
use Slim\Factory\AppFactory;
use Slim\Psr7\Response;
use Slim\Psr7\Request;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
class App
{
public function __construct()
{
// Load the enviroment file
$adapters = [
new EnvConstAdapter(),
new ServerConstAdapter(),
];
$repository = RepositoryBuilder::create()
->withReaders($adapters)
->withWriters($adapters)
->immutable()
->make();
Dotenv::create($repository, CONFIG_PATH, null)->load();
// Set up Dependency Injection
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions(CONFIG_PATH . DS . 'services.php');
$containerBuilder->addDefinitions(CONFIG_PATH . DS . 'actions.php');
/* causes fatal error in combination with CSRF guard */
//$containerBuilder->enableCompilation(ABS_PATH . DS . 'cache');
$container = $containerBuilder->build();
AppFactory::setContainer($container);
$app = AppFactory::create();
$responseFactory = $app->getResponseFactory();
// Register Middleware On Container
$container->set(Guard::class, function () use ($responseFactory) {
return new Guard($responseFactory);
});
$app->addRoutingMiddleware();
// Register Twig middleware
$app->add(TwigMiddleware::createFromContainer($app, Twig::class));
// Enable to register CSRF middleware for all routes
$app->add(Guard::class);
// Include routes
$routes = require CONFIG_PATH . DS . 'routes.php';
$routes($app);
$app->run();
}
}
Services.php:
<?php
declare(strict_types=1);
use Example\TwigExtension\CsrfExtension;
use Psr\Container\ContainerInterface;
use Slim\Csrf\Guard;
use Slim\Views\PhpRenderer;
use Slim\Views\Twig;
return [
Twig::class => function (ContainerInterface $container) {
$twig = new Twig(ABS_PATH . '/src/example/views', [
'cache' => false,
'debug' => true,
'auto_reload' => true,
]);
$twig->addExtension(new Twig_Extension_Debug());
$twig->addExtension(new CsrfExtension($container->get(Guard::class)));
return $twig;
},
PhpRenderer::class => function (ContainerInterface $container) {
return new PhpRenderer(ABS_PATH . '/src/example/views');
},
PDO::class => function (ContainerInterface $container) {
$driver = $_ENV["DB_DRIVER"];
$host = $_ENV["DB_HOST"];
$dbname = $_ENV["DB_NAME"];
$charset = $_ENV["DB_CHARSET"];
$username = $_ENV["DB_USERNAME"];
$password = $_ENV["DB_PASSWORD"];
$dsn = "$driver:host=$host;dbname=$dbname;charset=$charset";
$options = [
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset",
\PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
\PDO::ATTR_EMULATE_PREPARES => true,
];
try {
return new \PDO($dsn, $username, $password, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int) $e->getCode());
}
},
];
Actions.php:
<?php
declare(strict_types=1);
use Example\Controllers\HelloController;
use Example\Controllers\HomeController;
use Example\Controllers\DemoController;
use Psr\Container\ContainerInterface;
use Slim\Views\Twig;
return [
HelloController::class => function (ContainerInterface $container) {
$view = $container->get(Twig::class);
return new HelloController($view);
},
HomeController::class => function (ContainerInterface $container) {
$view = $container->get(Twig::class);
return new HomeController($view);
},
DemoController::class => function (ContainerInterface $container) {
$view = $container->get(Twig::class);
$product = $container->get(Product::class);
return new DemoController($view, $product);
}
];