与 laravel 相较,Yii2 将配置(依赖关系定义)外化,用行为(更类似于 python 中的织入)类,弥补
Trait
的一些不足,好处是可以动态扩展动作。至于事件处理则大同小异,有趣的是在命名上,yii2 借用了
jquery
事件系统的那一套,
on,off,trigger
。当然也相同之处,比如应用都是建立在容器之上。相比其它的面向领域,面向接口编程,Yii2 使用模块,来分层,分中心小应用,细化大架构。而
getter/setter
,及过滤器,java 痕迹太明显。
组件 Component
- Yii 应用的主要基石。是
yii\\base\\Component
类或其子类的实例主要由 属性(Property),事件(Event),行为(Behavior)三个功能组成
- 比常规的对象(Object)稍微重量级,要使用额外的内存和 CPU 时间来处理 事件 和 行为
- 不需要使用事件和行为时,继承
yii\\base\\Object
, 支持属性(Property)功能
- 永远在重写的构造方法结尾处调用一下父类的构造方法
- 实例化组件类,new 组件类, 组件普通参数 + 组件配置属性参数
\\Yii::createObject
静态方法,创建组件实例第一个数组参数 class 关联组件类名,后续关联元素依次为组件实例属性及值
Yii::createObject()
基于依赖注入容器实现
-
yii\\base\\BaseObject
类执行时的生命周期构造方法内的预初始化过程
- 通过 $config 配置对象
- 在 init () 方法内进行初始化后的收尾工作
- 对象方法调用,上述步骤皆在对象的构造方法内完成,即获得实例就已经初始化,可供使用
属性 Property
-
Yii
引入
yii\\base\\Object
的基类, 支持基于类内的
getter
和
setter
(读取器和设定器)方法来定义属性
- getter 和 setter 定义属性规则和限制这类属性的名字是不区分大小写,源于 PHP 方法名是不区分大小写
- 若此类属性名和类成员变量相同,以后者为准
- 该类属性不支持可见性(访问限制)
- 这类属性的 getter 和 setter 方法只能定义为非静态的
- 对不确定有无魔术方法
(getter 或 setter
的属性正常调用
property_exists()
将不会生效若真有此需求,应用
canGetProperty()
或
canSetProperty()
事件 Events
-
事件可以将自定义代码 “注入” 到现有代码中的特定执行点
附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行
事件处理器
Event Handlers
- 事件处理器是一个 PHP 回调函数,也可以是一个可调用对象
\'trim\'
[$object, $method]
[$class, $method]
function ($event) { ... }
事件对象 $event
event name
:事件名
event sender
:调用 trigger () 方法的对象
custom data
附加事件处理器时传入的数据,默认为空
附加事件处理器
- 调用组件类的 on 方法,诸如 \\yii\\base\\Component::on ()
public void on ( $name, $handler, $data = null, $append = true )
事件处理器顺序(Event Handler Order)
- 当事件被触发,已附加的处理器将按附加次序依次调用
yii\\base\\Event::event参数的‘yii\\base\\Event::handled
属性为真
触发事件(Triggering Events)
- 事件通过调用
yii\\base\\Component::trigger()
方法触发
public void trigger ( $name, yii\\base\\Event $event = null )
yii\\base\\Event
类或其子类的实例
移除事件处理器(Detaching Event Handlers)
public boolean off ( $name, $handler = null )
类级别的事件处理器
- 应用场景 想要一个类的所有实例都响应一个被触发的事件
yii\\base\\Event::on()
在类级别附加处理器在事件处理器内,通过 $event->sender 获取触发事件的对象
public static boolean off ( $class, $name, $handler = null )
接口事件
- 调用
Event::on()
并将接口类名作为第一个参数
全局事件
- 需要一个全局可访问的单例,如应用实例
通配符事件 Wildcard Events
- foo.event.* , 通配符模式支持实例 或类级别的事件
行为
-
行为是
yii\\base\\Behavior
或其子类的实例,也称为 mixins, 类似于原生的 Trait
作用 无须改变类继承关系即可增强一个已有的 组件 类功能
- 当行为附加到组件后,它将 “注入” 它的方法和属性到组件
- 行为通过组件能响应被触发的事件,从而自定义或调整组件正常执行的代码
处理事件
- 让行为响应对应组件的事件触发, 应覆写
yii\\base\\Behavior::events()
方法行为的 events () 方法返回事件列表和相应的处理器,指定事件处理器格式如下指向行为类的方法名的字符串
附加行为
- 静态附加行为覆写行为要附加的组件类的 behaviors () 方法即可
- 在对应组件里调用
yii\\base\\Component::attachBehavior()
方法
yii\\base\\Component::attachBehaviors()
方法一次附加多个行为
public void attachBehaviors (array $behaviors )
- [‘as myBehavior2’ => MyBehavior::className()]
使用行为
- 必须先将为附加到 component 类或其子类组件,然后可通过访问组件访问行为的公共成员变量
$component->getBehavior(\'myBehavior\');
getBehaviors()
移除行为
- 可以调用
yii\\base\\Component::detachBehavior()
方法用行为相关联的名字实现
Yii2 内置行为类
yii\\behaviors\\TimestampBehavior
在 Active Record 存储时自动更新它的时间戳属性
yii\\behaviors\\BlameableBehavior
使用当前用户 ID 自动填充指定的属性
yii\\behaviors\\SluggableBehavior
自动填充指定的属性,其值可以在 URL 中用作 slug
yii\\behaviors\\AttributeBehavior
在发生特定事件时自动为 ActiveRecord 对象的一个或多个属性 指定一个指定的值
yii2tech\\ar\\softdelete\\SoftDeleteBehavior
提供软删除和软恢复 ActiveRecord 的 方法
yii2tech\\ar\\position\\PositionBehavior
允许通过提供重新排序方法来 管理整数字段中的记录顺序
行为 VS Traits
- 都将自己的属性和方法 “注入” 到主类中,二者类似互补类而非替代类
- Traits 比行为更有效,因为行为是既需要时间又需要内存的对象
- 当附属于同一组件的不同行为之间可能存在名称冲突时, 通过优先考虑附加到该组件的行为
配置 Configurations
-
概述
在创建新对象和初始化已存在对象时使用配置
- 配置通常包含被创建对象的类名和一组将要赋值给对象 属性的初始值
- 亦可包含一组将被附加到对象事件上的句柄,和一组将被附加到对象上的行为
使用
- Yii::createObject () 方法接受一个配置数组并根据数组中指定的类名创建对象
Yii::configure()
方法根据配置去初始化其属性
Yii::configure($object, $config)
配置的格式
class
元素指定了将要创建的对象的完全限定类名
propertyName
元素指定了对象属性的初始值,键名是属性名,值是该属性对应的初始值只有公共成员变量以及通过 getter/setter 定义的 属性可以被配置
on eventName
元素指定了附加到对象事件上的句柄,数组的键名由 on 前缀加事件名组成
as behaviorName
元素指定了附加到对象的行为,值表示创建行为的配置信息
应用的配置
- application 类拥有很多可配置的属性和事件
小部件的配置
yii\\base\\Widget::widget()
和
yii\\base\\Widget::begin()
方法都可以用来创建小部件
默认配置
Yii::createObject()
方法基于依赖注入容器实现
Yii::creatObject()
创建对象时,可以附加一系列默认配置到指定类的任何实例
Yii::$container->set()
来定义
别名
- 设置与解析使用
Yii::setAlias()
来给文件路径或 URL 定义别名
- 调用
Yii::getAlias()
命令来解析根别名到对应的文件路径或 URL
- 一个通过 Composer 安装的 扩展 都自动添加了一个别名,定义于引导启动阶段
类的自动加载
- Yii 自动加载器每个类都必须置于命名空间之下
- 每个类都必须保存为单独文件
- 要将自定义命名空间添加到自动加载器,需要使用 Yii::setAlias () 为命名空间的根目录定义别名
- 类映射表功能,建立一个从类的名字到类文件路径的映射
Yii::$classMap
方法向映射表中添加类
- 在其他自动加载器安装成功之后, 再包含 Yii.php (yii 的自动加载器)
服务定位器(Service Locator)
- 定义提供各种应用所需的服务(或组件)的对象
- 在服务定位器中, 每个组件都只有一个单独的实例,并通过 ID 唯一地标识
- 在 Yii 中,服务定位器是
yii\\di\\ServiceLocator
或其子类的一个实例
- 最常用的服务定位器是 application(应用)对象,可以通过 \\Yii::$app 访问
- 注册相关组件通过
yii\\di\\ServiceLocator::set()
方法进行相关组件注册。
public void set ( $id, $definition )
$definition
可以是类名,配置数组,php 可调用对象,或者本身就是一个对象实例
- 服务定位器会返回同一个组件的单例
yii\\di\\ServiceLocator::has()
检查某组件 ID 是否被注册
yii\\di\\ServiceLocator::get()
- 模块允许任意嵌套;Yii 应用程序本质上是一个模块树
依赖注入容器
- 依赖注入容器是一个对象,知道怎样初始化并配置对象及其依赖的所有对象
-
Yii 通过 yii\\di\\Container
类提供 DI 容器特性构造方法注入容器会尝试获取它所依赖的类或接口的实例,然后通过构造器将其注入新的对象
- 可以提供仅由类的单个方法需要的依赖关系
- Setter 和属性注入是通过配置提供,该配置会提供给容器用于通过相应的 Setter 或属性注入依赖
- 容器将使用已注册的 PHP 回调来构建类的新实例
yii\\di\\Container::get()
方法将其第三个参数作为配置数组应用于正在创建的对象 如果该类实现
yii\\base\\Configurable
接口(例如 yii\\base\\BaseObject),则配置数组将作为最后一个参数传递给类构造函数
- 注册依赖关系用
yii\\di\\Container::set()
注册依赖关系
- 注册会用到一个依赖关系名称和一个依赖关系的定义, 键值对可递归,方便容器管理实例,类似 laravel 的别名系统
- 依赖关系名称可为类名,接口名或一个别名,依赖关系的定义可以是类名,配置数组,一个 PHP 回调
- 通过
set()
注册的依赖关系,在每次使用时都会产生一个新实例
- 使用
yii\\di\\Container::setSingleton()
注册一个单例的依赖关系
- 依赖关系解析是递归式进行
set()
或
setSingleton()
注册的,也可以是一个类构造器参数列表和一个
configuration
用于配置新创建的对象
- 在应用程序的入口脚本中引入
Yii.php
文件时,
Yii
就创建了一个 DI 容器
Yii::$container
访问
Yii::createObject()
时,此方法实际上会调用这个容器的 get () 方法创建新对象
- 可一次配置多个定义 , 将配置数组传递给
setDefinitions()
或
setSingletons()
方法
key
:类名称,接口名称或别名
value
:与 class 关联的定义,
class关联的定义,‘identifies
参数值将传递给 set () 方法
Instance::of(\'tempFileStorage\')
符号,
Container
将隐含地提供一个用
tempFileStorage
名称注册的依赖项应用场景 内部配置依赖项
- 应用开发在入口注册依赖关系
- Yii 在依赖住入(DI)容器之上实现了它的服务定位器
更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)
还有更多进阶学习资料领取噢进阶PHP月薪30k>>>架构师成长路线【视频、面试文档免费获取】