Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带OOP的PHP-MVC_Php_Oop_Model View Controller - Fatal编程技术网

带OOP的PHP-MVC

带OOP的PHP-MVC,php,oop,model-view-controller,Php,Oop,Model View Controller,我开始阅读symfony的书,并尝试自己实现一个真正基本的mvc框架来进行学习。我使用symfony的一些组件。 现在我有了一个index.php文件,如下所示 <?php require_once 'vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFrom

我开始阅读symfony的书,并尝试自己实现一个真正基本的mvc框架来进行学习。我使用symfony的一些组件。 现在我有了一个index.php文件,如下所示

<?php

require_once 'vendor/autoload.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$uri = $request->getPathInfo();

$frontController = new FrontController($uri);

您正在寻找的是依赖项注入容器(DIC)。这不仅仅是关于注入“模型”(实际上我讨厌这个词,因为我很困惑),而是关于注入任何类型的服务。DIC包含一个服务实例化逻辑。然后,您可以使用
FrontController
中的DIC获取所需服务并将其传递给控制器。此外,DIC引入了某种间接方式。您不必知道实际的服务实现,只需要知道它的名称

PHP最简单的DIC实现是。这是一个非常小的项目,我强烈建议您看看它的源代码。评论中提到的使用引擎盖下的丘疹

总之,您只需做两件事:

  • 在DIC中注册服务
  • 将此服务(或一些服务)注入控制器
注册服务的基本示例如下:

$container['orders'] = function($c) {
    return new OrdersModel();
};
通常,
FrontController
可以作为成员访问此类
$container
对象,或者
FrontController
本身可以是
容器。这种对象通常被称为
应用程序
。所有现有服务的注册必须在发送代码之前完成。由于注册服务不需要服务实例化(注册服务只是创建一个闭包),因此您可以免费注册数百个这样的服务,而无需额外的负载

现在,您需要以某种方式指定控制器的依赖项。一种方法是使用controller类中的
static
字段

class OrdersController {
    public static $dependencies = ['orders', 'otherService'];

    private $ordersModel;
    private $otherService;

    public function __construct($ordersModel, $otherService) {
        $this->ordersModel = $ordersModel;
        $this->otherService = $otherService;
    }
}
然后,在
FrontController
中实例化之前,您必须阅读每个控制器的依赖项列表:

...
$ctrlClass = !empty($request[1]) 
    ? ucfirst($request[1]) . "Controller" 
    : "IndexController";
$services = [];
foreach ($ctrlClass::dependencies as $serviceName) {
    $services[] = $this->container[$serviceName];
}

// Here could be better way - PHP is not my native lang.
$reflection = new ReflectionClass($classname);
$controller = $reflection->newInstanceArgs($services);
...
也就是说,到最后,您将获得一个控制器实例,其中包含所有必需的依赖项。这样的代码很容易测试

UPD:此外,服务
a
可能需要服务
B
作为内部依赖项。这种依赖性在Pimple方法中很容易满足:

$container['serviceA'] = function($c) {
    return new ServiceA($c['serviceB']);
};

$container['serviceB'] = function($c) {
    return new ServiceB();
};
在这种情况下,如果您的控制器需要
ServiceA
,它也间接地依赖于
ServiceB
。但是,您不必手动解决这种间接依赖关系

UPD2:进一步阅读:

  • 马丁·福勒

依赖注入确实是一个大话题。尝试阅读。如果你想创建自己的“框架”,我建议你看看。这是一个基于Symfony(由创建Symfony的同一个ppl创建)的微框架,为您提供了可使用的基本框架,并允许您自定义所需的组件。我想这对你来说是一次很好的学习经历。谢谢!我会看看粉刺和你给我的链接!
...
$ctrlClass = !empty($request[1]) 
    ? ucfirst($request[1]) . "Controller" 
    : "IndexController";
$services = [];
foreach ($ctrlClass::dependencies as $serviceName) {
    $services[] = $this->container[$serviceName];
}

// Here could be better way - PHP is not my native lang.
$reflection = new ReflectionClass($classname);
$controller = $reflection->newInstanceArgs($services);
...
$container['serviceA'] = function($c) {
    return new ServiceA($c['serviceB']);
};

$container['serviceB'] = function($c) {
    return new ServiceB();
};