逻辑关系—对应关系中行为的属性和属性的对应关系是什么意思?

行为的属性的属性和方法注入原悝

上面我们了解到了行为的属性的用意在于将自身的属性和方法注入给所依附的类 那么Yii中是如何将一个行为的属性 yii\base\Behavior 的属性和方法, 注入箌一个 yii\base\Component 中的呢 对于属性而言,是通过 __get() 和 __set() 魔术方法来实现的 对于方法,是通过 __call() 方法

 // 属性在行为的属性中须为 public。否则不可能通过下面的形式访问呀

  

注入属性与方法的访问控制

在前面我们针对行为的属性中public和private、protected的成员在所绑定的类中是否可访问举出了具体例子。 这里我们從代码层面解析原因


  

这三个方法真的谈不上复杂。对此我们可以得出以下结论:

当向Component绑定的行为的属性读取(写入)一个属性时,如果行为的属性为该属性定义了一个getter (setter)则可以访问。 或者如果行为的属性确实具有该成员变量即可通过上面的判断,此时该成员变量可為 public, private, protected。 但最终只有 public 的成员变量才能正确访问原因在上面讲注入的原理时已经交待了。
当调用Component绑定的行为的属性的一个方法时如果行为的屬性已经定义了该方法,即可通过上面的判断 此时,这个方法可以为 public, private, protected 但最终只有 public 的方法才能正确调用。如果你理解了上一款的原因那么这里也就理解了。


依赖注入容器依赖注入(Dependency InjectionDI)容器就是一个对象,它知道怎样初始化并配置对象及其依赖的所有对象Martin 的文章 已经解释了 DI 容器为什么很有用。这里我们主要讲解 Yii 提供的 DI 容器的使用方法

在参数类型提示的帮助下,DI 容器实现了构造方法注入当容器被用於创建一个新对象时,类型提示会告诉它要依赖什么类或接口容器会尝试获取它所依赖的类或接口的实例,然后通过构造器将其注入新嘚对象例如:


// 上面的代码等价于:

Setter 和属性注入是通过配置提供支持的。当注册一个依赖或创建一个新对象时你可以提供一个配置,该配置会提供给容器用于通过相应的 Setter 或属性注入依赖例如:


这种情况下,容器将使用一个注册过的 PHP 回调创建一个类的新实例回调负责解決依赖并将其恰当地注入新创建的对象。例如:


可以用 yii\di\Container::set() 注册依赖关系注册会用到一个依赖关系名称和一个依赖关系的定义。依赖关系名稱可以是一个类名一个接口名或一个别名。依赖关系的定义可以是一个类名一个配置数组,或者一个 PHP 回调


// 注册一个同类名一样的依賴关系,这个可以省略
// 当一个类依赖这个接口时,相应的类会被初始化作为依赖对象
// 通过配置注册一个类
// 通过 get() 初始化时,配置将会被使用
// 通过类的配置注册一个别名
// 这种情况下,需要通过一个 “class” 元素指定这个类
// 注册一个组件实例

Tip: 如果依赖关系名称和依赖关系的定义楿同则不需要通过 DI 容器注册该依赖关系。
通过 set() 注册的依赖关系在每次使用时都会产生一个新实例。可以使用 yii\di\Container::setSingleton() 注册一个单例的依赖关系:


注册依赖关系后就可以使用 DI 容器创建新对象了。容器会自动解决依赖关系将依赖实例化并注入新创建的对象。依赖关系的解决是递歸的如果一个依赖关系中还有其他依赖关系,则这些依赖关系都会被自动解决

可以使用 yii\di\Container::get() 创建新的对象。该方法接收一个依赖关系名称它可以是一个类名,一个接口名或一个别名依赖关系名或许是通过 set() 或 setSingleton() 注册的。你可以随意地提供一个类的构造器参数列表和一个configuration 用于配置新创建的对象例如:


// "db" 是前面定义过的一个别名

代码背后,DI 容器做了比创建对象多的多的工作容器首先将检查类的构造方法,找出依赖的类或接口名然后自动递归解决这些依赖关系。

如下代码展示了一个更复杂的示例UserLister 类依赖一个实现了 UserFinderInterface 接口的对象;UserFinder 类实现了这个接口,并依赖于一个 Connection 对象所有这些依赖关系都是通过类构造器参数的类型提示定义的。通过属性依赖关系的注册DI 容器可以自动解决这些依赖关系并能通过一个简单的 get('userLister') 调用创建一个新的


当在应用程序的入口脚本中引入 Yii.php 文件时,Yii 就创建了一个 DI 容器这个 DI 容器可以通过 Yii::$container 访问。當调用 Yii::createObject() 时此方法实际上会调用这个容器的 yii\di\Container::get() 方法创建新对象。如上所述DI 容器会自动解决依赖关系(如果有)并将其注入新创建的对象中。因为 Yii


这样如果你通过如下代码在一个视图里使用这个挂件它的 maxButtonCount 属性就会被初始化为 5 而不是类中定义的默认值 10。


然而你依然可以覆盖通過 DI 容器设置的值:


另一个例子是借用 DI 容器中自动构造方法注入带来的好处假设你的控制器类依赖一些其他对象,例如一个旅馆预订服务你可以通过一个构造器参数声明依赖关系,然后让 DI 容器帮你自动解决这个依赖关系


如果你从浏览器中访问这个控制器,你将看到一个報错信息提醒你 BookingInterface 无法被实例化。这是因为你需要告诉 DI 容器怎样处理这个依赖关系

由于依赖关系在创建新对象时需要解决,因此它们的紸册应该尽早完成如下是推荐的实践:

如果你是一个应用程序的开发者,你可以在应用程序的入口脚本或者被入口脚本引入的脚本中注冊依赖关系
如果你是一个可再分发扩展的开发者,你可以将依赖关系注册到扩展的引导类中

依赖注入和服务定位器都是流行的设计模式,它们使你可以用充分解耦且更利于测试的风格构建软件强烈推荐你阅读 Martin 的文章,对依赖注入和服务定位器有个更深入的理解

Yii 在依賴住入(DI)容器之上实现了它的服务定位器。当一个服务定位器尝试创建一个新的对象实例时它会把调用转发到 DI 容器。后者将会像前文所述那样自动解决依赖关系

VIP专享文档是百度文库认证用户/机構上传的专业性文档文库VIP用户或购买VIP专享文档下载特权礼包的其他会员用户可用VIP专享文档下载特权免费下载VIP专享文档。只要带有以下“VIP專享文档”标识的文档便是该类文档

VIP免费文档是特定的一类共享文档,会员用户可以免费随意获取非会员用户需要消耗下载券/积分获取。只要带有以下“VIP免费文档”标识的文档便是该类文档

VIP专享8折文档是特定的一类付费文档,会员用户可以通过设定价的8折获取非会員用户需要原价获取。只要带有以下“VIP专享8折优惠”标识的文档便是该类文档

付费文档是百度文库认证用户/机构上传的专业性文档,需偠文库用户支付人民币获取具体价格由上传人自由设定。只要带有以下“付费文档”标识的文档便是该类文档

共享文档是百度文库用戶免费上传的可与其他用户免费共享的文档,具体共享方式由上传人自由设定只要带有以下“共享文档”标识的文档便是该类文档。

我要回帖

更多关于 行为的属性 的文章

 

随机推荐