文档章节

From Apprentice To Artisan 翻译 04

zgldh
 zgldh
发布于 2014/10/08 20:38
字数 1215
阅读 2775
收藏 2

上一篇

Reflect Resolution 反射解决方案

One of the most powerful features of the Laravel container is its ability to automatically resolve dependencies via reflection. Reflection is the ability to inspect a classes and methods. For example, the PHP ReflectionClass class allows you to inspect the method avaliable on a given class. The PHP method method_exists is also a form of reflection. To play with PHP's reflection class, try the followring code on one of your classes:

用反射来自动处理依赖是Laravel容器的一个最强大的特性。反射是一种运行时探测类和方法的能力。比如,PHP的ReflectionClass可以探测一个类的方法。method_exists某种意义上说也是一种反射。我们来把玩一下PHP的反射类,试试下面的代码吧(StripeBiller换成你自己定义好的类):

<!-- lang: php -->
$reflection = new ReflectionClass('StripeBiller');
var_dump($reflection->getMethods());
var_dump($reflection->getConstants());

By leveraging this powerful feature of PHP, the Laravel IoC container can do some interesting things! For instance, consider the following class:

依靠这个强大的PHP特性, Laravel的IoC容器可以实现很有趣的功能!考虑接下来这个类:

<!-- lang:php -->
class UserController extends BaseController
{
    public function __construct(StripBiller $biller)
    {
        $this->biller = $biller;
    }
}

Note that the controller is type-hinting the StripBiller class. We are able to retrieve this type-hint using reflection. When the Laravel container does not have a resolver for a class explictity bound, it will try to resolve the class via reflection. The flow looks like this:

注意这个控制器的构造函数暗示着有一个StripBiller类型的参数。使用反射就可以检测到这种类型暗示。当Laravel的容器无法解决一个类型的明显绑定时,容器会试着使用反射来解决。程序流程类似于这样的:

  1. Do I have a resolver for StripBiller?

    已经有一个StripBiller的绑定了么?

  2. No resolver? Reflect into StripBiller to determin if it has dependencies.

    没绑定?那用反射来探测一下StripBiller吧。看看他都需要什么依赖。

  3. Resolve any dependencies needed by StripBiller (recursive).

    解决StripBiller需要的所有依赖(递归处理)

  4. Instantiate new StripBiller instance via ReflectionClass->newInstanceArgs().

    使用ReflectionClass->newInstanceArgs()来实例化StripBiller

As you can see, the container is doing a lot of heavy lifting for you, which saves you from having to write resolves for every single one of your classes. This is one of the most powerful and unique features of the Laravel container, and having a strong grasp of this capability is very beneficial when building large Laravel applications.

如你所见, 容器替我们做了好多重活,这能帮你省去写大量绑定的麻烦。这就是Laravel容器最强大也是最独特的特性。熟练掌握这种能力对构建大型Laravel应用是十分有益的。

Now, let's modify our controller a bit. What if it looks like this?

下面我们修改一下控制器, 改成这样会发生什么事儿呢?

<!-- lang:php -->
class UserController extends BaseController
{
    public function __construct(BillerInterface $biller)
    {
        $this->biller = $biller;
    }
}

Assuming we have not explicitly bound a resolver for BillerInterface, how will the container know what class to inject? Remember, interface can't be instantiated since they are just contracts. Without us giving the container any more information, it will be unable to instantiate this dependency. We need to specify a class that should be used as the default implementation of this interface, and we may do so via the bind method:

假设我们没有为BillerInterface做任何绑定, 容器该怎么知道要注入什么类呢?要知道,interface不能被实例化,因为它只是个约定。如果我们不提供更多信息的话,容器是无法实例化这个依赖的。我们需要明确指出哪个类要实现这个接口,这就需要用到bind方法:

<!-- lang:php -->
App::bind('BillerInterface','StripBiller');

Here, we are passing a string instead of a Closure, and this string tells the container to always use the StripBiller class anytime it needs an implementation of the BillerInterface interface. Again, we're gaining the ability to switch implementations of services with a simple one-line change to our container binding. For example, if we need to switch to Balanced Payments as our billing provider, we simply write a new BalancedBiller implementation of BillerInterface, and change our container binding:

这里我们只传了一个字符串进去,而不是一个匿名函数。 这个字符串告诉容器总是使用StripBiller来作为BillerInterface的实现类。 此外我们也获得了只改一行代码即可轻松改变实现的能力。比如,假设我们需要切换到Balanced Payments作为我们的支付提供商,我们只需要新写一个BalancedBiller来实现BillerInterface接口,然后这样修改容器代码:

<!-- lang:php -->
App::bind('BillerInterface', 'BalancedBiller');

Automatically, our new implementation will be used throughout out application!

我们的应用程序就装载上了的新支付实现代码了!

When binding implementations to interfaces, you may also use the singleton method so the container only instantiates one instance of the class per request cycle:

你也可以使用singleton方法来实现单例模式。

<!-- lang:php -->
App::singleton('BillerInterface', 'StripBiller');

Master The Container 掌握容器

Want to learn even more about the container? Read through its source! The container is only one class: Illuminate\Container\Container. Read over the source code to gain a deeper understanding of how the container works under the hood.

想了解更多关于容器的知识? 去读源码!容器只有一个类Illuminate\Container\Container. 读完了你就对容器有更深的认识了。

下一篇

© 著作权归作者所有

共有 人打赏支持
zgldh
粉丝 95
博文 35
码字总数 46344
作品 2
高级程序员
私信 提问
From Apprentice To Artisan 翻译 20

上一篇 Dependency Inversion Principle 依赖反转原则 Introduction 介绍 We have reached our final destination in our overview of the five SOLID design principles! The final princip......

zgldh
2015/03/19
0
4
From Apprentice To Artisan 翻译 17

上一篇 Open Closed Principle 开放封闭原则 Introduction 介绍 Over the life time of an application, more time is spent adding to the existing codebase rather than constantly addi......

zgldh
2015/03/18
0
0
From Apprentice To Artisan 翻译 08

上一篇 As Organizer 作为管理工具 One of the keys to building a well architected Laravel application is learning to use service providers as an organizational tool. When you are ......

zgldh
2014/12/09
0
0
From Apprentice To Artisan 翻译 02

上一篇 Taking It Further 更进一步 Let's consider another example to solidify our understanding. Perhaps we want to notify customers of charges to their account. We'll define tw......

zgldh
2014/08/22
0
1
From Apprentice To Artisan 翻译 16

上一篇 Single Responsibility Principle 单一职责原则 Introduction 介绍 The "SOLID" design principles, articulated by Robert "Uncle Bob" Martin, are five principles that provide ......

zgldh
2015/03/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

iframe里弹出的层显示在整个网页上

通过在iframe页面添加js脚本,动态给父窗体创建一个div,然后设置让其显示在最顶层这样就可以了 在文件夹中创建两个文件,一个iframe页面,一个父页面index。

少年已不再年少
4分钟前
0
0
聊聊storm trident spout的_maxTransactionActive

序 本文主要研究一下storm trident spout的_maxTransactionActive MasterBatchCoordinator storm-core-1.2.2-sources.jar!/org/apache/storm/trident/topology/MasterBatchCoordinator.java ......

go4it
13分钟前
0
0
js时间函数getTime() 在苹果手机上返回NaN的问题

一、出现问题 var newStartDate = new Date('2017-08-30');var newStartTime = newStartDate.getTime(); 获取到的时间戳,在Android手机正常,在IPhone中返回NaN。 问题说明: 在苹果手机...

tianma3798
15分钟前
0
0
访问日志不记录静态文件、切割和静态元素过期时间

11月16日任务 11.22 访问日志不记录静态文件 11.23 访问日志切割 11.24 静态元素过期时间 11.22、 访问日志不记录静态文件 网站大多元素为静态文件,如图片、css、js等,这些元素可以不用记录...

zgxlinux
21分钟前
0
0
爬虫教程」Python做一个简单爬虫,小白也能看懂的教程

俗话说“巧妇难为无米之炊”,除了传统的数据源,如历史年鉴,实验数据等,很难有更为简便快捷的方式获得数据,在目前互联网的飞速发展写,大量的数据可以通过网页直接采集,“网络爬虫”应运...

糖宝lsh
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部