文档章节

yii2 行为和Trait

阿北2017
 阿北2017
发布于 2017/08/28 15:00
字数 1633
阅读 31
收藏 0

这可能是大家最疑问的地方,到底有和不同。

进入我们自己的解释之前,我先把yii2官方的说法粘贴一份过来,这是一个我们在选择用行为还是trait的一个标准。

官方的说明

尽管行为在 "注入" 属性和方法方面类似于 trait ,它们在很多方面却不相同。如上所述,它们各有利弊。它们更像是互补的而不是相互替代。

行为的优势

  • 行为类像普通类支持继承。另一方面,trait 可以视为 PHP 语言支持的复制粘贴功能,它不支持继承。

  • 行为无须修改组件类就可动态附加到组件或移除。要使用 trait,必须修改使用它的类。

  • 行为是可配置的而 trait 不能。

  • 行为以响应事件来自定义组件的代码执行。

  • 当不同行为附加到同一组件产生命名冲突时,这个冲突通过先附加行为的优先权自动解决。而由不同 trait 引发的命名冲突需要通过手工重命名冲突属性或方法来解决。

trait 的优势

  • traits 比起行为更高效,因为行为是对象,消耗时间和内存。

  • IDE 对 trait 更友好,因为它们是语言结构。

  • 行为只能服务于组件类,而 trait 没有这个限制。

总结一下

通过上面的说明,总结来说就一条:用行为、用行为、用行为。

-------------------我是分割线------------------------

虽然我们已经会了行为,官方也说你就用行为就行了。但是我们还是有必要了解下traits,它到底是什么?

traits的注入

首先要说的是traits的目的是解决类只能单继承的问题,行为也是这个目的,我们在第一篇前导课 - 什么是行为?就已经分析了 。

有一点很重要,就是trait不能被实例化。

我们来举一个 trait 的例子,让你知道什么是trait

trait Mouse {
	public $name = '鼠标';
	public function click() {
		echo "鼠标点击了一下";
	}
}

class Computer {
	public function sayName(){
		echo "我是一台电脑";
	}
}

class Macbook extends Computer {
	use Mouse;
	public function say(){
		echo "我是一条有逼格的macbook";
	}
}

我来解释一下上面的代码,Macbook 和 Computer 是继承关系,Mouse 是一个trait ,Macbook 使用 use 关键字将 Mouse 注入到自己体内,此刻 Macbook 的 use 有点像yii2的 behaviors 函数。

接下来看看使用情况

$model= new Macbook ();
$model->say();// 我是一条有逼格的macbook
$model->sayName(); // 我是一台电脑
$model->click(); // 鼠标点击了一下

效果不错

很高兴的是 trait 也同样注入了 Macbook 类增强了其功能,但是和行为不同是我们必须通过修改 Macbook 类代码实现,而yii2的行为可以通过动态绑定来实现对 Macbook 类的零修改。关于动态绑定可以参考之前干货文章 传送门

优先级

这个问题在行为和 trait 中都会存在,当使用它们的类、继承的类中具有相同成员时谁会被使用?

  • 对于trait,优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
  • 对于行为,优先顺序是来自当前类的成员覆盖了被继承的方法,而继承的方法则覆盖了行为的方法。

没明白么?那看我的这个图。

alt

在顺序上略有不同。

多个组合成员名称冲突问题

什么意思那,就是一个类同时使用了多个 trait 的情况,看下面代码。

trait Mouse {
	public function click() {
		echo "鼠标点击了一下";
	}
}

trait Keyboard{
	public function click() {
		echo "键盘点击了一下";
	}
}

class Macbook  {
	use Mouse,Keyboard;
}

$model = new Macbook();
$model->click();

我们看看结果 哎 很不幸,对于此种情景PHP并没有给出自动处理方案,直接抛出了致命error。

这个时候我们必须人工参与,使用下面的关键词

  • insteadof
  • as

我们来说明下,还是上面的例子

...
class Macbook  {
	use Mouse,Keyboard {
		Mouse::click insteadof Keyboard;
	}
}

$model = new Macbook();
$model->click();

结果输出了 “鼠标点击了一下”,因为我们use的时候告诉php Mouse::click insteadof Keyboard,当冲突的时候使用Mouse的click代替Keyboard的同名方法。

当然我们还可以使用别名as,注意as无法替代insteadof,但是它可以让被替代者以其他的名字运行。

...
class Macbook  {
	use Mouse,Keyboard {
		Mouse::click insteadof Keyboard;
		Keyboard::click as keyClick;
	}
}

$model = new Macbook();
$model->click();
$model->keyClick();

看看结果

alt

我们解决了冲突。

yii2的多行为成员冲突问题

而对于yii2而言则按照先附加行为的优先权自动解决,并不会产生错误,具体如何解决本篇不再重复,可以去看下 揭秘yii2中行为的方法是如何注入到组件类中去的~ 这篇。

当然这种冲突解决方法会将后面的同名函数雪藏,而 trait 则可以将其通过as关键词再次启动起来。但是这个问题并不大,此种情景我们可以有太多方法解决了。

关于事件

event是个不能忽视的存在,通过前几篇我们都知道行为+事件可以拥有很多炫酷的注入能力,那么trait ?

当然也可以,但是会麻烦很多,我来举个例子。

// @app\components\EventTrait.php
namespace app\components;

use app\models\User;

trait EventTrait {
    public function initEvent(){
        User::on(User::EVENT_LOOK_ME,function(){
            echo "i am event";
        });
    }
}

// @app\models\User.php
class User extends \yii\db\ActiveRecord {
	...
	const EVENT_LOOK_ME = 'event_look_me';
	
	use EventTrait;
	...
}

// 在action中
$model = new User();
$model->initEvent();
$model->trigger(User::EVENT_LOOK_ME);

虽然也可以实现,但是自然没有行为来得容易,对代码的侵入性也太强,不建议这样用。

其他

当然根据官方还有很多,比如行为可配置等,这些因为前几篇都已经进行了讲解,这里不再重复。

整体来说,yii2行为和trait 都可以解决单继承问题,并且也具有很不错的注入和组合能力,但是在各方面行为和yii2其他模块整合更好一点,因此推荐用yii2的行为。

不过这不是说你可以放弃 trait 了,记住,行为只能服务于组件类,但是yii2的世界里还有不是组件类的孩子们,请思考。

最后说一句,今天七夕,祝兄弟连所有有媳妇的、有媳妇的节日快乐,没媳妇的赶紧code。


© 著作权归作者所有

共有 人打赏支持
阿北2017
粉丝 65
博文 56
码字总数 72253
作品 0
洛阳
Yii2 RC 版本发布下载,三年磨一剑!

今天YII2.0 RC版本已经发布,此版本现已提供下载: https://github.com/yiisoft/yii2/releases/tag/2.0.0-rc Yii 当前有两个主要版本:1.1 和 2.0。 1.1 版是上代的老版本,现在处于维护状态...

chinaphp
2014/09/28
4.4K
48
Yii2框架图解

Yii2框架图解 Love冥天个人博客-关注IT|PHP|互联网|php个人博客交流2017-11-281 阅读 yii2Yii2 图片根据Yii类参考手册,Yii源代码,开发常用方法构成. 1.yii2 控制器类图 2.yii2 cookie 类图...

Love冥天个人博客-关注IT|PHP|互联网|php个人博客交流
2017/11/28
0
0
yii2项目实战之配置

作者:白狼 出处:http://www.manks.top/document/yii2-blog-config.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律...

白狼栈
2016/08/01
24
0
yii2 - Behavior 实例及源码分析

Behavior 的简述 行为简单来说是组件的扩展,可以对组件的属性,方法,事件 (yii2组件的三大要点)进行扩展而无需改动组件现有的代码逻辑。即此行为所拥有的属性,方法,事件,都会被绑定它...

big_cat
2016/06/01
811
0
yii2开发中19条推荐实践(阿北总结)

虽然每个人的编程风格不同,但是有些建议能让你的代码更加规范和稳定,本次就我这次网站更新总结如下几点,希望对你的yii2学习和使用有所帮助。 环境说明 服务器环境: CentOS 开发环境及IDE...

阿北2017
06/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mac OS 最强鼠标改键软件:BetterAndBetter

官网: http://www.better365.cn 话不多说,先上你们最喜欢的软件界面截图。 通用: 触摸板: 鼠标: 键盘: 情景模式: 文本跳窗(自动跳窗): 四角触发: 工具箱: 脚本: 关于: 说下我目...

故国有明
40分钟前
16
0
Hbase Schema 模型设计注意事项及示例

一、Hbase 数据模型概述 HBase的数据模型也是由表组成,每一张表里也有数据行和列,但是在HBase数据库中的行和列又和关系型数据库的稍有不同。 表(Table): HBase会将数据组织成一张表,表名必...

PeakFang-BOK
今天
6
0
Blockathon(2018)上海竞赛项目成果今天揭晓

开幕式现场 10月19日,Blockathon(2018)上海在黄浦区P2联合创业办公社举行,本次活动由50名区块链开发者组成9支参赛队伍,来自国内外优秀区块链开发团队的20名技术专家担任导师及裁判。9支队...

HiBlock
今天
6
0
微信小程序开发系列六:微信框架API的调用

微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 微信小程序开发系列三:微信小程序的调试方法 微信小程序开发...

JerryWang_SAP
今天
12
0
5 个用 Python 编写 web 爬虫的方法

大家在读爬虫系列的帖子时常常问我怎样写出不阻塞的爬虫,这很难,但可行。通过实现一些小策略可以让你的网页爬虫活得更久。那么今天我就将和大家讨论这方面的话题。 我刚整理了一套2018最新...

糖宝lsh
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部