If we look at the Middleware concept published on the slim4 website and elsewhere.
It should be executed before a request reaches the application or when sending the response to the user.
The question is this, because even if a Middleware is executed before, a container is called before by the application:
Show me the code.
config
'providers' => [,
App\ServiceProviders\Flash::class => 'http'
],
'middleware' => [
App\Middleware\Session::class => 'http,console',
],
Session Middleware
class Session
{
public function __invoke(Request $request, RequestHandler $handler)
{
if (session_status() !== PHP_SESSION_ACTIVE) {
$settings = app()->getConfig('settings.session');
if (!is_dir($settings['filesPath'])) {
mkdir($settings['filesPath'], 0777, true);
}
$current = session_get_cookie_params();
$lifetime = (int)($settings['lifetime'] ?: $current['lifetime']);
$path = $settings['path'] ?: $current['path'];
$domain = $settings['domain'] ?: $current['domain'];
$secure = (bool)$settings['secure'];
$httponly = (bool)$settings['httponly'];
session_save_path($settings['filesPath']);
session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
session_name($settings['name']);
session_cache_limiter($settings['cache_limiter']);
session_start();
}
return $handler->handle($request);
}
}
Flash Message Container
class Flash implements ProviderInterface
{
public static function register()
{
$flash = new Messages();
return app()->getContainer()->set(Messages::class, $flash);
}
}
Execution app
...
// Instantiate PHP-DI ContainerBuilder
$containerBuilder = new ContainerBuilder();
AppFactory::setContainer($containerBuilder->build());
$app = AppFactory::create();
$providers = (array)$this->getConfig('providers');
array_walk($providers, function ($appName, $provider) {
if (strpos($appName, $this->appType) !== false) {
/** @var $provider ProviderInterface */
$provider::register();
}
});
$middlewares = array_reverse((array)$this->getConfig('middleware'));
array_walk($middlewares, function ($appType, $middleware) {
if (strpos($appType, $this->appType) !== false) {
$this->app->add(new $middleware);
}
});
....
$app->run();
Result
`Fatal error: Uncaught RuntimeException: Flash messages middleware failed. Session not found.`
Flash message needs a session started to work this already I know, and Middleware should be responsible for doing this, but it is always executed after the container
First, you are using dependency
and container
terms as if they are the same thing, which they are not.
About the problem with your code, in Flash::register()
method, you are creating a new object from Messages
class and putting this in the DI container. You are calling this method and forcing creation of the Message object, which needs the session to be already started, before letting the middleware start the session. You really should avoid storing objects in DIC, instead of storing their definition (how they are built). The following change is what I mean:
class Flash implements ProviderInterface
{
public static function register()
{
return app()->getContainer()->set(Messages::class, function() {
return new Messages();
});
}
}