Skip to content

Commit a9025e3

Browse files
author
王赛
committed
Merge pull request #22 from mpandar/master
搞定IoC和facades翻译
2 parents bf7464c + 274e918 commit a9025e3

File tree

2 files changed

+354
-0
lines changed

2 files changed

+354
-0
lines changed

cn/facades.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Facades
2+
3+
- [介绍](#introduction)
4+
- [说明](#explanation)
5+
- [实际用例](#practical-usage)
6+
- [创建 Facades](#creating-facades)
7+
- [模拟 Facades](#mocking-facades)
8+
- [Facade 类参考](#facade-class-reference)
9+
10+
<a name="introduction"></a>
11+
## 介绍
12+
13+
Facades(一种设计模式,通常翻译为外观模式)提供了一个"static"(静态)接口去访问注册到[IoC 容器](/docs/4.2/ioc)中的类 。Laravel 含有很多 facades,你可能不知道其实你在某些地方已经使用过它们了。Laravel的"facades"就像"静态代理方法",为IoC容器中的类服务,相比传统的静态方法,在保持了更强的可测试性和灵活性的同时,它提供更简洁,更富有表现力的语法。
14+
15+
有时候, 你可能想为你的应用程序或包创建自己的 facades, 所以,让我们来讨论一下如何开发和使用这些类。
16+
17+
> **注意:** 在深入 facades 之前,我们强烈建议你多了解一下 Laravel [IoC 容器](/docs/4.2/ioc)
18+
19+
<a name="explanation"></a>
20+
## 说明
21+
22+
在 Laravel 应用程序中, facade 是提供从容器中访问对象的类。`Facade` 类实现了该机制。Laravel的facades,和其他自定义的facades,都需要继承基类`Facade`
23+
24+
你的 facade 类只需要实现一个方法: `getFacadeAccesor``getFacadeAccessor` 方法的工作是定义如何从容器中取得对象。 Facades 基类构建了 `__callStatic()` 魔术方法来从 facade 延迟访问取得对象。
25+
26+
因此,当你使用facade调用,类似`Cache::get`,Laravel会从IoC容器取得Cache管理类并调用`get`方法。在技术层上说,Laravel Facades是一种便捷的语法使用Laravel IoC容器作为服务定位器.
27+
28+
<a name="practical-usage"></a>
29+
## 实际用例
30+
31+
在以下示例中,调用Laravel缓存系统, 咋一看该代码,可能会认为`get`静态方法是在`Cache`类执行。
32+
33+
$value = Cache::get('key');
34+
35+
然后,如果我们查看`Illuminate\Support\Facades\Cache`类, 你会发现该类没有任何`get`静态方法:
36+
37+
class Cache extends Facade {
38+
39+
/**
40+
* Get the registered name of the component.
41+
*
42+
* @return string
43+
*/
44+
protected static function getFacadeAccessor() { return 'cache'; }
45+
46+
}
47+
48+
`Cache`类继承`Facade`这个基类,并且定义了个`getFacadeAccessor()`方法。注意,该方法的工作是返回绑定到`IoC`的名字。
49+
50+
当用户引用任何在`Cache` facade 中的静态方法, Laravel 从 IoC 容器绑定中取得 `cache`,并且执行请求的对象方法(在该例子中为`get`)。
51+
52+
所以,我们 `Cache::get` 执行可以重写为:
53+
54+
$value = $app->make('cache')->get('key');
55+
56+
<a name="creating-facades"></a>
57+
## 创建Facades
58+
59+
要为自己的应用程序或者包创建一个facade是非常简单的。你只需要做三件事情:
60+
61+
- 一个 IoC 绑定。
62+
- 一个 facade 类。
63+
- 一个 facade 别名配置。
64+
65+
让我们来看个例子。这里,我们定义一个`PaymentGateway\Payment`类。
66+
67+
namespace PaymentGateway;
68+
69+
class Payment {
70+
71+
public function process()
72+
{
73+
//
74+
}
75+
76+
}
77+
78+
这个类可以放在`app/models`目录,或者其他任何Composer能够自动载入的位置。
79+
80+
我们需要能够在 IoC 容器中取得该类。所以,让我们增加一个绑定:
81+
82+
App::bind('payment', function()
83+
{
84+
return new \PaymentGateway\Payment;
85+
});
86+
87+
最好注册该绑定的位置是创建一个新的名为`PaymentServiceProvider`[服务提供器](/docs/4.2/ioc#service-providers),并且将该绑定加入到 `register` 方法。接下来你就可以配置 Laravel `app/config/app.php` 配置文件来加载该服务提供器。
88+
89+
接下来,我们就可以创建我们的 facade 类:
90+
91+
use Illuminate\Support\Facades\Facade;
92+
93+
class Payment extends Facade {
94+
95+
protected static function getFacadeAccessor() { return 'payment'; }
96+
97+
}
98+
99+
最后,如果你想,我们可以为我们 facade 设置一个别名到 `app/config/app.php` 配置文件里的 `aliases` 数组。现在,我们能够调用 Payment 类实例的 `process` 方法。
100+
101+
Payment::process();
102+
103+
### 关于自动载入别名一些注意点
104+
105+
`aliases`数组中的有些类接口可能是不可行的,因为[PHP不会尝试去自动载入未定义的类型约定](https://bugs.php.net/bug.php?id=39003)。假设`\ServiceWrapper\ApiTimeoutException`别名是`ApiTimeoutException`, 如果`catch(ApiTimeoutException $e)` 是在`\ServiceWrapper`命名空间之外使用,它将会永远不会被捕获到, 即使真的有一个异常被抛出。 一个类似的问题存在在那些进行类型约定的别名类上。唯一的变通方法是摒弃别名,在每个你想使用类型约定的文件的开始的地方使用`use`
106+
107+
<a name="mocking-facades"></a>
108+
## 模拟Facades
109+
110+
单元测试是 facades 工作的重要体现。事实上,可测试性是 facedes 存在的主要原因。要了解更多信息,查看文档[模拟 facades](/docs/4.2/testing#mocking-facades)部分。
111+
112+
<a name="facade-class-reference"></a>
113+
## Facade 类参考
114+
115+
下面你会找到所有的facade以及其包含的类。这是一个非常有用的工具,可以根据给定的facade快速定位到API文档。适用于[IoC 绑定](/docs/ioc) 的也同时给出了其key。
116+
117+
Facade | Class | IoC Binding
118+
------------- | ------------- | -------------
119+
App | [Illuminate\Foundation\Application](http://laravel.com/api/4.2/Illuminate/Foundation/Application.html) | `app`
120+
Artisan | [Illuminate\Console\Application](http://laravel.com/api/4.2/Illuminate/Console/Application.html) | `artisan`
121+
Auth | [Illuminate\Auth\AuthManager](http://laravel.com/api/4.2/Illuminate/Auth/AuthManager.html) | `auth`
122+
Auth (Instance) | [Illuminate\Auth\Guard](http://laravel.com/api/4.2/Illuminate/Auth/Guard.html) |
123+
Blade | [Illuminate\View\Compilers\BladeCompiler](http://laravel.com/api/4.2/Illuminate/View/Compilers/BladeCompiler.html) | `blade.compiler`
124+
Cache | [Illuminate\Cache\Repository](http://laravel.com/api/4.2/Illuminate/Cache/Repository.html) | `cache`
125+
Config | [Illuminate\Config\Repository](http://laravel.com/api/4.2/Illuminate/Config/Repository.html) | `config`
126+
Cookie | [Illuminate\Cookie\CookieJar](http://laravel.com/api/4.2/Illuminate/Cookie/CookieJar.html) | `cookie`
127+
Crypt | [Illuminate\Encryption\Encrypter](http://laravel.com/api/4.2/Illuminate/Encryption/Encrypter.html) | `encrypter`
128+
DB | [Illuminate\Database\DatabaseManager](http://laravel.com/api/4.2/Illuminate/Database/DatabaseManager.html) | `db`
129+
DB (Instance) | [Illuminate\Database\Connection](http://laravel.com/api/4.2/Illuminate/Database/Connection.html) |
130+
Event | [Illuminate\Events\Dispatcher](http://laravel.com/api/4.2/Illuminate/Events/Dispatcher.html) | `events`
131+
File | [Illuminate\Filesystem\Filesystem](http://laravel.com/api/4.2/Illuminate/Filesystem/Filesystem.html) | `files`
132+
Form | [Illuminate\Html\FormBuilder](http://laravel.com/api/4.2/Illuminate/Html/FormBuilder.html) | `form`
133+
Hash | [Illuminate\Hashing\HasherInterface](http://laravel.com/api/4.2/Illuminate/Hashing/HasherInterface.html) | `hash`
134+
HTML | [Illuminate\Html\HtmlBuilder](http://laravel.com/api/4.2/Illuminate/Html/HtmlBuilder.html) | `html`
135+
Input | [Illuminate\Http\Request](http://laravel.com/api/4.2/Illuminate/Http/Request.html) | `request`
136+
Lang | [Illuminate\Translation\Translator](http://laravel.com/api/4.2/Illuminate/Translation/Translator.html) | `translator`
137+
Log | [Illuminate\Log\Writer](http://laravel.com/api/4.2/Illuminate/Log/Writer.html) | `log`
138+
Mail | [Illuminate\Mail\Mailer](http://laravel.com/api/4.2/Illuminate/Mail/Mailer.html) | `mailer`
139+
Paginator | [Illuminate\Pagination\Factory](http://laravel.com/api/4.2/Illuminate/Pagination/Factory.html) | `paginator`
140+
Paginator (Instance) | [Illuminate\Pagination\Paginator](http://laravel.com/api/4.2/Illuminate/Pagination/Paginator.html) |
141+
Password | [Illuminate\Auth\Reminders\PasswordBroker](http://laravel.com/api/4.2/Illuminate/Auth/Reminders/PasswordBroker.html) | `auth.reminder`
142+
Queue | [Illuminate\Queue\QueueManager](http://laravel.com/api/4.2/Illuminate/Queue/QueueManager.html) | `queue`
143+
Queue (Instance) | [Illuminate\Queue\QueueInterface](http://laravel.com/api/4.2/Illuminate/Queue/QueueInterface.html) |
144+
Queue (Base Class) | [Illuminate\Queue\Queue](http://laravel.com/api/4.2/Illuminate/Queue/Queue.html) |
145+
Redirect | [Illuminate\Routing\Redirector](http://laravel.com/api/4.2/Illuminate/Routing/Redirector.html) | `redirect`
146+
Redis | [Illuminate\Redis\Database](http://laravel.com/api/4.2/Illuminate/Redis/Database.html) | `redis`
147+
Request | [Illuminate\Http\Request](http://laravel.com/api/4.2/Illuminate/Http/Request.html) | `request`
148+
Response | [Illuminate\Support\Facades\Response](http://laravel.com/api/4.2/Illuminate/Support/Facades/Response.html) |
149+
Route | [Illuminate\Routing\Router](http://laravel.com/api/4.2/Illuminate/Routing/Router.html) | `router`
150+
Schema | [Illuminate\Database\Schema\Blueprint](http://laravel.com/api/4.2/Illuminate/Database/Schema/Blueprint.html) |
151+
Session | [Illuminate\Session\SessionManager](http://laravel.com/api/4.2/Illuminate/Session/SessionManager.html) | `session`
152+
Session (Instance) | [Illuminate\Session\Store](http://laravel.com/api/4.2/Illuminate/Session/Store.html) |
153+
SSH | [Illuminate\Remote\RemoteManager](http://laravel.com/api/4.2/Illuminate/Remote/RemoteManager.html) | `remote`
154+
SSH (Instance) | [Illuminate\Remote\Connection](http://laravel.com/api/4.2/Illuminate/Remote/Connection.html) |
155+
URL | [Illuminate\Routing\UrlGenerator](http://laravel.com/api/4.2/Illuminate/Routing/UrlGenerator.html) | `url`
156+
Validator | [Illuminate\Validation\Factory](http://laravel.com/api/4.2/Illuminate/Validation/Factory.html) | `validator`
157+
Validator (Instance) | [Illuminate\Validation\Validator](http://laravel.com/api/4.2/Illuminate/Validation/Validator.html)
158+
View | [Illuminate\View\Factory](http://laravel.com/api/4.2/Illuminate/View/Factory.html) | `view`
159+
View (Instance) | [Illuminate\View\View](http://laravel.com/api/4.2/Illuminate/View/View.html) |
160+
161+
162+
163+
译者:mpandar(马胜盼)

cn/ioc.md

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# IoC 容器
2+
3+
4+
- [介绍](#introduction)
5+
- [基本用例](#basic-usage)
6+
- [哪里去注册绑定呢](#where-to-register)
7+
- [自动解析](#automatic-resolution)
8+
- [实际用例](#practical-usage)
9+
- [服务提供器](#service-providers)
10+
- [容器事件](#container-events)
11+
12+
<a name="introduction"></a>
13+
## Introduction
14+
15+
Laravel使用IoC(Inversion of Control,控制倒转,这是一个设计模式,可以先查看下百科)容器这个强有力的工具管理类依赖。依赖注入(也是一种设计模式,一般用于实现IoC)是一个不用编写固定代码来处理类之间依赖的方法,相反的,这些依赖是在运行时注入的,这样允许处理依赖时具有更大的灵活性。
16+
17+
理解 Laravel IoC容器是构建强大应用程序所必要的,也有助于Laravel 核心本身。
18+
19+
<a name="basic-usage"></a>
20+
## 基本用例
21+
22+
#### 绑定一个类型到容器
23+
24+
IoC 容器有两种方法来解决依赖关系:通过闭包回调或者自动解析。首先,我们来探究一下闭包回调。首先,需要绑定一个“类型”到容器中:
25+
26+
App::bind('foo', function($app)
27+
{
28+
return new FooBar;
29+
});
30+
31+
#### 从容器中取得一个类型
32+
33+
$value = App::make('foo');
34+
35+
当执行 `App::make` 方法,闭包函数被执行并返回结果。
36+
37+
38+
#### 绑定一个”共享“类型到容器
39+
40+
有时,你只想将绑定到容器的类型处理一次,然后接下来从容器中取得的都应该是相同实例:
41+
42+
App::singleton('foo', function()
43+
{
44+
return new FooBar;
45+
});
46+
47+
#### 绑定一个已经存在的类型实例到容器
48+
49+
你也可以使用`instance`方法,将一个已经存在的对象接口绑定到容器中:
50+
51+
$foo = new Foo;
52+
53+
App::instance('foo', $foo);
54+
55+
<a name="where-to-register"></a>
56+
## 哪里去注册绑定呢
57+
58+
IoC绑定,很像事件句柄或者路由过滤,通常在"bootstrap code(引导代码)"之后完成。换句话说,它们在你的应用程序准备处理请求,也即是在一个路由或者控制器被实际执行之前执行。和其他引导代码一样,`start`文件通常作为IoC绑定注册一种方法。另外,你可以创建一个`app/ioc.php`(文件名不一定一样)文件,并在`start`文件中包含它。
59+
60+
如果你的应用程序有很大量IoC绑定,或者你想根据不同的分类将IoC绑定分割到不同的文件,你可以尝试在[服务提供器](#service-providers)中进行绑定
61+
62+
<a name="automatic-resolution"></a>
63+
## 自动解析
64+
65+
#### 取得一个类
66+
67+
IoC容器足够强大,在许多场景下不需要任何配置就能取得类。例如
68+
69+
class FooBar {
70+
71+
public function __construct(Baz $baz)
72+
{
73+
$this->baz = $baz;
74+
}
75+
76+
}
77+
78+
$fooBar = App::make('FooBar');
79+
80+
81+
注意我们虽然没有在容器中注册`FooBar`类,容器仍然可以取得该类,甚至自动注入`Baz`依赖!
82+
83+
当某个类型没有绑定到容器,IoC容器将使用 PHP 的反射工具来检查类和读取构造器的类型提示。使用这些信息,容器可以自动构建类实例。
84+
85+
#### 绑定一个接口实现
86+
87+
然而,在某些情况下,一个类可能依赖某个接口实现,而不是一个 “具体的类”。当在这种情况下,`App::bind`方法必须通知容器注入哪个接口实现:
88+
89+
App::bind('UserRepositoryInterface', 'DbUserRepository');
90+
91+
现在考虑下这个控制器:
92+
93+
class UserController extends BaseController {
94+
95+
public function __construct(UserRepositoryInterface $users)
96+
{
97+
$this->users = $users;
98+
}
99+
100+
}
101+
102+
由于我们将 `UserRepositoryInterface` 绑定了具体类,`DbUserRepository` 在该控制器创建时将会被自动注入到该控制器。
103+
<a name="practical-usage"></a>
104+
## 实际用例
105+
106+
Laravel 提供了几个方法使用 IoC 容器增强应用程序可扩展性和可测试性。一个主要的例子是取得控制器。所有控制器都通过 IoC 容器取得,意味着可以在控制器构造方法中对依赖的类型提示,它们将自动被注入。
107+
108+
#### 对控制器的依赖关系做类型提示
109+
110+
class OrderController extends BaseController {
111+
112+
public function __construct(OrderRepository $orders)
113+
{
114+
$this->orders = $orders;
115+
}
116+
117+
public function getIndex()
118+
{
119+
$all = $this->orders->all();
120+
121+
return View::make('orders', compact('all'));
122+
}
123+
124+
}
125+
126+
在这个例子中,`OrderRepository` 将会自动注入到控制器。意味着当 [单元测试](/docs/4.2/testing) 模拟请求时,`OrderRepository` 将会绑定到容器以及注入到控制器中,允许无痛与数据库层交互。
127+
128+
#### IoC 使用的其他例子
129+
130+
[过滤器](/docs/4.2/routing#route-filters), [composers](/docs/4.2/responses#view-composers), 和 [事件句柄](/docs/4.2/events#using-classes-as-listeners)也能够从IoC容器中获取到。当注册它们的时候,只需要把它们使用的类名简单给出即可:
131+
132+
Route::filter('foo', 'FooFilter');
133+
134+
View::composer('foo', 'FooComposer');
135+
136+
Event::listen('foo', 'FooHandler');
137+
138+
<a name="service-providers"></a>
139+
## 服务提供器
140+
141+
服务器提供器是将一组相关 IoC 注册到单一路径的有效方法。将它们看做是一种引导组件的方法。在服务器提供器里,你可以注册自定义的验证驱动器,使用 IoC 容器注册应用程序仓库类,甚至是自定义 `Artisan` 命令。
142+
143+
事实上,大多数核心 Laravel 组件包含服务提供器。应用程序所有注册在服务提供器的均列在 `app/config/app.php` 配置文件的 `providers` 数组中。
144+
145+
#### 定义服务提供器
146+
147+
要创建服务提供器,只需继承 `Illuminate\Support\ServiceProvider` 类并且定义一个 `register` 方法:
148+
149+
150+
use Illuminate\Support\ServiceProvider;
151+
152+
class FooServiceProvider extends ServiceProvider {
153+
154+
public function register()
155+
{
156+
$this->app->bind('foo', function()
157+
{
158+
return new Foo;
159+
});
160+
}
161+
162+
}
163+
164+
注意在 `register` 方法,应用程序通过 `$this->app` 属性访问 IoC 容器。一旦你已经创建了提供器并且想将它注册到应用程序中, 只需简单的放入 app 配置文件里 `providers` 数组中。
165+
166+
#### 运行时注册服务提供器
167+
168+
你也可以使用 `App::register` 方法在运行时注册服务提供器:
169+
170+
App::register('FooServiceProvider');
171+
172+
<a name="container-events"></a>
173+
## 容器事件
174+
175+
#### 注册获取事件监听者
176+
177+
容器在每次获取对象时都触发一个事件。你可以通过使用 `resolving` 方法来监听该事件:
178+
179+
App::resolvingAny(function($object)
180+
{
181+
//
182+
});
183+
184+
App::resolving('foo', function($foo)
185+
{
186+
//
187+
});
188+
189+
注意获取到的对象将会传入回调函数中。
190+
191+
译者:mpandar(马胜盼)

0 commit comments

Comments
 (0)