簡體   English   中英

在MVC PHP中使用依賴注入

[英]Using Dependency Injection in MVC PHP

對於加載類,我使用PSR-4自動加載。 在我的index.php我使用FastRoute組件。 在該index.php我創建$ db連接並將其傳遞給控制器​​。

call_user_func_array([new $class($db), $method], $vars);

在控制器中,我將其接收並傳遞給模型並在其中使用。 我知道這是不好的方法。 index.php中創建的數據庫連接如何在我的模型中使用它而不通過控制器等傳遞,並且沒有單例連接實例? 如何使用DI或DIC在index.php建立數據庫連接並進入所有模型?

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

首先,您必須了解,“依賴注入”和“依賴注入容器”是兩個不同的東西:

  • DI是一種技術,用於在OOP中分離兩個類。
  • DIC是一款軟件,可以組裝對象圖

看來,您已經通過數據庫連接的方式很不好。 確切的技術原因可以描述為違反LoD 基本上,您的$db變量跨越了兩層邊界。

但是,解決方案不是 :“僅添加DI容器”。 那不會解決問題。 相反,您應該改進模型層的設計。 您可以在此處進行快速閱讀,但在這里我會給出一個簡短的版本:

  • 將持久性邏輯與域邏輯分開
  • 控制器應取決於服務,這將是控制器(存在於UI層中)與業務邏輯交互的方式。
  • 分離業務邏輯的最簡單方法是三部分:數據映射器(句柄持久性邏輯),域對象(用於業務規則)和服務(域對象與持久性對象之間的交互)

DB應該是datamapper的依賴項,它是專門為處理用戶實例而設計的(更多信息請參見 )。 該映射器應該是“帳戶管理服務”的直接依賴項(認為是好名聲),或者是使用該服務內部的工廠構造的(然后該工廠就是該服務的依賴項)。

PS至於“選擇哪個DIC”,我個人使用Symfony的獨立容器,但這純粹是個人喜好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM