laravel自定义门面
https://learnku.com/articles/19195
博客 /
Laravel / 11个月前 / 9415 / 44 / 更新于 2个月前 / 1 个改进
DI
DI 就是常说的依赖注入,那么究竟什么是依赖注入呢?
打个比方,电脑(非笔记本哈)需要键盘和鼠标我们才能进行操作,这个‘需要’换句话说就是‘依赖’键盘和鼠标。
那么,相应的,一个类需要另一个类才能进行作业,那么这也就是依赖。
看一段代码:
class Computer {
protected $keyboard;
public function __construct() {
$this->$keyboard = new Keyboard();
}
}
这里的Computer类依赖了键盘类。
好,既然我们已经知道了什么是依赖,那么什么是注入呢?
我们改造一下上面的代码:
class Computer {
protected $keyboard;
public function __construct(Keyboard $keyboard) {
$this->$keyboard = $keyboard;
}
}
$computer = new Computer(new Keyboard());
这里的Computer类依赖注入了Keyboard类。
关于依赖注入,我的理解是:
所需要的类通过参数的形式传入的就是依赖注入。
理解了依赖注入,我们可以接着理解 IOC。
IOC
IOC 是什么呢?
中文叫控制反转。啥意思呢? 这个看明白了 DI 后就能很容易的理解了。
通过 DI 我们可以看到,一个类所需要的依赖类是由我们主动实例化后传入类中的。
控制反转和这个有什么关系呢?
控制反转意思是说将依赖类的控制权交出去,由主动变为被动。
看一段 laravel 代码:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SessionController extends Controller
{
public function login(Request $request)
{
//这就是IOC,我们不需要主动传入类了一切由laravel去实现
}
}
看到这你可能有疑问了,这是怎么实现的呢?
这就是靠服务容器了,请往下接着看。
服务容器
看了很多文章,我一致认为服务容器就是一种设计模式。
它的目的就是解耦依赖。
它有点类似于我前面说的《享元模式》。区别在于服务容器解决了所有依赖的实现。
这里我们再从头至尾的看一遍,怎么一步步演化出服务容器。
依然是电脑的例子,我们知道电脑依赖键盘鼠标,可是键盘鼠标也有很多种呀。
先看一个最原始的代码例子:
class Computer {
protected $keyboard;
public function __construct($type = null) {
switch($type) {
case 'common':
$this->keyboard = new CommonKeyboard();
case 'awesome':
$this->keyboard = new AweSomeKeyboard();
default:
$this->keyboard = new Keyboard();
}
}
}
或许你一眼就看出了问题在哪。
如果我们又要增加一钟键盘,那我们又得对这个类进行修改。这样下去,这个类会变得庞大且耦合程度过高。
那么我们可以怎么修改呢?
- 工厂模式
这样我们可以避免直接的修改 Computer 类。
简单工厂
class Factory {
public static function getInstance($type){
switch($type) {
case 'common':
$this->keyboard = new CommonKeyboard();
break;
case 'awesome':
$this->keyboard = new AweSomeKeyboard();
break;
default:
$this->keyboard = new Keyboard();
break;
}
}
}
class Computer {
protected $keyboard;
public function __construct($type == null) {
$this->keyboard = Factory::getInstance($type);
}
}
这样使用简单工厂模式后,我们后续的修改可以不用对 Computer 类进行操作而只要修改工厂类就行了。这就相当于对 Computer 类进行了解耦。
Computer 类虽不在依赖那些键盘类了,但是却变为依赖工厂类了。
后续添加新类型的键盘就必须对工厂类进行修改。
所以这个工厂类还不能很好的满足要求,我们知道电脑对键盘的接口都是一致的,键盘必须实现这一接口才能被电脑识别,那我们对 Computer 和 Keyboard 类进行修改。
- DI(依赖注入)
interface Board {
public function type();
}
class CommonBoard implements Board {
public function type(){
echo '普通键盘';
}
}
class MechanicalKeyboard implements Board {
public function type(){
echo '机械键盘';
}
}
class Computer {
protected $keyboard;
public function __construct (Board $keyboard) {
$this->keyboard = $keyboard;
}
}
$computer = new Computer(new MechanialKeyBoard());
可是这样也有问题,如果我们后续对这台电脑使用的键盘不满意要进行替换呢? 我们又回到原点了,必须去修改传入的键盘类。
能不能做成可配置的呢?
- IOC 服务容器(超级工厂)
class Container
{
protected $binds;
protected $instances;
public function bind($abstract, $concrete)
{
if ($concrete instanceof Closure) {
$this->binds[$abstract] = $concrete;
} else {
$this->instances[$abstract] = $concrete;
}
}
public function make($abstract, $parameters = [])
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
array_unshift($parameters, $this);
return call_user_func_array($this->binds[$abstract], $parameters);
}
}
这就是一个简单的 IOC 服务容器。
这个怎么解决我们上述的问题呢?
$container = new Container;
$container->bind('Board', function($container){
return new CommonBoard;
});
$container->bind('Computer',function($container,$module){
return new Computer($container->make($module));
});
$computer = $container->make('Computer',['Board']);
这里生产出来的 Computer 类就是一个使用普通键盘的电脑类了。
解释一下代码:
bind(name,function($container){
return new Name;
})
这里的name和Name之间的关系是:
当我需要name类的时候你就给我实例化Name类。
make(name)方法是对name进行生产返回一个实例。
如果我们要更换键盘怎么办呢?
$container->bind('Board', function($container){
return new MechanicalBoard;
});
$container->bind('Computer',function($container,$module){
return new Computer($container->make($module));
});
$computer = $container->make('Computer',['Board']);
只要对 bind 绑定的 Board 类的实现进行修改,我们就可以很容易替换掉键盘了。这就是一个服务容器。
对服务容器进行一个理解:
容器就是一个装东西的,好比碗。而服务就是这个碗要装的饭呀,菜呀,等等东西。当我们需要饭时,我们就能从这个碗里拿到。如果你想在饭里加点菜(也就是饭依赖注入了菜),我们从碗里直接拿饭就可以了,而这些依赖都由容器解决了(这也就是控制反转)。
我们需要做的就是对提供的服务进行维护。
我们看一段真实的在 laravel 框架上能跑的代码:
当然 laravel 框架的服务容器比这里的要复杂很多了,但我们明白了它的使用目的以及使用场景就不难去入手 laravel 了。
PS:你的赞是我创作的动力!
为什么同是 9 年义务教育别人就那么优秀?
想知道请关注订阅号:Buger(关注送 laravel,linux,nginx 等学习资料!!!)
回复 ' 学习 ',推荐你 2 本书。
三海
laravel自定义门面的更多相关文章
- Laravel5 创建自定义门面(Facade)
门面为应用服务容器中的绑定类提供了一个“静态”接口.Laravel 内置了很多门面,你可能在不知道的情况下正在使用它们.Laravel 的门面作为服务容器中底层类的“静态代理”,相比于传统静态方法,在 ...
- 转: Laravel 自定义公共函数的引入
来源:Laravel 自定义公共函数的引入 背景习惯了 使用 ThinkPHP 框架,有一个公共方法类在代码编写上会快捷很多,所以有必要在此进行配置一番.测试框架:Laravel 5.5步骤指导1. ...
- laravel 自定义验证 Validator::extend
laravel 自定义验证 $messages = [ 'name.integer' => '名字不能为整型', 'name.max' => '长度不能超过5', ]; public st ...
- laravel 自定义常量方法
laravel 自定义常量方法 版本5以上验证OK 常量定义方案A: step1 按路径生成constants文件app/config/constants.php step2 constants文件里 ...
- Laravel开发:Laravel框架门面Facade源码分析
前言 这篇文章我们开始讲 laravel 框架中的门面 Facade,什么是门面呢?官方文档: Facades(读音:/fəˈsäd/ )为应用程序的服务容器中可用的类提供了一个「静态」接口.Lara ...
- Laravel自定义Api接口全局异常处理
在做API时,需要对一些异常进行全局处理,比如添加用户执行失败时,需要返回错误信息 // 添加用户 www.bcty365.com $result = User::add($user); if(emp ...
- laravel自定义分页功能的实现:
laravel版本:5.5.. 执行命令: php artisan vendor:publish --tag=laravel-pagination 在到 resources/views/vendor/ ...
- laravel 自定义分页 offset 和 limit 的使用
laravel 本身有一个自带的快速分页方法 paginate,只需要传入每页显示多少条数据就可以 了,但是如果想使用自定义从哪里开始呢,这时候就可以使用offset 和 limit 的组合,offs ...
- laravel php门面模式
门面模式 理解3个概念: 1)Container的概念,laravel所有的服务都注册在container里面,至于如何注册,就是使用service provider 2)service pr ...
随机推荐
- 设置Firefox自动清除缓存,无需手动清除
1.在firefox的地址栏上输入about:config回车 2.找到browser.cache.check_doc_frequency选项,双击将3改成1保存即可. 那么这个选项每个值都是什么含义 ...
- [JS]js中判断变量类型函数typeof的用法汇总[转]
1.作用: typeof 运算符返回一个用来表示表达式的数据类型的字符串. 可能的字符串有:"number"."string"."boolean&q ...
- centos6.5下配置django+uwsgi+nginx
https://blog.csdn.net/huanbia/article/details/54630180
- 看Linux 之父是如何定义 Linux?
看Linux 之父是如何定义 Linux? LINUX是什么? LINUX是一个免费类unix内核,适用于386-AT计算机,附带完整源代码.主要让黑客.计算机科学学生使用,学习和享受.它大部分用C编 ...
- TortoiseHg 学习笔记
0.前言 TortoiseHg是分布式的源代码管理工具Mercurial的GUIclient. mercurial 作为3大主流的分布式源代码管理工具.已经被广泛的使用.比如 googleco ...
- Spark中的Join类型
常规连接: 左半连接: 左半连接结果集:仅仅保留左边表中的行,这些行的joinkey出现在右边表中!!!(类似于leftTable.joinKey in (rightTable.joinKeys)). ...
- 【转】如何修改 video 样式
我们这里说的“修改 video 样式”并不是要自己实现一套 controls,而是尝试修改 video 的默认样式 隐藏全屏按钮 这个很容易查到 video::-webkit-media-contro ...
- linux 应用和发展
课程大纲 UNIX/Linux发展历史 自由软件 Linux应用领域 Linux学习方法 UNIX 发展历史 (1 )1965年,美国麻省理工学院(MIT). 通用电气公司(G ...
- ActiveMQ 控制台使用方法
一.为什么使用ActiveMQ 在总线的设计中可能会使用到JMS(Java Message Service)通道, Java消息服务(JMS)超越了生产商专有的MOM(Message-Oriented ...
- Fastcgi工作原理
FastCGI是一个可伸缩的,高速地在HTTP server和动态脚本语言间的接口 FastCGI优点 这种方式可以让HTTP服务器专一的处理静态请求或者将动态脚本服务器返回给客户端,很大程度上提高了 ...