Lang x Lang

Facades

Table of Contents

Introduction

Laravel のドキュメンテーション全体を通じて、Laravel の機能とやり取りする"facades"を介したコードの例を見ることができます。"facades"は、application のservice containerで利用可能な classes への"静的"なインターフェースを提供します。Laravel は、Laravel のほとんどすべての機能にアクセスを提供する多くの"facades"と共に提供されています。

Laravel facades は、"static proxies"として機能し、 service container 内の基礎となるクラスに対する短く、表現豊かな syntax の利点を提供しつつ、伝統的な静的メソッドよりも高いテスト可能性と柔軟性を維持します。 facades の動作を完全に理解していなくても問題ありません - 流れに身を任せて Laravel について学習を続けてください。

Laravel の全ての facades は、Illuminate\Support\Facades名前空間で定義されています。そのため、以下のように簡単に facade にアクセスすることができます:

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;

Route::get('/cache', function () {
    return Cache::get('key');
});

Laravel のドキュメンテーション全体で、多くの例が facades を使用してフレームワークのさまざまな features を示しています。

ヘルパー関数

facades を補完するために、 Laravel は多種多様なグローバル "ヘルパー関数"を提供しており、これにより一般的な Laravel features とより簡単にやり取りすることが可能になります。ご利用になる可能性がある一般的なヘルパー関数には、viewresponseurlconfigなどがあります。各 Laravel が提供するヘルパー関数は、それぞれの機能とともに文書化されていますが、完全なリストは専用のヘルパードキュメンテーション内でご覧いただけます。

たとえば、Illuminate\Support\Facades\Response facade を使って JSON response を生成する代わりに、単純にresponse関数を使用することができます。ヘルパ関数はグローバルで利用可能なので、それらを使用するために classes をインポートする必要はありません:

use Illuminate\Support\Facades\Response;

Route::get('/users', function () {
    return Response::json([
        // ...
    ]);
});

Route::get('/users', function () {
    return response()->json([
        // ...
    ]);
});

When to Utilize Facades

Facades には多くの利点があります。それらは、手短で覚えやすい syntax を提供し、Laravel の features を長い class 名を記憶したり、手動で注入したり設定したりすることなく使用することを可能にします。さらに、PHP の動的メソッドを unique に使用することで、テストが容易になります。

しかし、facades を使用する際には一定の注意が必要です。facades の primary な危険性は、class の scope creep です。facades は使用が非常に容易で、注入を必要としないため、class を増やし続けたり、single class で多くの facades を使用することが容易になります。dependency injection を使用すると、大きなコンストラクタがあなたに class が大きくなりすぎていることを視覚的にフィードバックしてくれるため、この可能性は緩和されます。したがって、facades を使用する際には、class のサイズに特に注意を払い、その scope の範囲が狭く保たれるようにしてください。もし class が大きすぎると感じたら、それを複数の小さな class に分割することを検討してください。

Facades 対 Dependency Injection

dependency injection の primary な利点の一つは、注入された class の実装を swap する能力です。これは testing 中に便利で、モックやスタブを注入して、スタブ上でさまざまなメソッドが assert されたことを確認できます。

通常、本当に静的な class method をモックまたはスタブにすることはできません。しかし、 facades が service container から解決されたオブジェクトに method 呼び出しをプロキシするための動的なメソッドを使用するため、私たちは facades を注入された class インスタンスをテストするのと同じようにテストできます。例えば、以下の route が与えられた場合:

use Illuminate\Support\Facades\Cache;

Route::get('/cache', function () {
    return Cache::get('key');
});

Laravel の facade testing メソッドを使って、私たちは以下のテストを書くことで、Cache::get method が我々が期待する引数で呼ばれたかどうかを確認することができます:

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');
}

Facades 対 ヘルパー関数

facades に加えて、" Laravel "には、 views の生成、 events の発火、 jobs のディスパッチ、または HTTP responses の送信など、一般的なタスクを実行できる「ヘルパー」関数が多数含まれています。これらのヘルパー関数の多くは、対応する facade と同じ機能を果たします。例えば、この" facade "コールとヘルパーコールは同等です:

return Illuminate\Support\Facades\View::make('profile');

return view('profile');

facade とヘルパー関数の間には全く実質的な違いはありません。ヘルパー関数を使用する場合でも、それに対応する facades と全く同じようにテストできます。たとえば、次の route をご覧ください:

Route::get('/cache', function () {
    return cache('key');
});

Cachehelper は、cache facade の基礎となる class で get method を呼び出す予定です。したがって、helper 関数を使用していても、期待した引数で method が呼び出されたことを確認するための次の test を書くことができます:

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');
}

How Facades Work

Laravel application において、 facade は、コンテナから object へのアクセスを提供する class です。これを可能にする仕組みは、Facade class にあります。Laravel の facades および作成する custom facades は、基底のIlluminate\Support\Facades\Facade class を拡張します。

Facadeベースの class では、__callStatic()マジックメソッドを使って、あなたの facade からコンテナから解決された object への呼び出しを遅延させます。以下の例では、Laravel cache システムへの呼び出しが行われています。このコードを一見すると、静的なget method がCache class 上で呼び出されていると思うかもしれません:

<?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 facade を "インポート" していることに注意してください。この facade は、 Illuminate\Contracts\Cache\Factory インターフェースの基本実装へのアクセスを代理する役割を果たします。 facade を使って行うどんな呼び出しも、Laravel の cache service の基本インスタンスに渡されます。

そのIlluminate\Support\Facades\Cache class を見てみると、getという静的な method が存在しないことがわかります。

class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     */
    protected static function getFacadeAccessor(): string
    {
        return 'cache';
    }
}

それどころか、Cache facade は基本的なFacade class を拡張し、 job getFacadeAccessor()を定義します。この method の仕事は、 service container のバインディングの名前を返すことです。 user がCache facade の任意の静的 method を参照するとき、 Laravel は“ service containerからcacheバインディングを解決し、要求された method (この場合はget)をその object に対して実行します。

Real-Time Facades

リアルタイムの facades を使用すると、 application 内の任意の class をまるで facade であるかのように扱うことができます。これがどのように使用されるかを説明するために、まずはリアルタイムの facades を使用しない何らかの code を見てみましょう。例えば、私たちの Podcast model が publish method を持っていると仮定しましょう。しかし、ポッドキャストを 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);
    }
}

method にパブリッシャー実装を注入することで、注入されたパブリッシャーをモックすることができ、method を単独で簡単にテストすることができます。しかし、publishメソッドを呼び出すたびにパブリッシャーインスタンスを常に渡す必要があります。リアルタイム facades を使用すると、同じテストの容易さを保ちながら、Publisher インスタンスを明示的に渡す必要がなくなります。リアルタイム facade を生成するには、インポートされた class の名前空間に Facades をプレフィックスとして追加します。

<?php

namespace App\Models;

use App\Contracts\Publisher; // [tl! remove]
use Facades\App\Contracts\Publisher; // [tl! add]
use Illuminate\Database\Eloquent\Model;

class Podcast extends Model
{
    /**
     * Publish the podcast.
     */
    public function publish(Publisher $publisher): void // [tl! remove]
    public function publish(): void // [tl! add]
    {
        $this->update(['publishing' => now()]);

        $publisher->publish($this); // [tl! remove]
        Publisher::publish($this); // [tl! add]
    }
}

リアルタイムの facade を使用すると、publisher の実装はインターフェースの一部または class 名を用いて、Facadesプレフィックスの後に現れる service container から解決されます。 testing を行う際には、Laravel の組み込みの facade testing helpers を使ってこの method 呼び出しをモックできます。

<?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();
    }
}

Facade Class Reference

以下に、すべての facade とその下にある class を見つけることができます。これは特定の facade root のための API ドキュメンテーションを素早く探るのに役立つツールです。該当する場合には、service container bindingキーも含まれています。

FacadeClassService Container バインディング
AppIlluminate\Foundation\Application app
ArtisanIlluminate\Contracts\Console\Kernel artisan
AuthIlluminate\Auth\AuthManager auth
Auth (インスタンス)Illuminate\Contracts\Auth\Guard auth.driver
BladeIlluminate\View\Compilers\BladeCompiler blade.compiler
BroadcastIlluminate\Contracts\Broadcasting\Factory  
Broadcast (インスタンス)Illuminate\Contracts\Broadcasting\Broadcaster  
バスIlluminate\Contracts\Bus\Dispatcher  
CacheIlluminate\Cache\CacheManager cache
Cache (インスタンス)Illuminate\Cache\Repository cache.store
ConfigIlluminate\Config\Repository config
CookieIlluminate\Cookie\CookieJar cookie
CryptIlluminate\Encryption\Encrypter encrypter
日付Illuminate\Support\DateFactory date
DBIlluminate\Database\DatabaseManager db
DB(インスタンス)Illuminate\Database\Connection db.connection
EventIlluminate\Events\Dispatcher events
ExceptionsIlluminate\Foundation\Exceptions\Handler  
Exceptions (インスタンス)Illuminate\Contracts\Debug\ExceptionHandler  
ファイルIlluminate\Filesystem\Filesystem files
GateIlluminate\Contracts\Auth\Access\Gate  
HashIlluminate\Contracts\Hashing\Hasher hash
HttpIlluminate\Http\Client\Factory  
LangIlluminate\Translation\Translator translator
LogIlluminate\Log\LogManager log
MailIlluminate\Mail\Mailer mailer
NotificationIlluminate\Notifications\ChannelManager  
PasswordIlluminate\Auth\Passwords\PasswordBrokerManager auth.password
Password (インスタンス)Illuminate\Auth\Passwords\PasswordBroker auth.password.broker
Pipeline (インスタンス)Illuminate\Pipeline\Pipeline  
ProcessIlluminate\Process\Factory  
QueueIlluminate\Queue\QueueManager queue
Queue (インスタンス)Illuminate\Contracts\Queue\Queue queue.connection
Queue (基本 Class)Illuminate\Queue\Queue  
RateLimiterIlluminate\Cache\RateLimiter  
RedirectIlluminate\Routing\Redirector redirect
RedisIlluminate\Redis\RedisManager redis
Redis (インスタンス)Illuminate\Redis\Connections\Connection redis.connection
RequestIlluminate\Http\Request request
ResponseIlluminate\Contracts\Routing\ResponseFactory  
Response (インスタンス)Illuminate\Http\Response  
RouteIlluminate\Routing\Router router
ScheduleIlluminate\Console\Scheduling\Schedule  
SchemaIlluminate\Database\Schema\Builder  
SessionIlluminate\Session\SessionManager session
Session (インスタンス)Illuminate\Session\Store session.store
StorageIlluminate\Filesystem\FilesystemManager filesystem
Storage (インスタンス)Illuminate\Contracts\Filesystem\Filesystem filesystem.disk
URLIlluminate\Routing\URLGenerator url
ValidatorIlluminate\Validation\Factory validator
Validator (インスタンス)Illuminate\Validation\Validator  
ViewIlluminate\View\Factory view
View (インスタンス)Illuminate\View\View  
ViteIlluminate\Foundation\Vite  

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use