控制反转 (IoC) 容器是一个用于管理类依赖的工具。依赖注入是一种移除硬编码类依赖的方法。相反,依赖项在运行时注入,从而实现更大的灵活性,因为依赖项实现可以轻松替换。
IoC 容器可以通过两种方式解析依赖:通过闭包回调或自动解析。首先,我们将探讨闭包回调。首先,一个“类型”可以绑定到容器中。
App::bind('foo', function($app) {
return new FooBar;
});$value = App::make('foo');当 App::make 方法被调用时,Closure 回调函数会执行并返回结果。
有时你可能希望将某个东西绑定到容器中,该东西只应解析一次,并且后续对容器的调用应返回相同的实例:
App::singleton('foo', function() {
return new FooBar;
});您也可以将现有对象实例绑定到容器中 使用 instance 方法:
$foo = new Foo;
App::instance('foo', $foo);在某些情况下,一个类可能依赖于一个接口实现,而不是一个“具体类型”。当出现这种情况时,必须使用 App::bind 方法来通知容器应该注入哪个接口实现:
App::bind('UserRepositoryInterface', 'DbUserRepository');现在考虑以下代码:
$users = App::make('UserRepositoryInterface');既然我们已经将 UserRepositoryInterface 绑定到一个具体类型,DbUserRepository 将会在这个控制器被创建时自动注入其中。
IoC 绑定,如事件处理器,通常属于“引导代码”的范畴。换句话说,它们为您的应用程序实际处理请求做准备,通常需要在路由或控制器实际被调用之前执行。最常见的位置是插件注册文件的 boot 方法。另外,插件可以在插件目录中提供一个名为 init.php 的文件,您可以使用它来放置 IoC 注册逻辑。
服务提供者是创建库并在一个单独位置执行与组相关的 IoC 注册的好方法。在服务提供者中,你可以注册一个自定义认证驱动,将你应用的仓库类注册到 IoC 容器中,甚至设置一个自定义的 Artisan 命令。
事实上,插件注册文件继承服务提供者并且大多数核心组件都包含服务提供者。你的应用程序所有已注册的服务提供者都列在 providers 数组的 config/app.php 配置文件中。
要创建服务提供者,只需扩展 October\Rain\Support\ServiceProvider 类并定义一个 register 方法:
use October\Rain\Support\ServiceProvider;
class FooServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('foo', function() {
return new Foo;
});
}
}请注意,在 register 方法中,你可以通过 $this->app 属性访问应用程序的 IoC 容器。一旦你创建了一个服务提供者并准备好将其注册到你的应用程序中,只需将其添加到你的 app 配置文件中的 providers 数组即可。
你也可以在运行时使用 App::register 方法注册服务提供者。
App::register('FooServiceProvider');您可以使用 before 和 after 方法在请求路由之前注册特殊事件。
App::before(function ($request) {
// Code to execute before the request is routed
});
App::after(function ($request) {
// Code to execute after the request is routed
});服务容器每次解析一个对象时都会触发一个事件。你可以使用 resolving 方法监听此事件。
App::resolving(function ($object, $app) {
// Called when container resolves object of any type...
});
App::resolving('foo', function ($fooBar, $app) {
// Called when container resolves objects using hint "foo"...
});
App::resolving('Acme\Blog\Classes\FooBar', function ($fooBar, $app) {
// Called when container resolves objects of type "FooBar"...
});正如你所看到的,正在解析的对象将被传递给回调函数,允许你在它被交给其消费者之前,在该对象上设置任何额外属性。
你可以使用 environment 方法来发现由 环境配置 所确定的应用程序环境。
// production
App::environment();可以使用 runningInBackend 方法来判断当前请求是否正在后台管理区域中执行。
App::runningInBackend();你也可以使用 runningInConsole 方法来检查正在执行的代码是否在 命令行界面:
App::runningInConsole();