快速理解Laravel容器(IOC、DI、Provider、Contract)

源码理解思维的提升

分享一些个人见解。
Laravel里面的某些概念,就像魔术一样,看起来很厉害,当知道魔术怎么变的,就会认为也不过如此。所以不必感觉Laravel里有些概念难以理解。

应当抛除被框架约束思维的枷锁,用PHP设计的角度去思考,关注大概,而不是在在框架层面逐行磨叽。毕竟源码那么多,越是底层变量越多,越抽象,频繁的调用和变量指向,看到天亮也看不明白。

PHP设计的角度去思考怎么理解:
对于Laravel源码,代码很优雅,很工程化,很正规,方便扩展,这是优点,坏处就是抽象,好比垃圾桶里的垃圾都要摆放好,太过于工程化的设计,会给写松散业务逻辑的开发者带来困惑。
举个例子,Laravel里面的很多契约,好多都是一个空interface,放到了vendor下,真的是可要可不要,也确实有不少人说泰勒·奥特威尔就是炫技。
所以迟早要被绕晕,必须抛开Laravel里面的各种细节,用不需要太工程化PHP代码去尝试实现它,实现的过程中会遇到各种优化或者是问题,然后逐步优化。

被框架约束思维的枷锁怎么理解:
框架发展了这么久,源码的累加,不是让从头看的,而是遇到了一类问题,需要追加代码,是一个演进的过程,通过出现的问题或要优化的需求作为驱动来实现代码(书写顺序),而不是通过代码的作用反推解决的问题(反向反了很难看懂源码,看不懂干啥的,原因就是这里),换句话说,1+1=?是问题,2是结果。方向反了只有结果2,怎么推理出问题是1+1,还是2+0,既然不知道问题,又怎么知道2的意义是啥,那个地方要用?

易经思维:像各国人描述乌龟,得学很长时间的各国语言(源码),随手画一个乌龟(思维),全世界的人多能看懂。
要发掘的不是源码这样写我怎么看懂,而是这样写解决了什么问题。

通俗的演进示例

第1步:直接上第一版代码,Test类实现查询功能,于是调用了MySQL类的select方法。

class MySQL {public function select() {echo '执行查询操作';}
}class Test {private $driver;public function __construct() {$this->driver = new MySQL();}public function search() {return $this->driver->select();}
}$crud = new Test();
$crud->search();

第2步:但是如果以后有了Oracle,PostgreSQL怎么办?,代码内部的依赖写死了。
所以类的内部要写活,将内部的依赖,反转到外边,控制权由类的外部控制,通过构造方法传参实现,这就是控制反转,方便代码解耦。

<?phpclass MySQL {public function select() {echo '执行查询操作';}
}class Test {private $driver;public function __construct($driver) {$this->driver = $driver;}public function search() {return $this->driver->select();}
}$crud = new Test(new MySQL);
$crud->search();

第3步:但是随着项目的复杂,类越来越多,对象到处都是,得有一个管事的领导人,进行统一管理,于是容器出现了。
容器至少需要两个方法,bind和make,bind用于存储,相当于领导人管辖的地域,分配一块地区,让这些容器有地方生存。make顾名思义就是制造,创建出来的这些容器(就是实例化的过程)让他们做事。
bind方法一般不会直接实例化对象,因为可能用不上,但是代码流程走到哪里了,存是得存起来,防止后期用得上,这很好理解,就好比Laravel的Cache模块,不是每次请求都一定能用得上,但是它仍旧会被预先加载。

class Container {private $container = [];public function bind($name, $class) {return $this->container[$name] = $class;}public function make($name) {$class = $this->container[$name] ?? null;if(! $class) {return null;}return new $class();}
}

第4步,整合到第2步的代码当中。
看起来简单东西搞复杂了,确实。但是框架中,对于大量的类和对象的管理却很有用,结合框架的反射,以及其它机制,是能够让类的管理变的更优雅的,
没有容器情况下的例子:
要狗肉账,张三问李四要债,李四说债务转移给王五了去问王五要,王五说债务转移给赵六了你去问他要,彼此踢皮球的环节耦合度太高,互相依赖。
在这里插入图片描述

有容器情况下的例子:
相当于直接起诉到法院,一步到位,不管你是谁。我通过法院的管事人,去解决问题。
在这里插入图片描述

<?phpclass MySQL {public function select() {echo '执行查询操作';}
}class Test {private $driver;public function __construct($driver) {$this->driver = $driver;}public function search() {return $this->driver->select();}
}class Container {private $container = [];public function bind($name, $class) {return $this->container[$name] = $class;}public function make($name) {$class = $this->container[$name] ?? null;if(! $class) {return null;}return new $class();}
}$container = new Container();
$container->bind('MySQL', MySQL::class);$crud = new Test($container->make('MySQL'));
$crud->search();

Laravel容器

laravel容器的源码在vendor/laravel/framework/src/Illuminate/Container/Container.php
Laravel核心概念,类比成一个存放各类对象的数组,贯穿了整个Laravel流程,用于降低耦合度,管理并存储各模块的类与对象。
一个框架提供了很多模块,就需要很多对象,这些对象需要统一管理,自动实例化,以及类类型的形参自动实例化的反射机制,于是有了容器。

IOC(控制反转)

类内部的依赖,反转到类外边,控制权由类的外部控制,通过构造方法传参实现,这就是控制反转,方便代码解耦。
上文示例有说明。

DI(依赖注入)

依赖注入是控制反转的一种实现方式
依赖注入函数内部传参,有助于提高代码的模块化、可测试性和灵活性,通俗讲就是按(开发者)需加载。
如下,UserController依赖于UserService类。在控制器的构造函数中注入了 UserService,而不是在 UserController 中实例化UserService的实例。Laravel的服务容器的反射机制会自动解析这个依赖关系。

class UserController extends Controller {protected $userService;public function __construct(UserService $userService) {$this->userService = $userService;}
}

Contract(契约)

看了容器的源码,发现有用到,顺便提一嘴。
听起来高大上,移除Laravel框架高大上的思维枷锁,也就一堆接口,用于规范化代码,实现大体布局,子类用它实现细节,没什么神奇的高科技。

Provider(服务提供者)

多个服务提供者组成一个容器,新建的provider需要再config/app.php中声明。
用于注册应用程序的服务、绑定依赖关系以及其它初始化操作,真用到的时候就去实现,没那么严谨。
先调用register方法,然后会去调用boot方法。

这个在安装某些插件的时候回去用这个,composer包里的代码,不足以支撑当前的应用场景,所以需要做一些配置,然后就用到了Provider。

app()、resolve()

我看到前公司技术老大经常这样用,以我目前的认知来看,这和直接用命名空间的逻辑去调用一个类没什么区别。

  • app(); 返回服务容器实例,参数可传递类名,表示调用那个类。
  • resolve();app()的别名, 函数使用服务容器解析给定名称的类或接口的实例,参数可传递类名,表示调用那个类。

扩展阅读

浅谈PHP框架中类成员方法的类类型形参是怎么利用ReflectionClass反射类自动实例化的(应该是全网首发)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/827934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vuetify3.0+tailwindcss+vite最新框架

1、根据vuetify官网下载项目 安装vuetify项目 2、根据tailwindcss官网添加依赖 添加tailwindcss依赖 3、 配置main.ts // main.ts import "./style.css"4、使用 <template><h1 class"text-3xl font-bold underline">Hello world!</…

解密 Grupo MasMovil 使用 ClickHouse 监控无线网络

本文字数&#xff1a;4151&#xff1b;估计阅读时间&#xff1a;11 分钟 作者&#xff1a;Rodrigo Aguirregabiria Herrero, Grupo MasMovil 审校&#xff1a;庄晓东&#xff08;魏庄&#xff09; 本文在公众号【ClickHouseInc】首发 我们很高兴与大家分享来自西班牙最大的电信…

数据类型总结

1 引言 在计算机的世界里&#xff0c;数据类型是被人类定义出来的&#xff0c;方便人去更好地理解、辨别数据。计算机只能识别二进制数&#xff0c;不可能要求写代码时&#xff0c;只是输入一些0/1的东西。通过定义数据类型&#xff0c;可以让人和计算机更好地“沟通”&#x…

如何评价微软发布的Phi-3,手机都可以运行的小模型

前几天才刚刚发布了Llama 3&#xff0c;今天微软就出手了&#xff0c;发布了小而精的phi-3 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 刚刚发布的Phi-3系列小模型技术报告&#xff0c;引起AI圈热议。 添加图片注释&#xff0c;不超过 140 字&#x…

【数据结构】三、栈和队列:1.栈的基础(从数据结构三要素讨论:逻辑结构、物理结构(存储结构)、数据运算(基本操作))

文章目录 栈Stack逻辑结构物理&#xff08;存储&#xff09;结构基本操作常考题型 栈Stack 逻辑结构 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或删除操作的线性表。 重要术语&#xff1a;栈顶&#xff08;现在能放入的一段&#xff09;&#xff0c;栈底&…

光接入网络的超宽带半导体光放大器

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 新颖的双有源层结构获得宽增益光谱&#xff0c;应用于多波单纤双向光放大 ----翻译Xiao Sun等人2016年撰写的文章&#xff0c;文中给出了宽光谱SOA的一种新颖的结构设计方法和仿真结果&#xff0c;但并未给…

JavaVue 借助json传递数据

由前端向后端发送一个json键值对 <template><div><button click"sendRequest">发送请求</button></div> </template><script setup> import axios from axios;const sendRequest () > {const jsonData {key1: value…

mysql面试题五(锁)

目录 1.mysql有哪些锁及作用 1. 行锁&#xff08;Row Locks&#xff09; 2. 间隙锁&#xff08;Gap Locks&#xff09; 3. Next-Key Locks 4. 意向锁&#xff08;Intention Locks&#xff09; 5. 表锁&#xff08;Table Locks&#xff09; 6. 元数据锁&#xff08;Metad…

蓝海彤翔作为协办单位参加2024陵水全球招商大会

4月16日&#xff0c;2024 陵水全球招商大会在海口第四届中国国际海南消费品博览会期间举办。蓝海彤翔作为本次大会的协办单位&#xff0c;将海南蓝陵数字科技有限公司与海南陵水国际数字内容产业平台落户陵水&#xff0c;标志着蓝海彤翔在数字内容产业领域迈出了坚实的一步&…

上位机图像处理和嵌入式模块部署(树莓派4b与视觉slam十四讲)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 实际使用中&#xff0c;树莓派4b是非常好的一个基础平台。本身板子价格也不是很贵&#xff0c;建议大家多多使用。之前关于vslam&#xff0c;也就是…

Docker基本操作学习

基本指令 docker服务启动&#xff1a; service docker start service docker restart service docker stop# 重启服务器自动运行docker systemctl enable docker镜像生成方式&#xff1a; 通过docker build DockerFile… 生成镜像 镜像相关指令&#xff1a; docker push 仓…

【Python】MongoDB中的批量写入案例,避免单条插入失败导致整体失败

当看尽潮起潮落 只要你记得我 你曾说过 会永远爱我 也许承诺 不过证明没把握 不用难过 不用掩饰什么 当结果是那么赤裸裸 其实不必说什么 才能离开我 起码那些经过属于我 &#x1f3b5; 莫文蔚《盛夏的果实》 MongoDB是一个功能强大的NoSQL数据库&#xf…

【黑马点评Redis——003优惠券秒杀4——消息队列Stream】

1. 目前还存在的问题 设置的阻塞队列可能会超出最大长度系统重启会导致阻塞队列中的信息消失&#xff0c;可能会出现问题 2. 消息队列 消息队列 (Message Queue)。 字面意思就是存放消息的队列。最简单的消息队列模型包括3个角色消息队列:存储和管理消息&#xff0c;也被称为…

甲醛传感器ETO-A1在建筑装修过程中甲醛监测的重要作用

随着建筑装修行业的快速发展&#xff0c;甲醛污染问题逐渐受到人们的关注。甲醛是一种常见的室内空气污染物&#xff0c;主要来源于建筑装修过程中使用的各种材料。为了保障人们的健康和安全&#xff0c;甲醛传感器在装修过程中的监测作用显得尤为重要。英国Alphasense公司推出…

vue3 -- 基于maptalks和threejs实现3D地图板块效果

文章目录 🍉开发环境🍉实现效果🍉准备地图json文件🍉文件结构🍉代码🍉side_mode (纹理图片)🍉开发环境 vue“3.3.4”maptalks“1.0.0-rc.23”maptalks.three“^0.38.3”three“~0.143.0”maptalks/gl-layers“^0.34.1”node“v16.20.0”pnpm“8.6.2”🍉实现效

矽塔SA6288Q栅极驱动器,可替代峰绍FD6288Q

SA6288 是一款集成了三个独立半桥栅极驱动器&#xff0c;特别适合于三相电机应用中高速功率MOSFET 和 IGBT 的栅极驱动。可在高达250V 电压下工作。 SA6288内置 VCC 和 VBS 欠压&#xff08; UVLO &#xff09;保护功能&#xff0c;防止功率管在过低的电压下工作&#xff0c;…

记一次 Java 应用内存泄漏的定位过程

问题现象 最近&#xff0c;笔者负责测试的某个算法模块机器出现大量报警&#xff0c;报警表现为机器CPU持续高占用。该算法模块是一个优化算法&#xff0c;本身就是CPU密集型应用&#xff0c;一开始怀疑可能是算法在正常运算&#xff0c;但很快这种猜测就被推翻&#xff1a;同…

vue 的 diff 算法

vue的diff算法&#xff0c;是其虚拟DOM实现中的核心部分&#xff0c;用于高效地比较新旧虚拟节点&#xff0c;并据此更新实际的DOM&#xff0c; vue的diff算法&#xff0c;基于以下策略来优化性能&#xff1a; 1、同层比较&#xff1a; Vue 的 diff 不会跨层级比较节点&…

springboot基于点餐码 二维码在线点餐系统vue.js+java

Maven: 项目管理和构建自动化工具&#xff0c;用于java项目。 java: 广泛使用的编程语言&#xff0c;适用于构建跨平台应用。 Springmvc:从而在使用Spring进行WEB开发时&#xff0c;可以选择使用Spring的Spring MVC框架。 MyBatis: java持久层框架&#xff0c;支持定制化SQL、存…

DirectX12(D3D12)基础教程(二十三) ——DirectShaderCompiler 头文件接口 ID3DInclude 的应用

目录 1、前言2、ID3DInclude 回调接口介绍3、基本使用方法4、示例代码中的实现 1、前言 本章教程较短小&#xff0c;但内容十分重要&#xff0c;是后续更灵活使用 Shader 编程的重要基础之一。也就是对 Shader 代码进行头文件分离复用设计进行全面支持。或者直白的说&#xff0…