php 依赖注入框架,通过实现依赖注入和路由,构建一个自己的现代化PHP框架
如何提高自己编写代码的能力呢?我们首先想到的是阅读学习优秀的开源项目,然后写一个自己的web框架或类库组件。作为web开发者,我们通常都是基于面向对象OOP来开发的,所以面向对象的设计能力或者说设计模式的运用能力尤为重要,当然还有开发语言本身特性和基础的灵活运用。
我们可以去阅读一些优秀的开源项目,理解里面的代码设计,去学习和造轮子来提高自己。
在优秀成熟的web framework中,路由和http处理是web框架必不可少的,整个框架的服务对象依赖解析也是很重要的,有了依赖注入容器可以实现类很好的解耦。
依赖注入容器 Dependency Injection Container
先来说下什么是依赖注入,依赖注入是一种允许我们从硬编码的依赖中解耦出来,从而在运行时或者编译时能够修改的软件设计模式(来自维基百科 Wikipedia)。
依赖注入通过构造注入,函数调用或者属性的设置来提供组件的依赖关系。
下面的代码中有一个 Database 的类,它需要一个适配器来与数据库交互。我们在构造函数里实例化了适配器,从而产生了耦合。这会使测试变得很困难,而且 Database 类和适配器耦合的很紧密。
namespace Database;
class Database
{
protected $adapter;
public function __construct()
{
$this->adapter = new MySqlAdapter;
}
}
class MysqlAdapter {}
这段代码可以用依赖注入重构,从而解耦
namespace Database;
class Database
{
protected $adapter;
public function __construct(MySqlAdapter $adapter)
{
$this->adapter = $adapter;
}
}
class MysqlAdapter {}
现在我们通过外界给予 Database 类的依赖,而不是让它自己产生依赖的对象。我们甚至能用可以接受依赖对象参数的成员函数来设置,或者如果 $adapter 属性本身是 public的,我们可以直接给它赋值。
根据依赖注入的概念,我们的框架实现了这些特性。
Dependency injection Container基于PSR-11规范实现,使用了PHP的类反射功能,去实例化类定义的对象依赖。定义类的对象依赖包括3种注入实现方式:构造方法注入(Constructor Injection)、setter方法或属性注入(Setter Injection)、匿名回调函数注入,代码示例如下:
1.构造方法注入(Constructor Injection)
declare(strict_types=1);
namespace Examples;
use Eagle\DI\Container;
class Foo
{
/**
* @var \Examples\Bar
*/
public $bar;
/**
* Foo constructor.
* @param \Examples\Bar $bar
*/
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
/*class Bar {
}*/
class Bar {
public $baz;
public function __construct(Baz $baz)
{
$this->baz = $baz;
}
}
class Baz {
}
$container = new Container;
$container->set(Foo::class)->addArguments(Bar::class);
$container->set(Bar::class)->addArguments(Baz::class);
$foo = $container->get(Foo::class);
var_dump($foo, $foo->bar);
var_dump($foo instanceof Foo); // true
var_dump($foo->bar instanceof Bar); // true
var_dump($foo->bar->baz instanceof Baz); // true
2.方法注入(Setter Injection)
declare(strict_types=1);
namespace Examples;
require 'vendor/autoload.php';
use Eagle\DI\Container;
class Controller
{
public $model;
public function __construct(Model $model)
{
$this->model = $model;
}
}
class Model
{
public $pdo;
public function setPdo(\PDO $pdo)
{
$this->pdo = $pdo;
}
}
$container = new Container;
$container->set(Controller::class)->addArguments(Model::class);
$container->set(Model::class)->addInvokeMethod('setPdo', [\PDO::class]);
$container->set(\PDO::class)
->addArguments(['mysql:dbname=test;host=localhost', 'root', '111111']);
$controller = $container->get(Controller::class);
var_dump($controller instanceof Controller); // true
var_dump($controller->model instanceof Model); // true
var_dump($controller->model->pdo instanceof \PDO); // true
3.匿名回调函数注入(Closure callable Injection)
declare(strict_types=1);
namespace Examples;
require 'vendor/autoload.php';
use Eagle\DI\Container;
class Controller
{
public $model;
public function __construct(Model $model)
{
$this->model = $model;
}
}
class Model
{
public $pdo;
public function setPdo(\PDO $pdo)
{
$this->pdo = $pdo;
}
}
$container = new Container;
$container->set(Controller::class, function () {
$pdo = new \PDO('mysql:dbname=test;host=localhost', 'root', '111111');
$model = new Model;
$model->setPdo($pdo);
return new Controller($model);
});
$controller = $container->get(Controller::class);
var_dump($controller instanceof Controller); // true
var_dump($controller->model instanceof Model); // true
var_dump($controller->model->pdo instanceof \PDO); // true
自动装配(auto wiring)
declare(strict_types=1);
namespace AutoWiring;
require 'vendor/autoload.php';
use Eagle\DI\ContainerBuilder;
class Foo
{
/**
* @var \AutoWiring\Bar
*/
public $bar;
/**
* @var \AutoWiring\Baz
*/
public $baz;
/**
* Construct.
*
* @param \AutoWiring\Bar $bar
* @param \AutoWiring\Baz $baz
*/
public function __construct(Bar $bar, Baz $baz)
{
$this->bar = $bar;
$this->baz = $baz;
}
}
class Bar
{
/**
* @var \AutoWiring\Bam
*/
public $bam;
/**
* Construct.
*
* @param \AutoWiring\Bam $bam
*/
public function __construct(Bam $bam)
{
$this->bam = $bam;
}
}
class Baz
{
// ..
}
class Bam
{
// ..
}
$container = new ContainerBuilder;
$container = $container->build();
$foo = $container->get(Foo::class);
var_dump($foo instanceof Foo); // true
var_dump($foo->bar instanceof Bar); // true
var_dump($foo->baz instanceof Baz); // true
var_dump($foo->bar->bam instanceof Bam); // true
路由 Route
再介绍下路由的使用,route可以使用symfony的http foundation组件来处理HTTP请求(http messages)。
require 'vendor/autoload.php';
use Eagle\Route\Router;
use Symfony\Component\HttpFoundation\Request;
$router = new Router();
$router->get('/articles', function () {
return 'This is articles list';
});
$router->get('/articles/{id:\d+}', function ($id) {
return 'Article id: ' . $id;
});
/* title为可选参数 */
$router->get('/articles/{id:\d+}[/{title}]', function ($id, $title) {
return 'Article id: ' . $id . ', title: ' . $title;
});
/*匹配处理路由组*/
$router->group('/articles', function () use ($router) {
$router->get('/list', function() {
return 'This is articles list';
});
$router->get('/detail', function ($id, $title) {
return 'Article detail id: ' . $id . ', title: ' . $title;
});
});
$request = new Request();
$routeHandler = $router->getRouteHandler();
$response = $routeHandler->handle($request);
echo $response;
其它的ORM、cache、filesystem、session、validation等组件可以使用composer来由用户自由扩展。
php 依赖注入框架,通过实现依赖注入和路由,构建一个自己的现代化PHP框架相关推荐
- python selenium自动化框架_一文讲透!实现一个Python+Selenium的自动化测试框架如此简单!...
首先你得知道什么是Selenium? Selenium是一个基于浏览器的自动化测试工具,它提供了一种跨平台.跨浏览器的端到端的web自动化解决方案.Selenium主要包括三部分:Selenium I ...
- 【 .NET Core 3.0 】框架之九 || 依赖注入 与 IoC
本文有配套视频:https://www.bilibili.com/video/av58096866/?p=5 前言 1.重要:如果你实现了解耦,也就是 api 层只引用了 IService 和 IRe ...
- 依赖注入[5]: 创建一个简易版的DI框架[下篇]
为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在<依赖注入[4]: 创建一个简易版的DI框架[上篇]> ...
- php 框架 容器,thinkphp5.1框架容器与依赖注入实例分析
本文实例讲述了thinkphp5.1框架容器与依赖注入.分享给大家供大家参考,具体如下: 容器----/thinkphp/library/think/Container.php 依赖注入:将对象类型的 ...
- java dna框架_DNA - IOC依赖注入 - 组件类库 - JAVA开源项目 - 开源吧
相关开源项目 Coinjema:Coinjema这个组件通过AspectJ与Groovy提供了一种强大的依赖注入机制.假如你厌烦一大堆XML配置文件,和需要掌握复杂工厂类与容器的时候,这个non-AP ...
- 从壹开始前后端分离【 .NET Core2.2 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探...
更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...
- Spring框架----Spring的依赖注入
1.spring的依赖注入的概念 依赖注入:dependency Injection IOC的作用:降低程序之间的依赖关系,但不是消除. 依赖关系的管理:以后都交给了spring来维护 在当前类中需要 ...
- 什么是依赖注入 php,什么是依赖注入?
译文首发于 什么是依赖注入,转载请注明出处. 本文是依赖注入(Depeendency Injection)系列教程的第一篇文章,本系列教程主要讲解如何使用 PHP 实现一个轻量级服务容器,教程包括: ...
- python依赖注入_什么是依赖注入?
这篇文章是关于一般依赖关系注入和在PHP中实现依赖注入容器系列的第一部分. 今天我不会谈论容器然而我想以一些具体的示例介绍依赖注入的概念希望说明尝试去解决问题和它给开发者带来的好处.如果你已经知道依赖 ...
最新文章
- linux--nfs 网络文件共享
- SVM(支持向量机)综述
- 手摸手Go 深入剖析sync.Pool
- 20190826:(leetcode习题)反转链表
- java旅客接口_GitHub - s1mplecc/checkin-scheduler: 使用 Java 实现的旅客人数分布预估与值机排班调度算法...
- HTML5初探 - 基本的HTML5模版
- 我的2017:从工作再到学生
- 蓝桥杯 前缀判断——2013年省赛C/C++A组真题5
- 《软件体系结构》第三章 软件体系结构风格
- #边学边记 必修4 高项:对事的管理 第六章 项目质量管理 质量管理基础
- 支架预压弹性变形值计算_支架预压计算.doc
- C语言--fseek()
- ps里面的css,PS中如何添加图层样式
- 卡方检验的统计量推导_卡方检验如何计算?
- CSC申请成功经验(自动化到生物信息,德国KIT-CSC攻博)
- python爬取qq音乐评论+jieba分词并统计词频+绘制词云并可视化数据
- 清华大学计算机系成立量子软件研究中心,应明生受聘为主任
- 设计模式学习专栏六--------适配器模式
- 中国诗歌艺术之人文之魂1,2(四川大学文学与新闻学院王红)
- 将SDPT3配置到matlab