Reputation: 4506
I'm new to SLIM3 and followed the tutorial to get some functions in the container that I want to access from anywhere in the code. So here's my index.php
file where I initalise everything:
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
// Require for loading the vendor libraries installed by composer
require 'vendor/autoload.php';
$config['displayErrorDetails'] = true;
$config['addContentLengthHeader'] = false;
$app = new \Slim\App(["settings" => $config]);
$container = $app->getContainer();
// Monolog initalisation. To use it write: $this->logger->addInfo("what you want to write here");
$container['logger'] = function($c) {
$logger = new \Monolog\Logger('eq_logger');
$file_handler = new \Monolog\Handler\StreamHandler("logs/app.log");
$logger->pushHandler($file_handler);
return $logger;
};
// Database connections
$container['dbteacher'] = function ($c) {
$pdo = new PDO($_SERVER['PGSQL_CONNECTION_STR']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
};
$container['dbagent'] = function ($c) {
$pdo = new PDO($_SERVER['PGSQL_CONNECTION_STR_AGENT']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $pdo;
};
$app->post('/{controller}/{function}', function (Request $request, Response $response) {
$headers = $request->getHeaders();
$params = $request->getParsedBody();
$classname = $request->getAttribute('controller');
$controller = new $classname($this->logger);
$function = $request->getAttribute('function');
$result = $controller->$function($params);
$response->getBody()->write($result);
return $response;
});
$app->run();
Here I can access logger
by typing $this->logger
, same goes for the dbteacher
and dbagent
, but I can only do that inside where these containers are created, when I am calling another function from a different class I want to be able to access them as well but I don't want to pass them in the parameter because that will be hard to maintain, I also though about having a config.php
class that initalises these containers and the $app
variable and extending it in every class I use but that doesn't sound right.
What's the best way to approach this?
Upvotes: 1
Views: 311
Reputation: 11135
You should use the functions of the dependency injection container (Pimple) which Slim3 uses.
That being said, I want to say that dynamically creating "controller"s isn't that nice, that abstraction shouldn't be there and you should just do $response->getBody()->write($result);
or the simpler method $response->write($result);
in every controller. Also, I don't see why a whole routing framework is needed for this construct.
But anyway if you want to stay with that solution, you can use Pimple, I'll explain that on an example.
You have several classes with different constructor parameter:
class A {
public function __construct($logger) {}
}
class B {
public function __construct($logger, $myHelper) {}
}
Firstly you add them all to the Pimple container:
$container['A'] = function($c) { // or $container[A::class] for type safety
return new A($c['logger']);
};
$container['B'] = function($c) {
return new A($c['logger'], $c['myHelper']);
};
And then you can get them in your route by calling get on the container on the app instance.
$app->post('/{controller}/{function}', function (Request $request, Response $response) {
$headers = $request->getHeaders();
$params = $request->getParsedBody();
$classname = $request->getAttribute('controller');
$controller = $this->getContainer()->get($classname);
$function = $request->getAttribute('function');
$result = $controller->$function($params);
$response->getBody()->write($result);
return $response;
});
Upvotes: 5