イントロダクションIntroduction
Laravelのコントロールの逆転(Inversion of control)コンテナはクラスの依存性を管理するパワフルなツールです。依存性の注入は、ハードコードされたクラスの依存を取り除く手法です。代わりに依存は実行時に注入され、依存的な実装を簡単に交換できる、素晴らしい柔軟性をもたらせてくれます。The Laravel inversion of control container is a powerful tool for managing class dependencies. Dependency injection is a method of removing hard-coded class dependencies. Instead, the dependencies are injected at run-time, allowing for greater flexibility as dependency implementations may be swapped easily.
Laravelのコアで実際に役立っているIoCコンテナを理解することは、パワフルで大きなアプリケーションを構築する際に重要です。Understanding the Laravel IoC container is essential to building a powerful, large application, as well as for contributing to the Laravel core itself.
基本的な使い方Basic Usage
タイプをコンテナに結びつけるBinding A Type Into The Container
IoCコンテナが依存を解決する方法は2つあります。クロージャーのコールバックによる方法と自動的な解決です。最初はクロージャーのコールバックを説明しましょう。初めにコンテナに「タイプ」を結びつけます。There are two ways the IoC container can resolve dependencies: via Closure callbacks or automatic resolution. First, we'll explore Closure callbacks. First, a "type" may be bound into the container:
App::bind('foo', function($app)
{
return new FooBar;
});
コンテナでタイプを解決するResolving A Type From The Container
$value = App::make('foo');
App::make
メソッドが呼び出されると、クロージャーコールバックが実行され、結果がリターンされます。When the App::make
method is called, the Closure callback is executed and the result is returned.
「共用」のタイプをコンテナと結びつけるBinding A "Shared" Type Into The Container
場合により、一度だけ解決される何かをコンテナに結び付けたいこともあるでしょう。毎回コンテナを呼び出す代わりに、同じインスタンスを返してくれるほうが望ましいこともあります。Sometimes, you may wish to bind something into the container that should only be resolved once, and the same instance should be returned on subsequent calls into the container:
App::singleton('foo', function()
{
return new FooBar;
});
存在するインスタンスをコンテナに結びつけるBinding An Existing Instance Into The Container
また、既に存在するインスタンスをコンテナと結合したいこともあるでしょう。instance
メソッドを使用します。You may also bind an existing object instance into the container using the instance
method:
$foo = new Foo;
App::instance('foo', $foo);
どこで結合を登録するかWhere To Register Bindings
イベントハンドラーやルートフィルターのようなIoC結合は、一般的には「初期化コード」と呼ばれる一部に当たります。言い換えれば、これらはアプリケーションで実際にリクエストを処理する準備を行い、通常ルートやコントローラーが実際に呼び出される前に実行される必要があります。他の多くの準備コードと同様に、いつもstart
ファイルはIoCの結合を登録する選択肢の一つでしょう。もしくは、(ファイル名は何でも良いのですが)app/ioc.php
ファイルを作成し、start
ファイルからrequireで取り込むこともできます。IoC bindings, like event handlers or route filters, generally fall under the title of "bootstrap code". In other words, they prepare your application to actually handle requests, and usually need to be executed before a route or controller is actually called. Like most other bootstrap code, the start
files are always an option for registering IoC bindings. Alternatively, you could create an app/ioc.php
(filename does not matter) file and require that file from your start
file.
アプリケーションでとても多くのIoC結合が必要だったり、カテゴリーによりIoC結合を別々のファイルに組織化したい場合は、サービスプロバイダーで結合を登録して下さい。If your application has a very large number of IoC bindings, or you simply wish to organize your IoC bindings in separate files by category, you may register your bindings in a service provider[#service-providers].
自動的な解決Automatic Resolution
クラスを解決するResolving A Class
IoCコンテナは多くの状況で、設定を全く行なわずとも、とても強力にクラスを解決します。例えば:The IoC container is powerful enough to resolve classes without any configuration at all in many scenarios. For example:
class FooBar {
public function __construct(Baz $baz)
{
$this->baz = $baz;
}
}
$fooBar = App::make('FooBar');
コンテナでFooBarクラスを登録しなくても、クラスを解決できることに注目してください。コンテナはBaz
に対してさえ依存を自動的に注入し解決します。Note that even though we did not register the FooBar class in the container, the container will still be able to resolve the class, even injecting the Baz
dependency automatically!
あるタイプがコンテナと結びついていない場合、クラスを調べ、コンストラクターのタイプヒントを読み取るために、PHPのReflection機能が使われます。これにより取得した情報により、コンテナは自動的にクラスのインスタンスを生成します。When a type is not bound in the container, it will use PHP's Reflection facilities to inspect the class and read the constructor's type-hints. Using this information, the container can automatically build an instance of the class.
インターフェイスを実装と結びつけるBinding An Interface To An Implementation
しかしながら、「具象タイプ」ではなく、インターフェイスの実装に依存しているケースもあります。そうした場合、どのインターフェイスを実装したクラスが注入されるのかをApp::bind
メソッドで知らせる必要があります。However, in some cases, a class may depend on an interface implementation, not a "concrete type". When this is the case, the App::bind
method must be used to inform the container which interface implementation to inject:
App::bind('UserRepositoryInterface', 'DbUserRepository');
では、以下のようなコントローラーを考えてみましょう。Now consider the following controller:
class UserController extends BaseController {
public function __construct(UserRepositoryInterface $users)
{
$this->users = $users;
}
}
UserRepositoryInterface
を実際のタイプと結びつけてあるため、このコントローラーが生成された時、DbUserRepository
が自動的に注入されます。Since we have bound the UserRepositoryInterface
to a concrete type, the DbUserRepository
will automatically be injected into this controller when it is created.
実践的な使い方Practical Usage
LaravelはIoCコンテナを使用し、アプリケーションの柔軟性とテストをしやすくする多くの機能を提供しています。良い例がコントローラーの解決です。全てのコントローラーはIoCコンテナを通じて解決されます。これが意味しているのは、コントローラーのコンストラクターにおけるタイプヒントの依存により、自動的に注されるということです。Laravel provides several opportunities to use the IoC container to increase the flexibility and testability of your application. One primary example is when resolving controllers. All controllers are resolved through the IoC container, meaning you can type-hint dependencies in a controller constructor, and they will automatically be injected.
タイプヒントのコントローラー依存Type-Hinting Controller Dependencies
class OrderController extends BaseController {
public function __construct(OrderRepository $orders)
{
$this->orders = $orders;
}
public function getIndex()
{
$all = $this->orders->all();
return View::make('orders', compact('all'));
}
}
この例でOrderRepository
クラスはコントローラーに自動的に注入されます。これが意味するのは、ユニットテストを行う際に、「モック」としてのOrderRepository
がコンテナーにより結び付けられ、コントローラーに注入され、データベースレイヤーの関係を面倒なしに代用(スタブ)してくれると言うことです。In this example, the OrderRepository
class will automatically be injected into the controller. This means that when unit testing[/docs/4.2/testing] a "mock" OrderRepository
may be bound into the container and injected into the controller, allowing for painless stubbing of database layer interaction.
IoCが使用される別の例Other Examples Of IoC Usage
フィルター、コンポーサー、イベントハンドラーもIoCコンテナにより解決されます。登録する時、シンプルに使用されるクラスの名前を指定してください。Filters[/docs/4.2/routing#route-filters], composers[/docs/4.2/responses#view-composers], and event handlers[/docs/4.2/events#using-classes-as-listeners] may also be resolved out of the IoC container. When registering them, simply give the name of the class that should be used:
Route::filter('foo', 'FooFilter');
View::composer('foo', 'FooComposer');
Event::listen('foo', 'FooHandler');
サービスプロバイダーService Providers
サービスプロパイダーは関係するIoC登録を一つの場所にまとめる素晴らしい方法です。アプリケーションのブートストラップコンポーネントとして捉えてください。サービスプロバイダーの中で、カスタム認証ドライバーを登録したり、アプリケーションのリポジトリクラスをIoCコンテナに登録したり、カスタムArtisanコマンドを準備したりさえできます。Service providers are a great way to group related IoC registrations in a single location. Think of them as a way to bootstrap components in your application. Within a service provider, you might register a custom authentication driver, register your application's repository classes with the IoC container, or even setup a custom Artisan command.
実際、Laravelのコアコンポーネントにサービスプロパイダーが含まれています。アプリケーションの全ての登録されたサービースプロバイダーはapp/config/app.php
設定ファイルの中で、providers
としてリストされています。In fact, most of the core Laravel components include service providers. All of the registered service providers for your application are listed in the providers
array of the app/config/app.php
configuration file.
サービスプロバイダを定義するDefining A Service Provider
サービスプロバイダを生成するには、ただIlluminate\Support\ServiceProvider
クラスを拡張し、register
メソッドを定義するだけです。To create a service provider, simply extend the Illuminate\Support\ServiceProvider
class and define a register
method:
use Illuminate\Support\ServiceProvider;
class FooServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('foo', function()
{
return new Foo;
});
}
}
register
メソッドの中で、アプリケーションIoCコンテナは$this->app
プロパティを通じ利用できることに注目してください。一度プロバイダーを作成すれば、アプリケーションに登録する準備はでき、後はただapp
設定ファイルのproviders
配列に付け加えるだけです。Note that in the register
method, the application IoC container is available to you via the $this->app
property. Once you have created a provider and are ready to register it with your application, simply add it to the providers
array in your app
configuration file.
実行時にサービスプロバイダーを登録するRegistering A Service Provider At Run-Time
また、実行時にApp::register
メソッドによりサービスプロバイダーを登録することもできます。You may also register a service provider at run-time using the App::register
method:
App::register('FooServiceProvider');
コンテナイベントContainer Events
Resolvingリスナーを登録Registering A Resolving Listener
コンテナはオブジェクトの解決時に毎回イベントを発行します。このイベントは`resolving'メソッドを使用しリッスンできます。The container fires an event each time it resolves an object. You may listen to this event using the resolving
method:
App::resolvingAny(function($object)
{
//
});
App::resolving('foo', function($foo)
{
//
});
解決されたオブジェクトがコールバックに渡されることに注目してください。Note that the object that was resolved will be passed to the callback.