イントロダクション
Laravelのドキュメント全体を通して、「ファサード」を介してLaravelの機能を操作するコード例を紹介しています。ファサードは、アプリケーションのサービスコンテナで使用可能なクラスに対して「静的な」インターフェイスを提供します。Laravelは、Laravelのほとんどすべての機能へのアクセスを提供する多くのファサードを提供しています。
Laravelファサードは、サービスコンテナ内の基礎となるクラスへの「静的プロキシ」として機能し、従来の静的メソッドよりもテスト容易性と柔軟性を維持しながら、簡潔で表現力豊かな構文という利点を提供しています。ファサードがどのように機能するかを完全に理解していなくても、まったく問題ありません。流れに沿って、Laravelについて学び続けてください。
Laravelのファサードはすべて、Illuminate\Support\Facades
名前空間で定義します。したがって、次のようなファサードに簡単にアクセスできます。
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;
Route::get('/cache', function () {
return Cache::get('key');
});
Laravelのドキュメント全体を通じ、コード例の多くでファサードを使用して、フレームワークのさまざまな機能を紹介しています。
ヘルパ関数
ファサードを補完するため、Laravelはさまざまなグローバルな「ヘルパ機能」を提供し、Laravel機能の一般的な操作をより簡単にしています。使用する可能性のある一般的なヘルパ関数には、view
、response
、url
、config
などがあります。Laravelが提供する各ヘルパ機能は、対応する機能とともにドキュメント化しています。関数の完全なリストは、専用のヘルパドキュメント内にあります。
たとえば、Illuminate\Support\Facades\Response
ファサードを使用してJSONレスポンスを生成する代わりに、単にresponse
関数を使用することもできます。ヘルパ関数はグローバルに利用できるため、使用するためにクラスをインポートする必要はありません。
use Illuminate\Support\Facades\Response;
Route::get('/users', function () {
return Response::json([
// ...
]);
});
Route::get('/users', function () {
return response()->json([
// ...
]);
});
いつファサードを使うか
ファサードには多くの利点があります。これらは、手作業で挿入または設定する必要のある長いクラス名を覚えていなくても、Laravelの機能を使用できるようにする簡潔で覚えやすい構文を提供しています。さらに、PHPの動的メソッドを独自に使用しているため、テストが簡単です。
ただし、ファサードを使用する場合は注意が必要です。ファサードの主な危険性は、クラスの「スコープクリープ」です。ファサードは非常に使いやすく、依存注入を必要としないため、1つのクラスで多くのファサードを使用するのは簡単で、クラスを成長させ続けてしまいがちです。依存注入を使用していれば、大きなコンストラクタによりクラスが大きくなりすぎていることを示す視覚的なフィードバックにより、これが起きる可能性は低減されます。したがって、ファサードを使用するときは、クラスのサイズに特に注意して、クラスの責任範囲が狭くなるようにしてください。クラスが大きくなりすぎている場合は、クラスを複数の小さなクラスに分割することを検討してください。
ファサード対依存注入
依存注入の主な利点の1つは、注入するクラスの実装を交換できることです。これは、モックまたはスタブを挿入して、さまざまなメソッドがスタブで呼び出されたことを表明できるため、テスト中に役立ちます。
通常、真に静的なクラスメソッドをモックまたはスタブすることはできません。ただし、ファサードは動的メソッドを使用して、サービスコンテナが解決するオブジェクトへのメソッド呼び出しをプロキシするため、挿入するクラスインスタンスをテストするのと同様に、実際にはファサードをテストできます。たとえば、次のルートがあるとします。
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () {
return Cache::get('key');
});
Laravelのファサードテストメソッドを使用して、次のテストを記述し、期待する引数でCache::get
メソッドを呼び出すことを確認できます。
use Illuminate\Support\Facades\Cache;
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$response = $this->get('/cache');
$response->assertSee('value');
}
ファサード対ヘルパ関数
Laravelには、ファサードに加えて、ビューの生成、イベントの発生、ジョブのディスパッチ、HTTP応答の送信などの一般的なタスクを実行できるさまざまな「ヘルパ」関数が含まれています。これらのヘルパ関数の多くは、対応するファサードと同じ機能を実行します。たとえば、このファサード呼び出しとヘルパ呼び出しは同等です。
return Illuminate\Support\Facades\View::make('profile');
return view('profile');
ファサードとヘルパ機能の間に実際的な違いはまったくありません。ヘルパ関数を使用する場合でも、対応するファサードとまったく同じようにテストできます。たとえば、次のルートがあるとします。
Route::get('/cache', function () {
return cache('key');
});
cache
ヘルパはCache
ファサードの基礎となるクラスでget
メソッドを呼び出します。したがって、ヘルパ関数を使用している場合でも、次のテストを記述して、期待した引数でメソッドが呼び出されたことを確認できます。
use Illuminate\Support\Facades\Cache;
/**
* 基本的な機能テストの例
*
* @return void
*/
public function testBasicExample()
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$response = $this->get('/cache');
$response->assertSee('value');
}
ファサードの仕組み
Laravelアプリケーションのファサードは、コンテナからのオブジェクトに対するアクセスを提供するクラスです。この作業を行うメカニズムは、Facade
クラスにあります。Laravelのファサード、および作成したカスタムファサードは、基本のIlluminate\Support\Facades\Facade
クラスを拡張します。
Facade
基本クラスは__callStatic()
マジックメソッドを利用して、ファサードへの呼び出しをコンテナが解決するオブジェクトへの呼び出しへと延期します。下の例では、Laravelキャッシュシステムが呼び出されます。このコードを一瞥すると、静的なget
メソッドがCache
クラスで呼び出されていると思われるかもしれません。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* 特定のユーザーのプロファイルを表示
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
$user = Cache::get('user:'.$id);
return view('profile', ['user' => $user]);
}
}
ファイルの上部近くで、Cache
ファサードを「インポート」していることに注意してください。このファサードは、Illuminate\Contracts\Cache\Factory
インターフェイスの基盤となる実装にアクセスするためのプロキシとして機能します。ファサードを使用して行う呼び出しはすべて、Laravelのキャッシュサービスの基盤となるインスタンスに渡されます。
そのIlluminate\Support\Facades\Cache
クラスを見ると、静的メソッドget
がないことがわかります。
class Cache extends Facade
{
/**
* コンポーネントの登録名を取得
*
* @return string
*/
protected static function getFacadeAccessor() { return 'cache'; }
}
代わりに、Cache
ファサードは基本のFacade
クラスを拡張し、メソッドgetFacadeAccessor()
を定義します。このメソッドの仕事は、サービスコンテナ結合名を返すことです。ユーザーがCache
ファサードの静的メソッドを参照すると、Laravelはサービスコンテナでcache
結合を依存解決し、リクエストされたメソッド(この場合はget
)をそのオブジェクトに対して実行します。
リアルタイムファサード
リアルタイムファサードを使用すると、アプリケーション内の任意のクラスをファサードであるかのように扱うことができます。これをどのように使用できるかを説明するために、最初にリアルタイムファサードを使用しないコードを調べてみましょう。たとえば、Podcast
モデルにpublish
メソッドがあるとしましょう。ただし、ポッドキャストを公開するには、Publisher
インスタンスを挿入する必要があります。
<?php
namespace App\Models;
use App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;
class Podcast extends Model
{
/**
* ポッドキャストを公開
*
* @param Publisher $publisher
* @return void
*/
public function publish(Publisher $publisher)
{
$this->update(['publishing' => now()]);
$publisher->publish($this);
}
}
パブリッシャーの実装をメソッドに注入すると、注入されたパブリッシャーをモックできるため、メソッドを分離して簡単にテストできます。ただし、publish
メソッドを呼び出すたびに、常にパブリッシャーインスタンスを渡す必要があります。リアルタイムのファサードを使用すると、Publisher
インスタンスを明示的に渡す必要がなく、同じテスト容易性を維持できます。リアルタイムのファサードを生成するには、インポートするクラスの名前空間の前にFacades
を付けます。
<?php
namespace App\Models;
use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;
class Podcast extends Model
{
/**
* ポッドキャストを公開
*
* @return void
*/
public function publish()
{
$this->update(['publishing' => now()]);
Publisher::publish($this);
}
}
リアルタイムファサードを使用する場合、パブリッシャーの実装はFacades
プレフィックスの後に表示されるインターフェイスまたはクラス名の部分を使用してサービスコンテナが依存解決します。テスト時には、Laravelの組み込みファサードテストヘルパを使用して、このメソッド呼び出しをモックできます。
<?php
namespace Tests\Feature;
use App\Models\Podcast;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PodcastTest extends TestCase
{
use RefreshDatabase;
/**
* テスト例
*
* @return void
*/
public function test_podcast_can_be_published()
{
$podcast = Podcast::factory()->create();
Publisher::shouldReceive('publish')->once()->with($podcast);
$podcast->publish();
}
}
ファサードクラスリファレンス
以下に、すべてのファサードとその基礎となるクラスを示します。これは、特定のファサードルートのAPIドキュメントをすばやく掘り下げるための便利なツールです。該当するサービスコンテナ結合キーがある場合は内容に含めています。