マネージャーとファクトリーManagers & Factories
ドライバーベースのコンポーネントの作成を管理する、複数のManager
クラスをLaravelは持っています。それらは、キャッシュ、セッション、認証、キューコンポーネントです。Managerクラスはアプリケーションの設定に基づき、特定のドライバーの実装を作成することに責任を持っています。例えば、CacheManager
クラスはAPC、Memcached、ファイル、その他のキャッシュの実装を生成することができます。Laravel has several Manager
classes that manage the creation of driver-based components. These include the cache, session, authentication, and queue components. The manager class is responsible for creating a particular driver implementation based on the application's configuration. For example, the CacheManager
class can create APC, Memcached, File, and various other implementations of cache drivers.
各マネージャーは、新しいドライバーのリゾルバーを簡単にマネージャへ登録できるように、extend
メソッドを備えています。以降では、各カスタムドライバーのサポートを注入する例と一緒に、こうしたマネージャーを説明していきます。Each of these managers includes an extend
method which may be used to easily inject new driver resolution functionality into the manager. We'll cover each of these managers below, with examples of how to inject custom driver support into each of them.
Note: どうぞ時間を取り、
CacheManager
やSessionManager
のように、初めからLaravelに用意してある様々なManager
クラスを調べてみてください。こうしたクラスを徹底的に読めば、Laravelの内部動作を完全に理解することができます。全Managerクラスは、Illuminate\Support\Manager
ベースクラスを拡張しており、各Managerに共通で便利な機能を提供しています。Note: Take a moment to explore the variousManager
classes that ship with Laravel, such as theCacheManager
andSessionManager
. Reading through these classes will give you a more thorough understanding of how Laravel works under the hood. All manager classes extend theIlluminate\Support\Manager
base class, which provides some helpful, common functionality for each manager.
キャッシュCache
Laravelのキャッシュ機能を拡張するには、CacheManager
のextend
メソッドを使用します。このメソッドはManagerへカスタムドライバーのリゾルバーを結合するために使用され、全Managerクラスで使用できます。例えば、"mongo"という名前のキャッシュドライバーを登録するには、次のようになります。To extend the Laravel cache facility, we will use the extend
method on the CacheManager
, which is used to bind a custom driver resolver to the manager, and is common across all manager classes. For example, to register a new cache driver named "mongo", we would do the following:
Cache::extend('mongo', function($app)
{
return Cache::repository(new MongoStore);
});
extend
メソッドの最初の引数は、ドライバーの名前です。この名前は、config/cache.php
設定ファイルの中のdriver
オプションと対応しています。2つ目の引数はクロージャーで、Illuminate\Cache\Repository
インスタンスをリターンしなければなりません。クロージャーは、Illuminate\Foundation\Application
のインスタンスであり、IoCコンテナでもある、$app
インスタンスへ渡されます。The first argument passed to the extend
method is the name of the driver. This will correspond to your driver
option in the config/cache.php
configuration file. The second argument is a Closure that should return an Illuminate\Cache\Repository
instance. The Closure will be passed an $app
instance, which is an instance of Illuminate\Foundation\Application
and an IoC container.
インストール後のLaravelアプリケーションに存在している、App\Providers\AppServiceProvider
中のboot
メソッドでCache::extend
は呼び出される必要があります。もしくは拡張を記述するために独自のサービスプロバイダーを作成することもできます。その場合、config/app.php
のproviders配列へ指定するのを忘れないでください。The call to Cache::extend
could be done in the boot
method of the default App\Providers\AppServiceProvider
that ships with fresh Laravel applications, or you may create your own service provider to house the extension - just don't forget to register the provider in the config/app.php
provider array.
カスタムキャッシュドライバーを作成するには、Illuminate\Contracts\Cache\Store
契約を実装する必要があります。ですから、MongoDBキャッシュの実装は、以下のようになるでしょう。To create our custom cache driver, we first need to implement the Illuminate\Contracts\Cache\Store
contract. So, our MongoDB cache implementation would look something like this:
class MongoStore implements Illuminate\Contracts\Cache\Store {
public function get($key) {}
public function put($key, $value, $minutes) {}
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function forget($key) {}
public function flush() {}
}
それぞれのメソッドをMongoDB接続を使用して実装する必要があります。実装を完了したら、カスタムドライバーの登録も完成させましょう。We just need to implement each of these methods using a MongoDB connection. Once our implementation is complete, we can finish our custom driver registration:
Cache::extend('mongo', function($app)
{
return Cache::repository(new MongoStore);
});
カスタムキャッシュドライバーコードをどこへ公開しようか迷っているなら、Packagist
で使用できるようにすることを考えてください!もしくは、appディレクトリーの中にExtensions
名前空間を作成することもできます。しかし、Laravelは厳格なアプリケーション構造を持っていないので、好みに合わせ、自由に構造を決めて良いことを覚えておきましょう。If you're wondering where to put your custom cache driver code, consider making it available on Packagist! Or, you could create an Extensions
namespace within your app
directory. However, keep in mind that Laravel does not have a rigid application structure and you are free to organize your application according to your preferences.
セッションSession
Laravelにカスタムセッションドライバーを拡張するのは、キャッシュシステムを拡張するのと同様、簡単です。カスタムコードを登録するため、セッションでもextend
メソッドを使用します。Extending Laravel with a custom session driver is just as easy as extending the cache system. Again, we will use the extend
method to register our custom code:
Session::extend('mongo', function($app)
{
// Return SessionHandlerInterfaceの実装を返す
});
セッションをどこで拡張するかWhere To Extend The Session
セッションの拡張は、AppServiceProvider
のboot
メソッドの中へコードしましょう。You should place your session extension code in the boot
method of your AppServiceProvider
.
セッションの拡張をコーディングするWriting The Session Extension
カスタムセッションドライバーはSessionHandlerInterface
を実装する必要があることに注意してください。このインターフェイスは、実装する必要のあるシンプルないくつかのメソッドを含んでいます。MongoDB実装のスタブは、以下のようなコードになります。Note that our custom session driver should implement the SessionHandlerInterface
. This interface contains just a few simple methods we need to implement. A stubbed MongoDB implementation would look something like this:
class MongoHandler implements SessionHandlerInterface {
public function open($savePath, $sessionName) {}
public function close() {}
public function read($sessionId) {}
public function write($sessionId, $data) {}
public function destroy($sessionId) {}
public function gc($lifetime) {}
}
これらのメソッドは、キャシュのStoreInterface
のように、簡単に理解できないため、それぞれのメソッドを簡単に解説しましょう。Since these methods are not as readily understandable as the cache StoreInterface
, let's quickly cover what each of the methods do:
open
メソッドは、通常ファイルベースのセッション保存システムで使用されます。Laravelには最初からfile
セッションドライバーが含まれているため、このメソッドにはほとんど何も記述する必要はないでしょう。空っぽのスタブのままにしておけます。PHPがこのメソッドを私達に実装しろと要求しているのは、実際、インターフェイスの設計がまずいからに過ぎません。(後ほど説明します。)Theopen
method would typically be used in file based session store systems. Since Laravel ships with afile
session driver, you will almost never need to put anything in this method. You can leave it as an empty stub. It is simply a fact of poor interface design (which we'll discuss later) that PHP requires us to implement this method.close
メソッドは、open
メソッドと同様に、通常無視できます。ほとんどのドライバーでは、必要ありません。Theclose
method, like theopen
method, can also usually be disregarded. For most drivers, it is not needed.read
メソッドは、指定された$sessionId
に関係付けられた、文字列のセッションデーターをリターンする必要があります。ドライバーからセッションデーターを取得したり、保存したりする時に、シリアライズや他のエンコードを行う必要はありません。Laravelがシリアライズを行います。Theread
method should return the string version of the session data associated with the given$sessionId
. There is no need to do any serialization or other encoding when retrieving or storing session data in your driver, as Laravel will perform the serialization for you.write
メソッドは$data
文字列を$sessionId
と関連付けて、MongoDBやDynamo、その他の持続的なストレージシステムに保存する必要があります。Thewrite
method should write the given$data
string associated with the$sessionId
to some persistent storage system, such as MongoDB, Dynamo, etc.destroy
メソッドは、$sessionId
に関連付けられたデーターを持続的なストレージから削除します。Thedestroy
method should remove the data associated with the$sessionId
from persistent storage.gc
メソッドは、指定されたUNIXタイムスタンプの$lifetime
より古いセッションデーターを全部破棄しなくてはなりません。MemcachedやRedisのように、自分で古いデーターを破棄するシステムでは、このメソッドは空のままにします。Thegc
method should destroy all session data that is older than the given$lifetime
, which is a UNIX timestamp. For self-expiring systems like Memcached and Redis, this method may be left empty.
SessionHandlerInterface
を実装したら、セッションマネージャーに登録する準備ができました。Once the SessionHandlerInterface
has been implemented, we are ready to register it with the Session manager:
Session::extend('mongo', function($app)
{
return new MongoHandler;
});
セッションドライバーを登録し終えたら、mongo
ドライバーをconfig/session.php
ファイルで使用できます。Once the session driver has been registered, we may use the mongo
driver in our config/session.php
configuration file.
Note: カスタムセッションハンドラーを書いたら、Packagistで他の開発者と共有できることを思い出してください。Note: Remember, if you write a custom session handler, share it on Packagist!
認証Authentication
キャッシュやセッション機能と同じ方法で、認証も拡張できます。既にお馴染みの、extend
メソッドを今回も使用します。Authentication may be extended the same way as the cache and session facilities. Again, we will use the extend
method we have become familiar with:
Auth::extend('riak', function($app)
{
// Return implementation of Illuminate\Contracts\Auth\UserProvider
});
UserProvider
の実装は、Illuminate\Contracts\Auth\Authenticatable
実装をMySQLやRiakなどの永続する保存システムから取得することだけに責任を持ちます。これらの2つのインターフェイスは、ユーザーデーターがどのように保存されているか、どのクラスがユーザーを表しているかにかかわらず、Laravel認証システムのメカニズムを機能させ続けてくれます。The UserProvider
implementations are only responsible for fetching a Illuminate\Contracts\Auth\Authenticatable
implementation out of a persistent storage system, such as MySQL, Riak, etc. These two interfaces allow the Laravel authentication mechanisms to continue functioning regardless of how the user data is stored or what type of class is used to represent it.
UserProvider
契約を見てみましょう。Let's take a look at the UserProvider
contract:
interface UserProvider {
public function retrieveById($identifier);
public function retrieveByToken($identifier, $token);
public function updateRememberToken(Authenticatable $user, $token);
public function retrieveByCredentials(array $credentials);
public function validateCredentials(Authenticatable $user, array $credentials);
}
retrieveById
関数は、典型的にはMySQLデータベースの自動増加IDのような、ユーザーを表す数字キーを受け付けます。IDに一致するAuthenticatable
の実装が取得され、メソッドにより返されます。The retrieveById
function typically receives a numeric key representing the user, such as an auto-incrementing ID from a MySQL database. The Authenticatable
implementation matching the ID should be retrieved and returned by the method.
retrieveByToken
関数は、一意の$identifier
と、remember_token
フィールドに保存されている"Remember me"トークンにより、ユーザーを取得します。前のメソッドと同様に、Authenticatable
の実装をリターンしなくてはなりません。The retrieveByToken
function retrieves a user by their unique $identifier
and "remember me" $token
, stored in a field remember_token
. As with with previous method, the Authenticatable
implementation should be returned.
updateRememberToken
メソッドは、$user
のremember_token
フィールドを新しい$token
で更新します。新しいトークンは"Remember me"によるログインが成功した時に生成される真新しいトークンでも良いですし、もしくはユーザーがログアウトした時はnullでもかまいません。The updateRememberToken
method updates the $user
field remember_token
with the new $token
. The new token can be either a fresh token, assigned on successfull "remember me" login attempt, or a null when user is logged out.
retrieveByCredentials
メソッドは、アプリケーションにログインするために、Auth::attempt
メソッドに渡された、ログイン情報の配列を受け取ります。メソッドはユーザー情報に一致するユーザーが、裏にある持続的なストレージに存在しているか「クエリー」する必要があります。典型的にメソッドは、"where"条件で$credentials['username']
のクエリーを実行することでしょう。このメソッドでパスワードのバリデーションや認証を試みてはいけません。The retrieveByCredentials
method receives the array of credentials passed to the Auth::attempt
method when attempting to sign into an application. The method should then "query" the underlying persistent storage for the user matching those credentials. Typically, this method will run a query with a "where" condition on $credentials['username']
. This method should not attempt to do any password validation or authentication.
validateCredentials
メソッドは指定された$user
とユーザーを認証するための$credentials
を比較する必要があります。例えば、このメソッドでは $user->getAuthPassword()
文字列と、Hash::make
した$credentials['password']
を比較する必要があるでしょう。The validateCredentials
method should compare the given $user
with the $credentials
to authenticate the user. For example, this method might compare the $user->getAuthPassword()
string to a Hash::make
of $credentials['password']
.
これでUserProvider
のメソッドをそれぞれ学習し終えました。今度は、Authenticatable
に注目していきましょう。プロバイダーはこのインターフェイスの実装をretrieveById
とretrieveByCredentials
メソッドから、返さなくてはならないことを覚えておいてください。Now that we have explored each of the methods on the UserProvider
, let's take a look at the Authenticatable
. Remember, the provider should return implementations of this interface from the retrieveById
and retrieveByCredentials
methods:
interface Authenticatable {
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}
このインターフェイスはシンプルです。getAuthIdentifier
メソッドは、そのユーザーの「主キー」を返さなくてはなりません。MySQLがバックエンドで使われているなら、ここでも自動増加主キーとなるでしょう。getAuthPassword
は、ユーザーのハッシュ済みのパスワードを返す必要があります。このインターフェイスにより、どんなORMやストレージの抽象クラスを使用してるのかに係わらず、認証システムをユーザークラスに対し動作させることを可能にしています。デフォルトでLaravelはこのインターフェイスを実装している、app
ディレクトリーの、User
クラスを含んでいます。ですから、実装のサンプルとして、このクラスを調べてみてください。This interface is simple. The getAuthIdentifier
method should return the "primary key" of the user. In a MySQL back-end, again, this would be the auto-incrementing primary key. The getAuthPassword
should return the user's hashed password. This interface allows the authentication system to work with any User class, regardless of what ORM or storage abstraction layer you are using. By default, Laravel includes a User
class in the app
directory which implements this interface, so you may consult this class for an implementation example.
ついに、UserProvider
を実装し、Auth
ファサードへ拡張を登録する準備が整いました。Finally, once we have implemented the UserProvider
, we are ready to register our extension with the Auth
facade:
Auth::extend('riak', function($app)
{
return new RiakUserProvider($app['riak.connection']);
});
ドライバーをextend
メソッドで登録したら、config/auth.php
設定ファイルでその新しいドライバーに切り替えましょう。After you have registered the driver with the extend
method, you switch to the new driver in your config/auth.php
configuration file.
IoCベースの拡張IoC Based Extension
Laravelフレームワークに含まれている、ほとんどすべてのサービスプロバイダーは、IoCコンテナでオブジェクトを結合しています。config/app.php
設定ファイルで、アプリケーションのサービスプロバイダーのリストを見つけられます。時間があれば、プロバイダーそれぞれのソースコードを拾い読みしてください。そうすれば、それぞれのプロバイダーがフレームワークに何を付け加えているのか、さらにIoCコンテナに数々のサービスを結合するため、どんなキーが使用されているか、もっと知ることができます。Almost every service provider included with the Laravel framework binds objects into the IoC container. You can find a list of your application's service providers in the config/app.php
configuration file. As you have time, you should skim through each of these provider's source code. By doing so, you will gain a much better understanding of what each provider adds to the framework, as well as what keys are used to bind various services into the IoC container.
例えば、HashServiceProvider
は、IoCコンテナでhash
キーと結合されており、Illuminate\Hashing\BcryptHasherインスタンスが依存解決されます。あなたは自分のアプリケーションの中でIoC結合をオーバーライドすることにより、簡単にクラスを拡張したり、オーバーライドしたりできます。例えば:For example, the HashServiceProvider
binds a hash
key into the IoC container, which resolves into a Illuminate\Hashing\BcryptHasher
instance. You can easily extend and override this class within your own application by overriding this IoC binding. For example:
<?php namespace App\Providers;
class SnappyHashProvider extends \Illuminate\Hashing\HashServiceProvider {
public function boot()
{
$this->app->bindShared('hash', function()
{
return new \Snappy\Hashing\ScryptHasher;
});
parent::boot();
}
}
このクラスはベースクラスのデフォルトServiceProvider
ではなく、 HashServiceProvider
を拡張していることに注意してください。サービスプロバイダーを拡張したら、config/app.php
設定ファイルの中の、HashServiceProvider
をあなたが拡張したプロバーダー名へ交換してください。Note that this class extends the HashServiceProvider
, not the default ServiceProvider
base class. Once you have extended the service provider, swap out the HashServiceProvider
in your config/app.php
configuration file with the name of your extended provider.
ここまでコンテナで結合されたコアクラスを拡張する、一般的な方法を見てきました。基本的に、コンテナ上の全てのコアクラスは、こうした方法で結合されており、オーバーライド可能です。繰りかえしますが、フレームワークに含まれているサービスプロバイダーを全般的に読んでみてください。様々なクラスに親しめますし、どのキーで結合されているか分かります。これは、Laravelがどのように一つにまとめられているのかを詳しく理解できる、素晴らしい方法です。This is the general method of extending any core class that is bound in the container. Essentially every core class is bound in the container in this fashion, and can be overridden. Again, reading through the included framework service providers will familiarize you with where various classes are bound into the container, and what keys they are bound by. This is a great way to learn more about how Laravel is put together.