bootstrap/app.phpのないプロジェクトをLarastanで静的解析する
こんにちは、でぃーほりです。
今回は、Larastanについての記事です。
bootstrap/app.php がないLaravelプロジェクト -- パッケージ
例えば、複数のサブシステムからなるシステムを作る際、サブシステム横断的に使うものを共通化するためのプロジェクトを作ることがあります。
- migration
- Eloquent Model
- config
- ドメインロジック
- etc.
以下、これをパッケージと呼びます。
パッケージは、単体ではWebアプリケーションとして動作しないので、 bootstrap/app.php や Kernel.php などを持ちません。
tree -d -L 1 common
common
|-- config
|-- database
|-- resources
|-- src
|-- tests
`-- vendor
bootstrap/app.php がないと、configが正しく設定されず、静的解析が失敗することがある
Larastanでは、configが正しく設定されていないと静的解析に失敗することがあります。
例えば、解析対象のコードにEloquent Modelのリレーションシップが含まれていると、DBのコネクションの設定が必要です。
bootstrap/app.php がないと、configが正しく読み込まれず、下記のようなエラーが出ます。
------ -------------------------------------------------------------------
Line Models/MyModel.php
------ -------------------------------------------------------------------
Internal error: Database connection [subsystem_a] not configured.
Run PHPStan with --debug option and post the stack trace to:
https://github.com/phpstan/phpstan/issues/new
------ -------------------------------------------------------------------
解消方法
configを読み込むための bootstrap/app.php を書きます。
<?php
declare(strict_types=1);
use NunoMaduro\Larastan\ApplicationResolver;
require __DIR__ . '/../vendor/autoload.php';
$app = ApplicationResolver::resolve();
$configFilepaths = glob(__DIR__ . '/../config/*');
assert($configFilepaths !== false);
foreach ($configFilepaths as $configFilepath) {
$pathinfo = pathinfo($configFilepath);
$configName = $pathinfo['filename'];
$app->make('config')->set($configName, require $configFilepath);
}
return $app;
詳細
静的解析対象のLaravelプロジェクトにbootstrap/app.phpがない場合、 Larastanのbootstrap.php が使用されます。
執筆時点でのmaster HEADのコードを引用します。
...
use NunoMaduro\Larastan\ApplicationResolver;
define('LARAVEL_START', microtime(true));
if (file_exists($applicationPath = getcwd().'/bootstrap/app.php')) { // Applications and Local Dev
$app = require $applicationPath;
} else { // Packages
$app = ApplicationResolver::resolve();
}
...
静的解析対象がパッケージの場合、else句に入って\NunoMaduro\Larastan\ApplicationResolver::resolve()
でApplicationが構築されます。
続いて、 ApplicationResolver.php を見てみます。
...
use Orchestra\Testbench\Concerns\CreatesApplication;
/**
* @internal
*/
final class ApplicationResolver
{
use CreatesApplication;
/**
* Creates an application and registers service providers found.
*
* @return \Illuminate\Contracts\Foundation\Application
* @throws \ReflectionException
*/
public static function resolve(): Application
{
$app = (new self)->createApplication();
...
\Orchestra\Testbench\Concerns\CreatesApplication
トレイトのcreateApplication()
でApplicationを構築していることがわかります。
ここで構築されるApplicationには/vendor/orchestra/testbench-core/laravel/config/
のコンフィグが読み込まれ、パッケージのconfigが読み込まれません。
ゆえに、自分でconfigを読み込ませる必要があったわけです。
まとめ
- パッケージプロジェクトにLarastanをかけるときは、config読み込み用の bootstrap/app.php を用意する