2017-08-18 64 views
1

我是SLIM3的新手,並遵循教程在容器中獲取某些函數,我想從代碼中的任何位置訪問它。因此,這裏是我的index.php文件,其中我initalise一切:通過鍵入$this->logger訪問容器功能的最佳設計方法

<?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,這同樣適用於dbteacherdbagent,但我只能做到這裏面其中創建這些容器,當我從另一個類調用另一個函數我也希望能夠訪問它們,但我不想將它們傳遞給參數,因爲這將很難維護,但我也有關於使用這些容器的類以及$app變量,並將其擴展到我使用的每個類中,但聽起來並不正確。 解決這個問題的最好方法是什麼?

回答

5

您應該使用Slim3使用的依賴注入容器(Pimple)的功能。

話雖這麼說,我想說的是,動態創建「控制器」 s是不是很好,那抽象不應該存在,你應該只是做的是$response->getBody()->write($result);或在每一個簡單的方法$response->write($result);控制器。我也不明白爲什麼這個構造需要整個路由框架。

但無論如何,如果你不想保持這種解決方案,你可以使用疙瘩,我會解釋一個例子。

你有幾類不同的構造器參數:

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

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

首先將它們全部添加到piple容器:

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

感謝您的回答,api連接到具有不同模塊(即儀表板,類視圖,學生視圖等)的角度應用程序,每個人都有不同的API端點。我正在建立的是爲每個模塊(控制器)設置一個類,並在該類內部調用前端將調用的一個函數,這樣可以幫助開發人員確定他們應該在哪裏編寫新函數。 除此之外,這個$ app-> post將允許我在數據通過函數之前驗證數據,或者例如驗證用戶。 知道... –

+0

...你仍然會推薦每個API結束點函數都有一個$ app-> post,爲什麼? –

+1

@NaguibIhab jup,你可以[像這樣的結構](https://stackoverflow.com/a/45197291/4244993),那麼你仍然有一個類的功能。對於像身份驗證這樣的東西,你可以使用[中間件](https://www.slimframework.com/docs/concepts/middleware.html) – jmattheis