Yii2 实例管理

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.php

class 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本身.到那时候的讨论可能涉及到更深的层次.就目前而言,就目前的应用层次,看待每一个框架,你会发现每个作者的思想都有很独特的地方,可能这个思想本身就已经大于框架本身的意义了,尤其是每个作者展现给我们的,在现实和理想冲突的时候,做出的妥协.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • date: 2017-11-21 18:15:18title: yii 源码解读 百度脑图 - yii 源码解析:...
    daydaygo阅读 3,468评论 1 11
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,071评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,622评论 18 399
  • Sites 网站 yiifeed:Yii 最新动态都在这里 yiigist:Yii 专用的 Packages my...
    guanguans阅读 2,654评论 0 11
  • 原贴 在安装过程中发现问题 一、安装Parallels Desktop Parallels Desktop 号称M...
    表象_Dark阅读 10,739评论 0 2