Yii2 实例管理

来源:互联网 发布:公司logo设计软件 编辑:程序博客网 时间:2024/05/20 11:27

Yii2 实例管理

Yii2框架没有提供类似ZendFramework3中提供的ServiceManager.那么Yii2框架是如何管理对象实例的呢?

长时间使用Yii2框架的童鞋一定已经适应了对象中的public变量,以及一个来自yii\base\Component的__set()魔术方法来完成对象构造的过程,但是新鸟如何使用这一切来实例化一个对象呢?

Yii2最擅长的是extends多个对象使他们拥有多个父类的特征.那么习惯了ZendFramework3这种纯粹OOP的童鞋,有没有方法既可以尽快适应Yii2的简约,又坚定的不侵犯对象变量的私有性,甚至还能优雅的用注入取代继承呢?

以下比较对象默认为ZendFramework3.

Yii2 对象的实例化

在ZendFramework3中,对象的实例化是我见过相对复杂的.

  1. 首先ServiceManager会读取所有已配置模块的Module对象(每个模块提供给ServiceManager的入口),并根据loadModules,loadModule等事件,以特定(可配置的,通过引用不同的内置Interface)方式获取模块配置文件.
  2. 获得配置文件时,ServiceManager会检查依赖(如果需要).
  3. 一切顺利后,ServiceManager会依照配置文件,寻找这个模块或类的工厂.工厂是一个callable,可以极其复杂,因为每个工厂会接受到整个项目的容器,也就是ServiceManager,也可以是简单的内置,InvokeFactory.
  4. 最终ServiceManager会自动的将工厂的产品,也就是这个模块的实例缓存到自身的变量中,以便全局可以访问.

可见ServiceManager是一个综合体,用于对象实例的管理,充当全局容器(里面甚至包含所有的配置文件和事件管理模块等所有框架的内核).

你肯定会担心性能损耗,在小型项目中这种损耗是有的,就像快速排序,面对大宗数据才是它大展身手的时候.也就是说,随着项目体量的增加,这种损耗的递增会远远低于体量的递增.

缺点:学习成本很高.


那么Yii2中有这样的机制吗?答曰,有.

Yii2中居然用一个近似让人啼笑皆非的方式解决了这个全局容器的需求.就是那个哪里都能看到的静态调用Yii.

use Yii;

很聪明!但是缺少了保障:

  1. 安全性.对于全部项目,Yii这个容器始终是可见的,没有注入的安全性,不注入你休想碰全局.Yii2的问题在于安全,尤其是多人开发的项目,例如通过Yii::$app->user->setIdentity($identity);轻松改变框架的当前登录用户,伪造当前用户.

  2. 稳定性.这个是我的猜测,将整个框架直接交给一个Yii,真的好吗?做法等同于将整个框架放入了一个PHP数组,并且这还是个全局的数组.

优点:学习成本很低.


Yii2在设计上表达了一个简单粗暴的观点,简单大于一切,甚至性能!

Yii2在对象的实例化时居然使用了Reflection[泪目.jpg],你没有看错,就是那个性能如老狗的反射.为什么呢?

就为了让你少些代码.

Yii::createObject([    'class' => 'foo\bar',    'name'  => 'Bob']);

以上代码实例化了一个foo\bar;对象,并执行了$bar->name = 'Bob';,怎么样,是不是很简单?这一切都是Reflection的功劳.当然Yii::createObject()还有一下用法,更加神奇.

//In foo/bar.phpclass bar{    public function __construct(SomeInterface $param1, $param2 = 'nothing')    {        //something to do.    }}//In some place.Yii::createObject('foo\bar', [    'param1' => $someClass,//instance from SomeInterface])

可见.Yii::createObject()还可以对你的__construct赋值.不但会检查参数列表的默认值,对象类型,而且还会为提供可变参数的构造函数检查PHP’版本.很贴心有木有?

但是这一切都是Reflection提供的.也是在PHP应用层能解决的唯一途径.

在动不动就实例化几百个对象的应用中,如果追求性能极致的小伙伴,最好还是自己实现实例管理工具.我也会在后续的空闲时间实现这个功能,请关注本人GitHub.

Yii2 对象实例的缓存

var_dump(Yii::$container->get(Test::class) === Yii::$container->get(Test::class));

上例返回false[懵逼.jpg],怎么回事,Yii2不缓存对象吗?那么Yii2的单例如何实现呢?

原来,Yii2中你要想让自己的对象被缓存,只有先Yii::$container->set(),再Yii::$container->get().setget的参数列表是对称的.

也就是说,Yii2不会自动给你缓存对象,实现单例.可能是怕误导不知道设计模式的初学者,为了对新手友好吧.

setget的具体用法在\yii\di\Container的注释中有非诚详细的说明.

值得一说的是,作者也意识到频繁的使用Reflection对性能的影响,所以在每次实例化的时候会自动的缓存对象的Reflection.这点还是非常温馨的.


Yii2中最常见的实例化对象的方法

Yii::createObject();

这个东西,这其实只是简单的对yii\di\Containreget()的封装.

这个方法有两个参数:

  1. 对象设置
    这是个数组,除了'class' => 'SomeClass'表示这个类的名字外,其他全部代表这个类的属性.
  2. constructor参数列表
    这个没有什么好解释的,就是构造函数的参数列表写成数组的形式而已.

总结

其实作文还没有写完,我并没有去yy怎样去自己实现一个实例容器模块.因为我想在模块出现在GitHub上的时候,结合README详细说明.并在以后的开发中不断改进.

毫无疑问,Yii2是个非常精妙的框架,脾气也非常清晰,易用大于一切,毕竟用框架开发的项目不会是超大项目.如果追求性能上的极致,可能任何框架都没法满足你的要求,甚至是PHP本身.到那时候的讨论可能涉及到更深的层次.就目前而言,就目前的应用层次,看待每一个框架,你会发现每个作者的思想都有很独特的地方,可能这个思想本身就已经大于框架本身的意义了,尤其是每个作者展现给我们的,在现实和理想冲突的时候,做出的妥协.

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 三星j3系统坏了怎么办 金立手机黑屏了怎么办 金立手机死机了怎么办 促卵泡生成素偏高怎么办 促卵泡成熟素偏高怎么办 促卵泡生成素100怎么办 路虎冷却液过低怎么办 强制险过期4个月怎么办 摩托车5年没年检怎么办 大事故定损不够怎么办 125摩托钥匙丢了怎么办 刺猬上的蜱虫怎么办 被宠物貂咬了怎么办 狗狗细小后咳嗽怎么办 十字绣丝线太滑怎么办 地垫与地面打滑怎么办 强电和水管交叉怎么办 小丫一个黄大怎么办 用友加密狗丢了怎么办 吸费软件扣费怎么办 我接了95515电话怎么办 硬盘没有4k对齐怎么办 梦幻西游鬼区了怎么办 移动4g信号不好怎么办 手机4g信号不好怎么办 家里4g信号不好怎么办 小孩流鼻涕怎么办最简单方法 猫鼻子摔出血了怎么办 让野猫挠出血了怎么办 家养猫咬出血了怎么办 被小猫抓出血了怎么办 猫咪指甲剪多了怎么办 猫咪指甲剪很了怎么办 家里的公猫老叫怎么办 猫生小猫没有奶怎么办 小孩凉了胃呕吐怎么办 母猫配种不配合怎么办 狗狗肚子有硬块怎么办 狗狗身上有硬块怎么办 小猫和大猫打架怎么办 大猫对小猫哈气怎么办