はじめに
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つは、注入されたクラスの実装を入れ替える能力です。これはテスト中に便利で、モックやスタブを注入し、さまざまなメソッドがスタブで呼び出されたことを確認できます。
通常、真の静的クラスメソッドをモックまたはスタブすることは不可能です。しかし、ファサードは動的メソッドを使用してサービスコンテナから解決されたオブジェクトへのメソッド呼び出しをプロキシするため、実際にはファサードを注入されたクラスインスタンスと同様にテストできます。たとえば、次のルートがあるとします:
use Illuminate\Support\Facades\Cache;
Route::get('/cache', function () {
return Cache::get('key');
});
Laravelのファサードテストメソッドを使用して、Cache::get
メソッドが期待した引数で呼び出されたことを確認するために、次のテストを書くことができます:
use Illuminate\Support\Facades\Cache;
test('basic example', function () {
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$response = $this->get('/cache');
$response->assertSee('value');
});
use Illuminate\Support\Facades\Cache;
/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
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');
});
``````php
use Illuminate\Support\Facades\Cache;
/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
Cache::shouldReceive('get')
->with('key')
->andReturn('value');
$response = $this->get('/cache');
$response->assertSee('value');
}
`
ファサードの仕組み
Laravelアプリケーションにおいて、ファサードはコンテナからオブジェクトへのアクセスを提供するクラスです。この仕組みを実現するための機構はFacade
クラスにあります。Laravelのファサードと、あなたが作成するカスタムファサードは、基本のIlluminate\Support\Facades\Facade
クラスを拡張します。
``````php
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*/
public function showProfile(string $id): View
{
$user = Cache::get('user:'.$id);
return view('profile', ['user' => $user]);
}
}
`
ファイルの上部近くで、Cache
ファサードを「インポート」していることに注意してください。このファサードは、Illuminate\Contracts\Cache\Factory
インターフェースの基盤となる実装にアクセスするためのプロキシとして機能します。ファサードを使用して行うすべての呼び出しは、Laravelのキャッシュサービスの基盤となるインスタンスに渡されます。
``````php
class Cache extends Facade
{
/**
* Get the registered name of the component.
*/
protected static function getFacadeAccessor(): string
{
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
{
/**
* Publish the podcast.
*/
public function publish(Publisher $publisher): void
{
$this->update(['publishing' => now()]);
$publisher->publish($this);
}
}
メソッドにパブリッシャーの実装を注入することで、注入されたパブリッシャーをモックできるため、メソッドを孤立して簡単にテストできます。ただし、publish
メソッドを呼び出すたびに、常にパブリッシャーインスタンスを渡す必要があります。リアルタイムファサードを使用すると、Publisher
インスタンスを明示的に渡す必要がなく、同じテスト可能性を維持できます。リアルタイムファサードを生成するには、インポートされたクラスの名前空間をFacades
でプレフィックスします:
<?php
namespace App\Models;
use App\Contracts\Publisher;
use Facades\App\Contracts\Publisher;
use Illuminate\Database\Eloquent\Model;
class Podcast extends Model
{
/**
* Publish the podcast.
*/
public function publish(Publisher $publisher): void
public function publish(): void
{
$this->update(['publishing' => now()]);
$publisher->publish($this);
Publisher::publish($this);
}
}
リアルタイムファサードが使用されると、パブリッシャーの実装は、Facades
プレフィックスの後に表示されるインターフェースまたはクラス名の部分を使用してサービスコンテナから解決されます。テスト中は、Laravelの組み込みファサードテストヘルパーを使用してこのメソッド呼び出しをモックできます:
<?php
use App\Models\Podcast;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('podcast can be published', function () {
$podcast = Podcast::factory()->create();
Publisher::shouldReceive('publish')->once()->with($podcast);
$podcast->publish();
});
<?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;
/**
* A test example.
*/
public function test_podcast_can_be_published(): void
{
$podcast = Podcast::factory()->create();
Publisher::shouldReceive('publish')->once()->with($podcast);
$podcast->publish();
}
}
ファサードクラスリファレンス
以下に、すべてのファサードとその基盤となるクラスを示します。これは、特定のファサードルートのAPIドキュメントを迅速に掘り下げるための便利なツールです。該当する場合は、サービスコンテナバインディングキーも含まれています。