Laravel

【Laravel】ファーサードとは

こんにちは!ともです(@_tomo_engineer)!

今回はLaravelの強力な機能の1つファサード(Facade)についてです。

ファサードなんて言葉初めて聞いた。難しそう!

ってなったんですが調べてみる、とても強力なLaravelの機能です。

是非Laravelを利用する上でマスターしたい機能の1つです!

今回はCSV出力機能をファサードに登録するという例を見ながら解説を行いたいと思います。

結論から先に書くと、

  • Facadeはサービスプロバイダーに登録されたサービスコンテナを引き出す窓口である
  • Facadeを利用する事で、機能をまとめ、コントローラの肥大化を抑える

今回のFacadeの解説は、Facadeの利用方法についての説明であり

Laravel内でのFacadeの仕組みを解説したものではありません。

目次

  • Facadeを理解する為に
  • Facadeとは
  • サービスプロバイダーとは
  • Facadeの作成
  • Facadeのメリット

Facadeを理解する為に

私はFacadeを理解するにあたり3つの良記事に出会いました。

Qiita:Laravelのファサードが全然わからなかったので自分なりに調べた事

ララ帳:ファサードとは

Qiita:LaravelでCSVダウンロード

1番目の記事で概念を学び、2・3の記事を見ながら手を動かしたという流れになります。

CSV出力について調べていた所、3番目の記事に出会いました。

Facadeの作成練習にピッタリだと思います。

Facadeとは

上記の2番目の記事によると、Facadeとは建物の正面という意味があるそうです。

またドキュメントには以下の用に書かれています。

ファサード(facade、「入り口」)はアプリケーションのサービスコンテナに登録したクラスへ、「静的」なインターフェイスを提供します。Laravelのほとんどの機能に対して、ファサードが用意されています。Laravelの「ファサード」は、サービスコンテナ下で動作しているクラスに対し、”static proxy”として動作しています。これにより伝統的な静的メソッドよりもテストの行いやすさと柔軟性を保ちながらも、簡潔で記述的であるという利点があります。

分かる様でわからないな・・・

自分なりに図解すると、この様なイメージです。

図解しましたが、サービスプロバイダーとサービスコンテナがわからないとイメージが湧きませんね。

ただ、開発者がCSVの機能を使いたいと思った時、CSVの機能を担うサービスコンテナ(クラス)にアクセスする為に、ファサードとサービスプロバイダを経由している事が分かります。

使いたい機能を利用する為に、ファサードが入り口となっているイメージが着くのでは無いでしょうか?

しかし、こんな疑問も湧きました。

わざわざファサードやらサービスプロバイダーを経由してクラスにアクセスする必要あるのか?

この疑問を解消する為に、サービスプロバイダーを少し知る必要があります。

サービスプロバイダーとは

はじめに申し上げると、僕はサービスプロバイダーは正確にまだ把握できていません

ただイメージを掴むことはできました。

ドキュメントには次の様に書かれています。

サービスプロバイダは、Laravelアプリケーション全体の起動処理における、初めの心臓部です。皆さんのアプリケーションと同じく、Laravelのコアサービス全部もサービスプロバイダを利用し、初期起動処理を行っています。

ところで「初期起動処理」とは何を意味しているのでしょうか? サービスコンテナの結合や、イベントリスナ、フィルター、それにルートなどを登録することを一般的に意味しています。サービスプロバイダはアプリケーション設定の中心部です。

アプリケーションの心臓部で、初期起動処理を担っているそうですね。

サービスプロバイダについては以下のブログ記事で理解が少し深まりました。

新人Webエンジニアの記録:LaravelのDIコンテナはどう使われているのか

ララ帳:ファサードとは

サービスプロバイダで依存注入を行う事ができ、パフォーマンス向上に繋がると書かれています。

サービスコンテナにその他のクラスが依存している場合、サービスプロバイダで依存注入してやる必要があるのでしょう。

よってFacade・サービスプロバイダを介してサービスコンテナにアクセスしているのだと考えられます。

また理解が深まればブログに書きたいと思います。

Facadeの作成

今までの説明でFacadeがサービコンテナの起動の窓口になっている事が分かりましたので、ファサードを作成していきます。

この図解にもありますが、ファサードの作成には3つのステップが必要です。

  1. サービスコンテナの作成
  2. サービスプロバイダの作成
  3. ファサードの作成
  4. パスを通す

以降はQiitaの記事の引用ですので、Qiita:LaravelでCSVダウンロードをご覧ください。

サービスコンテナの作成

  • app\Lib\CSV.php
<?php namespace MyProject\Lib\CSV;

use Response;

class CSV
{    
    public function __construct()
    {
    }

  /**
     * CSVダウンロード
     * @param array $list
     * @param array $header
     * @param string $filename
     * @return \Illuminate\Http\Response
     */
    public function download($list, $header, $filename)
    {
        if (count($header) > 0) {
            array_unshift($list, $header);
        }
        $stream = fopen('php://temp', 'r+b');
        foreach ($list as $row) {
            fputcsv($stream, $row);
        }
        rewind($stream);
        $csv = str_replace(PHP_EOL, "\r\n", stream_get_contents($stream));
        $csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8');
        $headers = array(
            'Content-Type' => 'text/csv',
            'Content-Disposition' => "attachment; filename=$filename",
        );
        return \Response::make($csv, 200, $headers);
    }
}

自身のお好きな場所に、サービスコンテナを作成します。

サービスプロバイダの作成

<?php namespace MyProject\Lib\CSV;

use Illuminate\Support\ServiceProvider;

class CSVServiceProvider extends ServiceProvider
{

    public function register()
    {
        $this->app->bindshared('csv', function()
        {
            return new CSV;
        });

    }

}

先ほど作成したCSVというサービスコンテナを”csv”という名前で登録しています。

ファサードの作成

<?php namespace MyProject\Facades;

use Illuminate\Support\Facades\Facade;

class CSV extends Facade
{

    public static function getFacadeAccessor()
    {
        return 'csv';
    }

}

CSVサービスコンテナの起動するサービスプロバイダを”csv”という名前で登録しましたが、Facadeでどのサービスプロバイダと紐つけるか行なっています。

今回の場合CSVというファサードはCSVServiceProvierと紐ついています。

composer dump-autoload

してオートロードをしておきましょう。

パスを通す

'providers' => array(
       ……………………
    'MyProject\CSV\CSVServiceProvider',// 追記

    'aliases' => array(
       ……………………
    'CSV'        => 'MyProject\Facades\CSV',// 追記

あとは

CSV::download();

でcsvの機能が利用できます。

Facadeの利点

Facadeとして機能を作成しておく事により、以下のメリットがあります。

  • 一連の機能をまとめる事ができるためコントローラの肥大化を抑える事ができる
  • メンテナンスが用意である

色々なコントローラでCSV出力の機能を書いてしまうと、コントローラが肥大化し管理が大変になります。

またCSV出力機能に修正を入れる時、多くのコントローラに散在したCSV出力機能を修正することは困難です。

まとめ

今回はFacadeの概念的な理解と作成方法についての内容でした。

僕自身まだFacade・サービスプロバイダ・サービスコンテナに関しての理解が足りていませんが、いくつかの記事を参考に概念的な理解を進める事ができました。

しかし、これより先はブログ記事等に頼らず、ソースを読む必要がありそうです

特にDI(Dependency Injection)、依存注入についてソースコードを辿る必要がありそう。

もし強いエンジニアの方がいれば、教えて頂きたいです!