【发布时间】:2017-07-20 08:44:57
【问题描述】:
对于加载类,我使用 PSR-4 自动加载。在我的index.php 中,我使用 FastRoute 组件。在那个index.php 中,我创建了 $db 连接并将其传递给控制器。
call_user_func_array([new $class($db), $method], $vars);
在控制器中,我收到它并将其传递给模型并在那里使用它。
我知道这是不好的方法。在index.php 中创建的数据库连接如何在我的模型中使用它而不是通过控制器等传递它并且没有连接的单例实例?如何使用DI或DIC在index.php建立db连接并进入所有模型?
index.php:
<?php
require_once 'vendor/autoload.php';
$db = new DbConnection(new DbConfig($config));
$dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/users', 'UserController/actionGetAllUsers');
$r->addRoute('GET', '/users/{id:\d+}', 'UserController/actionGetUserById');
});
// Fetch method and URI from somewhere
$httpMethod = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
$uri = substr($uri, 0, $pos);
}
$uri = rawurldecode($uri);
switch ($routeInfo[0]) {
case FastRoute\Dispatcher::NOT_FOUND:
// ... 404 Not Found
break;
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
break;
case FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
list($class, $method) = explode("/", $handler, 2);
$module = strtolower(str_replace('Controller', '', $class));
$class = 'Vendorname\\' . $module . '\\controllers\\' . $class;
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
call_user_func_array([new $class($db), $method], $vars);
break;
}
控制器:
class UserController extends BaseApiController
{
protected $db;
public function __construct($db)
{
$this->db = $db;
parent::__construct();
}
public function actionGetAllUsers()
{
$model = new User($this->db);
echo json_encode($model->getAllUsers());
}
型号:
class User
{
protected $db;
public function __construct($db)
{
$this->db = $db;
}
public function getAllUsers()
{
$stmt = $this->db->prepare('SELECT * FROM user');
$stmt->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
【问题讨论】:
-
研究使用一些依赖注入容器,例如Pimple。 Illuminate/Container、league/container 或类似名称。这就是当今大多数框架所做的。
-
@MagnusEriksson 但我也应该将其注入控制器,并在我的示例中从控制器将其注入模型?我对 DIC 的理解正确吗?
-
没有。您应该只注入特定类本身需要的依赖项。假设“Controller1”需要“UserClass”而“UserClass”需要“Database”,控制器只会获得“UserClass”,但容器会确保您获得了“UserClass”的实例,该实例已经注入了“Database” .控制器不应该知道或关心“UserClass”依赖项。
-
对于大多数 DiC(除了 Illuminate),您将在开始时将所有类及其依赖项注册到容器中。然后,当您通过容器获取实例时,容器将确保您获得所有正确的实例,它们各自的依赖项已经注入(您已经注册到容器中)。看看上面提到的容器,他们有一些例子可能会更清楚。
标签: php design-patterns model-view-controller dependency-injection fastroute