Readouble

Laravel 5.7 ファサード

イントロダクションIntroduction

ファサード(facade、「入り口」)はアプリケーションのサービスコンテナに登録したクラスへ、「静的」なインターフェイスを提供します。Laravelのほとんどの機能に対して、ファサードが用意されています。Laravelの「ファサード」は、サービスコンテナ下で動作しているクラスに対し、"static proxy"として動作しています。これにより伝統的な静的メソッドよりもテストの行いやすさと柔軟性を保ちながらも、簡潔で記述的であるという利点があります。Facades provide a "static" interface to classes that are available in the application's service container[/docs/{{version}}/container]. Laravel ships with many facades which provide access to almost all of Laravel's features. Laravel facades serve as "static proxies" to underlying classes in the service container, providing the benefit of a terse, expressive syntax while maintaining more testability and flexibility than traditional static methods.

Laravelのファサードはすべて、Illuminate\Support\Facades名前空間下で定義されています。ですから、簡単にファサードへアクセスできます。All of Laravel's facades are defined in the Illuminate\Support\Facades namespace. So, we can easily access a facade like so:

use Illuminate\Support\Facades\Cache;

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

フレームワークの様々な機能をデモンストレートするために、Laravelのドキュメント全般でたくさんの例がファサードを使用しています。Throughout the Laravel documentation, many of the examples will use facades to demonstrate various features of the framework.

いつファサードを使うかWhen To Use Facades

ファサードにはたくさんの利点があります。自分で取り込んだり、設定したりする必要があり、長くて覚えにくいクラス名を使わずに、Laravelの機能を簡素で覚えやすい文法で使ってもらえます。その上に、PHPの動的メソッドのユニークな使用方法のおかげで、簡単にテストができます。Facades have many benefits. They provide a terse, memorable syntax that allows you to use Laravel's features without remembering long class names that must be injected or configured manually. Furthermore, because of their unique usage of PHP's dynamic methods, they are easy to test.

しかしながら、ファサードの使用にはいくつか気をつけるべき点も存在します。ファサードの一番の危険性は、クラスの責任範囲の暴走です。ファサードはとても簡単に使用でき、依存注入も必要ないため、簡単にクラスが成長し続ける結果、一つのクラスで多くのファサードが使われます。依存注入を使用すれば、クラスが大きくなりすぎることに伴う、大きなコンストラクタの視覚的なフィードバックにより、この危険性は抑制されます。ですから、ファサードを使用するときは、クラスの責任範囲を小さくとどめるため、クラスサイズに特に注意をはらいましょう。However, some care must be taken when using facades. The primary danger of facades is class scope creep. Since facades are so easy to use and do not require injection, it can be easy to let your classes continue to grow and use many facades in a single class. Using dependency injection, this potential is mitigated by the visual feedback a large constructor gives you that your class is growing too large. So, when using facades, pay special attention to the size of your class so that its scope of responsibility stays narrow.

lightbulb">Tip!! Laravelに関連した、サードパーティパッケージを構築する場合は、ファサードの代わりにLaravelの契約を使うほうが好ましいでしょう。Laravel自身の外でパッケージを構築するわけですから、Laravelのテストヘルパへアクセスする必要はありません。{tip} When building a third-party package that interacts with Laravel, it's better to inject Laravel contracts[/docs/{{version}}/contracts] instead of using facades. Since packages are built outside of Laravel itself, you will not have access to Laravel's facade testing helpers.

ファサード 対 依存注入Facades Vs. Dependency Injection

依存注入の最大の利便性は、注入するクラスの実装を入れ替えられるという機能です。モックやスタブを注入し、そうした代替オブジェクトの様々なメソッドのアサートが行えるため、テスト中に便利です。One of the primary benefits of dependency injection is the ability to swap implementations of the injected class. This is useful during testing since you can inject a mock or stub and assert that various methods were called on the stub.

本当の静的クラスメソッドをモックしたり、スタブにすることは、通常は不可能です。しかしファサードは、サービスコンテナが依存解決したオブジェクトの代替メソッドを呼び出すために、動的メソッドが使えますので、注入したクラスインスタンスをテストするのと同様に、ファサードを実際にテスト可能です。Typically, it would not be possible to mock or stub a truly static class method. However, since facades use dynamic methods to proxy method calls to objects resolved from the service container, we actually can test facades just as we would test an injected class instance. For example, given the following route:

use Illuminate\Support\Facades\Cache;

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

Cache::getメソッドが、予想した引数で呼び出されることを確認するために、以下のようなテストを書けます。We can write the following test to verify that the Cache::get method was called with the argument we expected:

use Illuminate\Support\Facades\Cache;

/**
 * 基本的なテスト機能の例
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $this->visit('/cache')
         ->see('value');
}

ファサード 対 ヘルパ関数Facades Vs. Helper Functions

ファサードに加え、Laravelは様々な「ヘルパ」関数を用意しており、ビューの生成、イベントの発行、ジョブの起動、HTTPレスポンスの送信など、一般的なタスクを実行できます。こうしたヘルパ関数の多くは、対応するファサードと同じ機能を実行します。たとえば、以下のファサードとヘルパの呼び出しは、同じ働きをします。In addition to facades, Laravel includes a variety of "helper" functions which can perform common tasks like generating views, firing events, dispatching jobs, or sending HTTP responses. Many of these helper functions perform the same function as a corresponding facade. For example, this facade call and helper call are equivalent:

return View::make('profile');

return view('profile');

ここではファサードとヘルパ関数との間に、全く違いはありません。ヘルパ関数を使う場合も、対応するファサードと全く同様にテストできます。たとえば、以下のルートが存在するとしましょう。There is absolutely no practical difference between facades and helper functions. When using helper functions, you may still test them exactly as you would the corresponding facade. For example, given the following route:

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

内部でcacheヘルパは、Cacheファサードの裏で動作しているクラスのgetメソッドを呼び出します。ですから、ヘルパ関数を使用していても、期待する引数でメソッドが呼びだされていることを確認する、以下のテストを書けます。Under the hood, the cache helper is going to call the get method on the class underlying the Cache facade. So, even though we are using the helper function, we can write the following test to verify that the method was called with the argument we expected:

use Illuminate\Support\Facades\Cache;

/**
 * 基本的なテスト機能の例
 *
 * @return void
 */
public function testBasicExample()
{
    Cache::shouldReceive('get')
         ->with('key')
         ->andReturn('value');

    $this->visit('/cache')
         ->see('value');
}

ファサードの仕組みHow Facades Work

Laravelアプリケーション中で、ファサードとは、コンテナを通じてオブジェクトにアクセス方法を提供するクラスのことです。Facadeクラス中の仕組みでこれを行なっています。Laravelのファサードと皆さんが作成するカスタムファサードは、Illuminate\Support\Facades\Facadeクラスを拡張します。In a Laravel application, a facade is a class that provides access to an object from the container. The machinery that makes this work is in the Facade class. Laravel's facades, and any custom facades you create, will extend the base Illuminate\Support\Facades\Facade class.

Facade基本クラスは、ファサードへの関数呼び出しをコンテナにより依存解決されたオブジェクトへ送るため、__callStatic()マジックメソッドを使用します。下の例では、Laravelのキャッシュシステムを呼び出しています。これを読むと一見、Cacheクラスのstaticなgetメソッドが呼び出されているのだと考えてしまうことでしょう。The Facade base class makes use of the __callStatic() magic-method to defer calls from your facade to an object resolved from the container. In the example below, a call is made to the Laravel cache system. By glancing at this code, one might assume that the static method get is being called on the Cache class:

<?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のキャッシュサービスの実装へ渡されます。Notice that near the top of the file we are "importing" the Cache facade. This facade serves as a proxy to accessing the underlying implementation of the Illuminate\Contracts\Cache\Factory interface. Any calls we make using the facade will be passed to the underlying instance of Laravel's cache service.

そのため、Illuminate\Support\Facades\Cacheクラスを見てもらえば、staticのgetメソッドは存在していないことが分かります。If we look at that Illuminate\Support\Facades\Cache class, you'll see that there is no static method get:

class Cache extends Facade
{
    /**
     * コンポーネントの登録名を取得
     *
     * @return string
     */
    protected static function getFacadeAccessor() { return 'cache'; }
}

かわりにCacheファサードは、Facadeベースクラスを拡張し、getFacadeAccessor()メソッドを定義しています。このメソッドの仕事は、サービスコンテナの結合名を返すことです。ユーザーがCacheファサードのどのstaticメソッドを利用しようと、Laravelはサービスコンテナからcacheに結び付けられたインスタンスを依存解決し、要求されたメソッドを(この場合はget)そのオブジェクトに対し実行します。Instead, the Cache facade extends the base Facade class and defines the method getFacadeAccessor(). This method's job is to return the name of a service container binding. When a user references any static method on the Cache facade, Laravel resolves the cache binding from the service container[/docs/{{version}}/container] and runs the requested method (in this case, get) against that object.

リアルタイムファサードReal-Time Facades

リアルタムファサードを使用すれば、アプリケーション中のどんなクラスでも、ファサードとして取り扱えます。活用法を示すために、新しいテストの手法を撮ってみましょう。例として、Podcastモデルがpublishメソッドを持っているとしましょう。しかしポッドキャストを公開(publish)するには、Publisherインスタンスを注入する必要があるとします。Using real-time facades, you may treat any class in your application as if it were a facade. To illustrate how this can be used, let's examine an alternative. For example, let's assume our Podcast model has a publish method. However, in order to publish the podcast, we need to inject a Publisher instance:

<?php

namespace App;

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

メソッドへPublisherの実装を注入することにより、注入するpublisherをモックできるため、メソッドを簡単にメソッドを他と切り離してテストできます。しかし、publishメソッドを呼び出すごとに、publisherインスタンスを常に渡す必要があります。リアルタイムファサードを使用すれば、同じてスタビリティを保ちながらも、明確にPublisherインスタンスを渡す必要がなくなります。リアルタイムファサードを作成するには、インポートするクラスのプレフィックスとして、Facade名前空間を付けます。Injecting a publisher implementation into the method allows us to easily test the method in isolation since we can mock the injected publisher. However, it requires us to always pass a publisher instance each time we call the publish method. Using real-time facades, we can maintain the same testability while not being required to explicitly pass a Publisher instance. To generate a real-time facade, prefix the namespace of the imported class with Facades:

<?php

namespace App;

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

リアルタイムファサードを使用しているため、インターフェイスやクラス名のFacadeプレフィックス後の部分を使い、サービスコンテナがpublisherの実装を依存注入解決します。テストのときは、このメソッドの呼び出しをモックするために、ファサードに組み込まれているLaravelのテストヘルパが使用できます。When the real-time facade is used, the publisher implementation will be resolved out of the service container using the portion of the interface or class name that appears after the Facades prefix. When testing, we can use Laravel's built-in facade testing helpers to mock this method call:

<?php

namespace Tests\Feature;

use App\Podcast;
use Tests\TestCase;
use Facades\App\Contracts\Publisher;
use Illuminate\Foundation\Testing\RefreshDatabase;

class PodcastTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A test example.
     *
     * @return void
     */
    public function test_podcast_can_be_published()
    {
        $podcast = factory(Podcast::class)->create();

        Publisher::shouldReceive('publish')->once()->with($podcast);

        $podcast->publish();
    }
}

ファサードクラス一覧Facade Class Reference

以下は全ファサードと実際のクラスの一覧です。これは特定のファサードを元にし、APIドキュメントを素早く探したい場合に便利な道具になります。対応するサービスコンテナ結合キーも記載しています。Below you will find every facade and its underlying class. This is a useful tool for quickly digging into the API documentation for a given facade root. The service container binding[/docs/{{version}}/container] key is also included where applicable.

ファサードFacade クラスClass サービスコンテナ結合Service Container Binding
AppApp Illuminate\Foundation\ApplicationIlluminate\Foundation\Application[https://laravel.com/api/{{version}}/Illuminate/Foundation/Application.html] appapp
ArtisanArtisan Illuminate\Contracts\Console\KernelIlluminate\Contracts\Console\Kernel[https://laravel.com/api/{{version}}/Illuminate/Contracts/Console/Kernel.html] artisanartisan
AuthAuth Illuminate\Auth\AuthManagerIlluminate\Auth\AuthManager[https://laravel.com/api/{{version}}/Illuminate/Auth/AuthManager.html] authauth
Auth (Instance)Auth (Instance) Illuminate\Contracts\Auth\GuardIlluminate\Contracts\Auth\Guard[https://laravel.com/api/{{version}}/Illuminate/Contracts/Auth/Guard.html] auth.driverauth.driver
BladeBlade Illuminate\View\Compilers\BladeCompilerIlluminate\View\Compilers\BladeCompiler[https://laravel.com/api/{{version}}/Illuminate/View/Compilers/BladeCompiler.html] blade.compilerblade.compiler
BroadcastBroadcast Illuminate\Contracts\Broadcasting\FactoryIlluminate\Contracts\Broadcasting\Factory[https://laravel.com/api/{{version}}/Illuminate/Contracts/Broadcasting/Factory.html]   
Broadcast (Instance)Broadcast (Instance) Illuminate\Contracts\Broadcasting\BroadcasterIlluminate\Contracts\Broadcasting\Broadcaster[https://laravel.com/api/{{version}}/Illuminate/Contracts/Broadcasting/Broadcaster.html]   
BusBus Illuminate\Contracts\Bus\DispatcherIlluminate\Contracts\Bus\Dispatcher[https://laravel.com/api/{{version}}/Illuminate/Contracts/Bus/Dispatcher.html]   
CacheCache Illuminate\Cache\CacheManagerIlluminate\Cache\CacheManager[https://laravel.com/api/{{version}}/Illuminate/Cache/CacheManager.html] cachecache
Cache (Instance)Cache (Instance) Illuminate\Cache\RepositoryIlluminate\Cache\Repository[https://laravel.com/api/{{version}}/Illuminate/Cache/Repository.html] cache.storecache.store
ConfigConfig Illuminate\Config\RepositoryIlluminate\Config\Repository[https://laravel.com/api/{{version}}/Illuminate/Config/Repository.html] configconfig
CookieCookie Illuminate\Cookie\CookieJarIlluminate\Cookie\CookieJar[https://laravel.com/api/{{version}}/Illuminate/Cookie/CookieJar.html] cookiecookie
CryptCrypt Illuminate\Encryption\EncrypterIlluminate\Encryption\Encrypter[https://laravel.com/api/{{version}}/Illuminate/Encryption/Encrypter.html] encrypterencrypter
DBDB Illuminate\Database\DatabaseManagerIlluminate\Database\DatabaseManager[https://laravel.com/api/{{version}}/Illuminate/Database/DatabaseManager.html] dbdb
DB (Instance)DB (Instance) Illuminate\Database\ConnectionIlluminate\Database\Connection[https://laravel.com/api/{{version}}/Illuminate/Database/Connection.html] db.connectiondb.connection
EventEvent Illuminate\Events\DispatcherIlluminate\Events\Dispatcher[https://laravel.com/api/{{version}}/Illuminate/Events/Dispatcher.html] eventsevents
FileFile Illuminate\Filesystem\FilesystemIlluminate\Filesystem\Filesystem[https://laravel.com/api/{{version}}/Illuminate/Filesystem/Filesystem.html] filesfiles
GateGate Illuminate\Contracts\Auth\Access\GateIlluminate\Contracts\Auth\Access\Gate[https://laravel.com/api/{{version}}/Illuminate/Contracts/Auth/Access/Gate.html]   
HashHash Illuminate\Contracts\Hashing\HasherIlluminate\Contracts\Hashing\Hasher[https://laravel.com/api/{{version}}/Illuminate/Contracts/Hashing/Hasher.html] hashhash
LangLang Illuminate\Translation\TranslatorIlluminate\Translation\Translator[https://laravel.com/api/{{version}}/Illuminate/Translation/Translator.html] translatortranslator
LogLog Illuminate\Log\LogManagerIlluminate\Log\LogManager[https://laravel.com/api/{{version}}/Illuminate/Log/LogManager.html] loglog
MailMail Illuminate\Mail\MailerIlluminate\Mail\Mailer[https://laravel.com/api/{{version}}/Illuminate/Mail/Mailer.html] mailermailer
NotificationNotification Illuminate\Notifications\ChannelManagerIlluminate\Notifications\ChannelManager[https://laravel.com/api/{{version}}/Illuminate/Notifications/ChannelManager.html]   
PasswordPassword Illuminate\Auth\Passwords\PasswordBrokerManagerIlluminate\Auth\Passwords\PasswordBrokerManager[https://laravel.com/api/{{version}}/Illuminate/Auth/Passwords/PasswordBrokerManager.html] auth.passwordauth.password
Password (Instance)Password (Instance) Illuminate\Auth\Passwords\PasswordBrokerIlluminate\Auth\Passwords\PasswordBroker[https://laravel.com/api/{{version}}/Illuminate/Auth/Passwords/PasswordBroker.html] auth.password.brokerauth.password.broker
QueueQueue Illuminate\Queue\QueueManagerIlluminate\Queue\QueueManager[https://laravel.com/api/{{version}}/Illuminate/Queue/QueueManager.html] queuequeue
Queue (Instance)Queue (Instance) Illuminate\Contracts\Queue\QueueIlluminate\Contracts\Queue\Queue[https://laravel.com/api/{{version}}/Illuminate/Contracts/Queue/Queue.html] queue.connectionqueue.connection
Queue (Base Class)Queue (Base Class) Illuminate\Queue\QueueIlluminate\Queue\Queue[https://laravel.com/api/{{version}}/Illuminate/Queue/Queue.html]   
RedirectRedirect Illuminate\Routing\RedirectorIlluminate\Routing\Redirector[https://laravel.com/api/{{version}}/Illuminate/Routing/Redirector.html] redirectredirect
RedisRedis Illuminate\Redis\RedisManagerIlluminate\Redis\RedisManager[https://laravel.com/api/{{version}}/Illuminate/Redis/RedisManager.html] redisredis
Redis (Instance)Redis (Instance) Illuminate\Redis\Connections\ConnectionIlluminate\Redis\Connections\Connection[https://laravel.com/api/{{version}}/Illuminate/Redis/Connections/Connection.html] redis.connectionredis.connection
RequestRequest Illuminate\Http\RequestIlluminate\Http\Request[https://laravel.com/api/{{version}}/Illuminate/Http/Request.html] requestrequest
ResponseResponse Illuminate\Contracts\Routing\ResponseFactoryIlluminate\Contracts\Routing\ResponseFactory[https://laravel.com/api/{{version}}/Illuminate/Contracts/Routing/ResponseFactory.html]   
Response (Instance)Response (Instance) Illuminate\Http\ResponseIlluminate\Http\Response[https://laravel.com/api/{{version}}/Illuminate/Http/Response.html]   
RouteRoute Illuminate\Routing\RouterIlluminate\Routing\Router[https://laravel.com/api/{{version}}/Illuminate/Routing/Router.html] routerrouter
SchemaSchema Illuminate\Database\Schema\BuilderIlluminate\Database\Schema\Builder[https://laravel.com/api/{{version}}/Illuminate/Database/Schema/Builder.html]   
SessionSession Illuminate\Session\SessionManagerIlluminate\Session\SessionManager[https://laravel.com/api/{{version}}/Illuminate/Session/SessionManager.html] sessionsession
Session (Instance)Session (Instance) Illuminate\Session\StoreIlluminate\Session\Store[https://laravel.com/api/{{version}}/Illuminate/Session/Store.html] session.storesession.store
StorageStorage Illuminate\Filesystem\FilesystemManagerIlluminate\Filesystem\FilesystemManager[https://laravel.com/api/{{version}}/Illuminate/Filesystem/FilesystemManager.html] filesystemfilesystem
Storage (Instance)Storage (Instance) Illuminate\Contracts\Filesystem\FilesystemIlluminate\Contracts\Filesystem\Filesystem[https://laravel.com/api/{{version}}/Illuminate/Contracts/Filesystem/Filesystem.html] filesystem.diskfilesystem.disk
URLURL Illuminate\Routing\UrlGeneratorIlluminate\Routing\UrlGenerator[https://laravel.com/api/{{version}}/Illuminate/Routing/UrlGenerator.html] urlurl
ValidatorValidator Illuminate\Validation\FactoryIlluminate\Validation\Factory[https://laravel.com/api/{{version}}/Illuminate/Validation/Factory.html] validatorvalidator
Validator (Instance)Validator (Instance) Illuminate\Validation\ValidatorIlluminate\Validation\Validator[https://laravel.com/api/{{version}}/Illuminate/Validation/Validator.html]   
ViewView Illuminate\View\FactoryIlluminate\View\Factory[https://laravel.com/api/{{version}}/Illuminate/View/Factory.html] viewview
View (Instance)View (Instance) Illuminate\View\ViewIlluminate\View\View[https://laravel.com/api/{{version}}/Illuminate/View/View.html]   

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
OS表示
全OS表示
macOSのみ表示
windowsのみ表示
linuxのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作