はじめに
Laravelのファサードを作成する手順をまとめました。
Laravelを使用する上で、避けては通れないほど重要な機能の一つです。
実際に独自のファサードを作成し、使い方もまとめましたので、実践に役立つと思います。
Laravel Sailでの開発環境の構築方法は以下をご覧ください。
他にも私のブログで、Laravelについて解説している記事がありますのでご覧ください。
【紹介】個人開発
私の個人開発ですがQuiphaというサービスを開発しました。(Laravel, Vue3など)
良かったら、会員登録して動作を試してみて下さい。
また、Laravel 9 実践入門という書籍を出版しました。
Kindle Unlimitedを契約している方であれば、読み放題で無料でご覧いただくことができます。
ファサードのメリット
一番分かりやすいメリットとしては、自分でインスタンスを生成しなくても使える点でしょう。
// インスタンスを手動で作成
$book = new Book();
$book->getBook(1);
// インスタンスをnewせずに取得
\Book::getBook(1);
また、Laravelのファサードは、モックするための便利な方法が提供されているため、テストを行う際にも役立ちます。
サービスクラスの作成
今回は、ビジネスロジックを想定し、サービスクラスとして作成しますが、クラスであれば何でも良いです。
Servicesフォルダを作成しました。
app\Services\
上記のフォルダに以下のような簡単なクラスを作成しました。
<?php
namespace App\Services;
/**
* Book Service
*/
class BookService
{
/**
* get book
*
* @param string $book_no no
*/
public function getBook($book_no)
{
return "get book: " . $book_no;
}
}
サービスプロバイダーの作成
クラスをサービスコンテナに登録します。以下のコマンドで、サービスプロバイダーを作成します。
$ sail php artisan make:provider BookServiceProvider
ファイルが作成されました。
app\Providers\BookServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class BookServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
registerメソッドの中で、サービスコンテナへの登録を行います。
名前とクラスパスでサービスコンテナに登録することができます。
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->bind('book', 'App\Services\BookService');
}
サービスプロバイダーの登録
configファイルを開きましょう。
config\app.php
先ほど作成したサービスプロバイダーをconfigに追加します。
'providers' => [
...
App\Providers\BookServiceProvider::class,
],
今回はファサードを介して取得するので関係ありませんが、この時点でサービスコンテナからインスタンスを取得することができます。
$bookService = app()->make('book');
$book = $bookService->getBook(1);
echo $book; // get book: 1
ファサードの作成
ファサードを作成します。Facadesフォルダを作成しました。
app\Facades\
サービスプロバイダーの、サービスコンテナーに指定した名前を戻り値に指定します。
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Book extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'book';
}
}
エイリアスの登録
エイリアスに登録しましょう。configファイルを開きます。
config\app.php
'aliases' => [
...
'Book' => App\Facades\Book::class,
],
これにより、長いクラスのパスを毎回指定しなくて済みます。
例えばuseに指定しなくても、バックスラッシュだけでFacadeにアクセスできるようになります。
\Book
ファサードを使ってみる
ファサードを介して、サービスクラスのインスタンスを取得してみます。
エイリアスに登録したため、useに宣言は不要で、以下のようにファサードを使用することができます。
$book = \Book::getBook(1);
echo $book; // get book
VS Codeで確認
エイリアスについては、別記事で詳細にまとめていますので、こちらをご覧ください。
今回は以下の手順を行い、自作のファサードがVS Code上でエラーにならないか確認しましょう。
対応する前は、VS Code上でソースを確認するとエラー表示になっていました。
ちなみに、ソース上ではこのようになっていますが、実際は問題なく実行できます。
以下のコマンドで、定義を最新化します。
$ sail php artisan ide-helper:generate
VS Code上で、エラーもなく、PHPDocも正常に表示され、自作した関数へジャンプすることができました。
ファサードのモック
ファサードのメリットの一つとして、ファサードへの呼び出しをモックできます。
先程と同様、通常の実行を見てみましょう。
$book = \Book::getBook(1);
echo $book; // get book: 1
それでは、getBookメソッドの呼び出しをモックしてみましょう。
もとのクラスは全く変更しておりません。shouldReceiveとandReturnを使用するだけで、getBookの戻り値を変更することができました。
\Book::shouldReceive('getBook')->andReturn('test code!');
$book = \Book::getBook(1);
echo $book; // test code!
Laravelのモックについては、以下を参考ください。
ファサードを介して取得するインスタンスはシングルトン?
検証
ここからは色々と検証してみます。
インスタンスの挙動を試すために、クラス内に変数の追加と、getter/setterを追加しました。
<?php
namespace App\Services;
/**
* Book Service
*/
class BookService
{
var $book_name = "default name";
/**
* get book name
*
* @return string book name
*/
public function getBookName()
{
return $this->book_name;
}
/**
* set book name
*
* @param string $name name
*/
public function setBookName($name)
{
$this->book_name = $name;
}
/**
* get book
*
* @param string $book_no no
*/
public function getBook($book_no)
{
return "get book: " . $book_no;
}
}
サービスコンテナの確認
サービスコンテナには、「$this->app->bind()」で登録しました。
これはサービスコンテナから取得する度に、新しいインスタンスが取得されます。
$bookService = app()->make('book');
echo spl_object_id($bookService); // インスタンスID: 282
$bookService->setBookName("laravel");
echo $bookService->getBookName(); // laravel
// もう一度取得すると、別インスタンスで取得される
$bookService = app()->make('book');
echo spl_object_id($bookService); // インスタンスID: 289
echo $bookService->getBookName(); // default name
今度は、サービスコンテナにシングルトンで登録してみます。
$this->app->singleton('book', 'App\Services\BookService');
試してみると、同じインスタンスが取得できました。
$bookService = app()->make('book');
echo spl_object_id($bookService); // インスタンスID: 282
$bookService->setBookName("laravel");
echo $bookService->getBookName(); // laravel
// もう一度取得すると、同じインスタンスが取得される
$bookService = app()->make('book');
echo spl_object_id($bookService); // インスタンスID: 282
echo $bookService->getBookName(); // laravel
ここまでは想定通りの動きです。
ファサードの確認
では、サービスコンテナには、「$this->app->bind()」で登録した場合、ファサードを介して取得するインスタンスは毎回変わるのでしょうか。
以下のコードで試してみました。
\Book::setBookName("laravel");
echo \Book::getBookName(); // laravel
上記のことから、ファサードを介して取得できるインスタンスは毎回同じようです。
(シングルトンのような挙動)
需要があるかどうかは別として、ファサードを介して新しいインスタンスを取得するにはどうすればよいでしょうか。
ファサードクラスに、リフレッシュを行う関数を作成しました。
app\Facades\Book.php
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Book extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'book';
}
/**
* refresh
*/
public static function refresh()
{
static::clearResolvedInstance(static::getFacadeAccessor());
}
}
refresh関数を呼ぶことで、新しいインスタンスを取得できることが確認できました。
\Book::setBookName("laravel");
echo \Book::getBookName(); // laravel
// インスタンスをリフレッシュ
\Book::refresh();
// 新しいインスタンスを取得
echo \Book::getBookName(); // default name
その他
初学者へ
Laravelを初めて触る方へ向け、手順やアドバイスをまとめました。
外部サーバーへ公開
作成したアプリは公開して使ってもらいましょう!
Laravelアプリケーションを外部公開する方法をまとめました。
脆弱性対策
脆弱性を抱えたアプリケーションの場合、攻撃を受ける可能性があり大変危険です。
作成したアプリケーションは、脆弱性対策も意識しましょう。
GitHubと連携
GitHubと連携する方法を解説しました。
プロジェクトの管理はGitHubを活用しましょう。
GitHub Copilot
GitHub Copilotを導入し、AIにコーディングをサポートしてもらうこともできます。
さいごに
今回は、Laravelのファサードを作成する手順をまとめました。
Laravelは色々と便利な機能や仕組みを提供していますので、是非理解して活用しましょう。
他にも私のブログで、Laravelについて解説している記事がありますのでご覧ください。
コメント