自作ライブラリを使いたいけどどうやるの?
Laravelで自作の関数をまとめたライブラリをどの場所からでも簡単に呼び出せるようにする方法です。 サービスコンテナ/サービスプロバイダ/ファサードを使って実現する方法です。
Laravel勉強中なので、調べながら理解していった過程も合わせて書きます。
まず、自作関数のライブラリを「app/MyLib/MyUtil.php」として作成します。
この中の “testFunction()” をどこからでも簡単に呼び出して使いたいのです。
<?php
namespace App\Mylib;
class MyUtil
{
public function testFunction()
{
return 'succeeded';
}
}
とりあえずストレートに呼び出す
まずは何も工夫せず呼び出してみます。
routes/web.php に以下のコードを書いて、ブラウザから「ルート/test」を呼び出してみると、「succeeded」と表示されます。目的の関数を正しく呼び出せました。
でも、この方法だとどこからでも呼び出すには毎回 MyUtilクラスをインスタンス化する必要があり、まったく快適ではありません。
<?php
Route::get('test', function()
{
// MyUtil クラスをインスタンス化する
$myUtil = new App\MyLib\MyUtil;
// testFunction 関数を実行して 文字列'succeeded' を返す
return $myUtil->testFunction();
}
);
サービスコンテナに登録して呼び出す
サービスコンテナとは、文字通りサービスを入れておくコンテナのことで、この場合は自作ライブラリがサービスにあたります。
サービスコンテナにサービスを登録しておくと、アプリケーションのどこからでもインスタンス化して呼び出せるらしい。
まさにやりたかったこと!!登録の方法は以下の通り。
app()->bind(<任意のサービス名>, <登録したいサービス>);
これを
app()->make(<サービス名>);
とするとどこからでもサービスをインスタンス化して呼び出す事ができるのです。
実際に先ほどのコードをこのやり方に変更してみます。
<?php
Route::get('test', function()
{
// サービスコンテナに'MyUtil'という名前で MyUtilクラスを登録する。
// これでどの場所からでも MyUtilクラスのインスタンスが呼び出せる。
app()->bind('MyUtil', App\MyLib\MyUtil::class);
// サービスコンテナからMyUtilクラスのインスタンスを $myUtil に格納する。
$myUtil = app()->make('MyUtil');
// testFunction 関数を実行して 文字列'succeeded' を返す。
return $myUtil->testFunction();
}
);
再びブラウザから「ルート/test」を呼び出してみると、「succeeded」と表示されます。
やったー!!...というわけにはいきません。
「app()->bind()」を実行したのは ‘test’ のPOSTメソッドにアクセスした時だけです。
これでは他のURLにアクセスした時には呼び出せないのです。
サービスプロバイダに登録する
この悩みを解決するにはサービスプロバイダを利用します。
まずは以下のartisanコマンドでサービスプロバイダを作成します。(既存のサービスプロバイダを使ってもよい。)
$ php artisan make:provider MyUtilServiceProvider
ここでは、MyUtilServiceProvider という名前のサービスプロバイダを作成しましたが、名称は任意のもので構いません。
app/Providers に MyUtilServiceProvider.php というファイルができたので、そこに以下のコードを書きます。
<?php
use App\Mylib\MyUtil;
---
public function register()
{
// 自作ユーティリティライブラリをサービスコンテナに登録
$this->app->bind('MyUtil', MyUtil::class);
}
次に config/app.php の ‘providers’配列の末尾に以下のコードを追加します。
<?php
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\MyUtilServiceProvider::class, // ← この行を追加する。
これにより、アプリケーションの起動時に App\Providers\MyUtilServiceProvider::class の中の register()関数が実行され、「app()->bind(‘MyUtil’, MyUtil::class);」により自作ライブラリがどこからでも使えるようになります。
(MyUtilServiceProvider.php の中の「$this->app」は、「app()」と同じこと。)
routes/web.php を以下のように書き換えます。
<?php
Route::get('test', function()
{
$myUtil = app()->make('MyUtil');
return $myUtil->testFunction();
}
);
ブラウザからアクセスしても「succeeded」が表示されます。
ファサードでさらにスマートにする
かなり洗練されてきましたが、app()->make()関数を使うあたりがまだ少しやぼったい感じがします。仕上げにファサードを使ってさらにスマートにします。
まず、新規にファイル app/Facades/MyUtilFacade.php を作成して下記のコードを記述します。
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class MyUtilFacade extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'MyUtil';
}
}
次に、config/app.php の ‘aliases’ 配列に先ほど作成したファサードファイルを追加します。
<?php
'aliases' => Facade::defaultAliases()->merge([
// 'ExampleClass' => App\Example\ExampleClass::class,
'MyUtil' => App\Facades\MyUtilFacade::class, // ← この行を追加する
])->toArray(),
これにより、routes/web.php は
<?php
Route::get('test', function()
{
return MyUtil::testFunction();
}
と書く事ができるようになり、同様にブラウザからのアクセスで「succeeded」が表示されます。
この「MyUtill」は、アプリケーションのどこからでも呼び出して使う事ができるようになっています。
始めの野暮ったい書き方からLaravelのスマートな書き方になりました!