基于依赖注入容器的PHP项目示例及使用方法

ChatGPT4o 使用 ChatGPT 4o 回答

问题:

请根据最佳实践给出基于依赖注入容器核心文件:index.php,Router.php,Container.php,Controller.php,Model.php 及程序里面UserModel.php,UserController.php怎么使用实例化的Request和Database的代码

回答:

依赖注入(Dependency Injection, DI)是一种设计模式,它允许将对象的依赖关系从内部管理转移到外部容器管理。通过使用依赖注入容器(Dependency Injection Container, DIC),我们可以更好地管理对象的创建和依赖关系。

下面是一个简单的依赖注入容器示例,包括核心文件 index.php, Router.php, Container.php, Controller.php, Model.php 以及程序文件 UserModel.php, UserController.php。我们还会展示如何实例化 RequestDatabase 并在 UserController 中使用它们。

核心文件

index.php

<?php

require 'Container.php';
require 'Router.php';
require 'Controller.php';
require 'Model.php';
require 'UserModel.php';
require 'UserController.php';

// 创建依赖注入容器
$container = new Container();

// 注册 Request
$container->set('Request', function() {
    return new Request();
});

// 注册 Database
$container->set('Database', function() {
    return new Database('localhost', 'root', '', 'test_db');
});

// 注册 UserModel
$container->set('UserModel', function($c) {
    return new UserModel($c->get('Database'));
});

// 注册 UserController
$container->set('UserController', function($c) {
    return new UserController($c->get('Request'), $c->get('UserModel'));
});

// 创建路由器并处理请求
$router = new Router($container);
$router->handleRequest($_SERVER['REQUEST_URI']);

Router.php

<?php

class Router {
    private $container;

    public function __construct($container) {
        $this->container = $container;
    }

    public function handleRequest($uri) {
        // 简单的路由逻辑
        if ($uri == '/user') {
            $controller = $this->container->get('UserController');
            $controller->index();
        } else {
            echo "404 Not Found";
        }
    }
}

Container.php

<?php

class Container {
    private $bindings = [];

    public function set($name, $resolver) {
        $this->bindings[$name] = $resolver;
    }

    public function get($name) {
        if (isset($this->bindings[$name])) {
            return $this->bindings[$name]($this);
        }
        throw new Exception("No binding found for {$name}");
    }
}

Controller.php

<?php

abstract class Controller {
    protected $request;

    public function __construct($request) {
        $this->request = $request;
    }
}

Model.php

<?php

abstract class Model {
    protected $db;

    public function __construct($db) {
        $this->db = $db;
    }
}

程序文件

UserModel.php

<?php

class UserModel extends Model {
    public function getAllUsers() {
        // 假设我们有一个简单的查询
        $stmt = $this->db->query("SELECT * FROM users");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

UserController.php

<?php

class UserController extends Controller {
    private $userModel;

    public function __construct($request, $userModel) {
        parent::__construct($request);
        $this->userModel = $userModel;
    }

    public function index() {
        $users = $this->userModel->getAllUsers();
        echo json_encode($users);
    }
}

其他辅助类

Request.php

<?php

class Request {
    public function get($key, $default = null) {
        return $_GET[$key] ?? $default;
    }

    public function post($key, $default = null) {
        return $_POST[$key] ?? $default;
    }
}

Database.php

<?php

class Database extends PDO {
    public function __construct($host, $user, $pass, $dbname) {
        parent::__construct("mysql:host=$host;dbname=$dbname", $user, $pass);
    }
}

运行说明

  1. 将所有文件放在同一目录下。
  2. 确保数据库连接信息正确,并且数据库中有一个 users 表。
  3. 通过浏览器访问 /user 路径,应该会看到用户数据的 JSON 输出。

这个示例展示了如何使用依赖注入容器来管理对象的创建和依赖关系,从而使代码更加模块化和可测试。