Laravelにはいつでもどこでも使えるコンセプトの関数であるhelper関数が用意されています。
ヘルパ 6.x Laravel
例えば、public_path関数は次の通りの関数で__DIR__定数を元にどうこうする手間を省いてくれます。
public_path()
public_path関数は、publicディレクトリの完全パスを返します。さらに、publicディレクトリ中の指定ファイルへの完全パスを生成することもできます。$path = public_path(); $path = public_path('css/app.css');
便利なhelper関数ですが実行環境によっては問題の起きる場合があります。例えば、public_path関数は/publicディレクトリがドキュメントルートであることを期待しますが、実際の環境ではそれができないこともあります(主に運用上の理由)。この記事ではこれを上書きする方法を紹介します。
helper関数はLaravelの根元にある関数です。この記事で紹介する方法は結構ハックな方法ですので上書きせずに済む方法があるならそちらを選んだ方が賢明です。
基本的なhelper関数の読み込みはComposerが行っています。vendor/laravel/framework/src/Illuminate/Support/composer.jsonの次の記述が定義箇所です。
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
},
"files": [
"helpers.php"
]
},
題では上書き、としましたが実際には先に関数を定義することによってLaravlの用意したhelper関数でなく自前で用意したhelper関数を優先させる方針をとります。これの実現にはComposerのオートローダファイルよりも先に自前helper関数ファイル(ここでは/app/helper.phpとする)を読み込ませればよいです。
方針の実現のためには困ったことがあります。Laravelはwebサーバ、コマンドライン、テスト(PHPUnit)とそれぞれの場合で一番最初に読むPHPファイルが異なっており(ローカルサーバも含めれば4つ)それぞれに次の様なcomposerのオートローダファイル(autoload.php)読み込みが記述されています。
// 例はpublic/index.php
<?php
/**
* Laravel - A PHP Framework For Web Artisans
*
* @author Taylor Otwell <taylor@laravel.com>
*/
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/
require __DIR__.'/../vendor/autoload.php';
これらそれぞれに先読みの記述を追加するのは手間です。特にテストのPHPUnitはvendor以下にあり、手で触るのは非常にためらわれます。解決の方法にcomposerのオートローダファイルの書き換えがあります。composerのオートローダファイルnの中身とこれを実現するArtisanコマンドファイルは次です。
// 書き換え対象の/vendor/autoload.php <?php // autoload.php @generated by Composer require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInitbbd211dfaae508fccbfee8d10254e044::getLoader();
<?php
namespace App\Console\Commands\ForDevelop;
use App\Console\BaseCommand;
class OverrideHelper extends BaseCommand
{
protected $signature = 'develop:override-helper';
protected $description = 'composerの自動出力したオートローダに/app/helper.phpの読み込みを最優先にする処理を書きこむ';
public function handle()
{
$autoloaderPath = base_path('vendor/autoload.php');
$oldContent = file_get_contents($autoloaderPath);
// オートローダファイルの一番最初のrequire_onceに自前のヘルパ関数ファイルが来るようにする
$newContent = str_replace('require', "require_once __DIR__ . '/../app/helpers.php';\nrequire", $oldContent);
// vendor/autoload.phpを直に書き換える
file_put_contents($autoloaderPath, $newContent);
}
}
これをcomposerのオートローダファイルが変わるたびに実行されるようにプロジェクトのcomposer.jsonに組み込めばOKです.
# composer.json
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
"@php artisan develop:override-helper"
],
}
これで自作のhelper関数が最優先で読み込まれるようになります。