访问容器功能的最佳设计方法

时间:2017-08-18 03:28:46

标签: php slim-3

我是SLIM3的新手,并按照教程获取了我想从代码中的任何位置访问的容器中的一些函数。所以这是我的index.php文件,其中我将所有事情都搞砸了:

<?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();

在这里,我可以通过键入logger来访问$this->logger,同样适用于dbteacherdbagent,但我只能在创建这些容器的位置内执行此操作,我正在调用另一个我希望能够访问它们的类的函数,但我不想在参数中传递它们,因为这很难维护,我也想要{{1这个容器和config.php变量的初始化并在我使用的每个类中扩展它,但听起来不对。 什么是解决这个问题的最好方法?

1 个答案:

答案 0 :(得分:5)

你应该使用Slim3使用的依赖注入容器(Pimple)的功能。

话虽这么说,我想说动态创建&#34;控制器并不是那么好,抽象不应该存在,你应该做$response->getBody()->write($result);或者每个控制器中更简单的方法$response->write($result);。另外,我不明白为什么这个结构需要一个完整的路由框架。

但无论如何,如果你想继续使用这个解决方案,你可以使用Pimple,我会在一个例子中解释一下。

您有几个具有不同构造函数参数的类:

class A {
    public function __construct($logger) {}
}

class B {
    public function __construct($logger, $myHelper) {}
}

首先将它们全部添加到Pimple容器中:

$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']);
};

然后你可以通过调用应用实例上的容器来获取它们。

$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;
});