⚠️

Laravel Extra Intellisense(vscode拡張機能)+Dockerで設定変更しないとヤバい項目

2021/10/07に公開

はじめに

Laravel開発者のみなさん、vscode拡張機能の 「Laravel Extra Intellisense」 を使っていますか?
「Laravel Extra Intellisense」はLaravelの基本的なコード補完や参照ヘルプなどが可能になる、とても便利な拡張機能ですよね。

でも、docker環境で使用する際はご注意ください。
設定変更をしておかないと、正常に動作しなかったり、思わぬエラーが発生したりします。

この記事を読むと、Docker環境でLaravel Extra Intellisenseを使用する際の正しい設定変更が可能になります。

バージョン情報

筆者の動作確認環境は以下の通りです。

  • vscode 1.60.2
  • Laravel Extra Intellisense v0.6.1
  • Docker Desktop 4.0.1
  • Docker Engine 20.10.8
  • Docker Compose 1.29.2
  • Windows10 Professional
  • WSL2 Ubuntu-20.0.4(※WSL Integration有効)
  • PHP: 8.0.11
  • Laravel Framework 8.54
  • Laravel Sail 1.0.1

前提条件

ボリュームマウントでLaravelアプリケーションのソースコードをホスト側とdockerコンテナ側で共有していること。
ぶっちゃけると、docker-compose.ymlなどで以下のような設定が為されていること。

docker-compose.yml
services:
    laravel.test:
        volumes:
            - '.:/var/www/html'

筆者の環境はLaravel Sail環境なので、デフォルトでボリュームマウントされています。

Laravel Extra Intellisenseとは?

Laravel用のオートコンプリート機能を追加してくれます。ルート名とルートパラメータ、ビューと変数、コンフィグ、Laravel Mix、多言語化、バリデーションルールの補完を追加するパッケージです。

そしてこの拡張機能は、Laravelアプリケーションを自動的かつ定期的に実行して、オートコンプリートを提供するために必要な情報を取得します。

では、どのようにLaravelアプリケーションを自動的かつ定期的に実行しているのでしょうか?
それは、以下のように設定されています。

上記のコマンドが1分間隔で実行されています。

どのようなコマンドが実行されているのか?

php -rコマンドにより、以下のプログラムが実行されています。
つまり、{code}の中身は以下です。

以下、筆者の環境情報です。

  • base path:/var/www/html
  • アプリケーション名:example-app
{code}
define('LARAVEL_START', microtime(true));

require_once '/var/www/html/example-app/vendor/autoload.php';

$app = require_once '/var/www/html/example-app/bootstrap/app.php';

class VscodeLaravelExtraIntellisenseProvider extends \Illuminate\Support\ServiceProvider{   public function register() {}?public function boot()?{       if (method_exists($this->app['log'], 'setHandlers')) {???$this->app['log']->setHandlers([new \Monolog\Handler\NullHandler()]);

??}?}}$app->register(new VscodeLaravelExtraIntellisenseProvider($app));

$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);

$status = $kernel->handle($input = new Symfony\Component\Console\Input\ArgvInput,new Symfony\Component\Console\Output\ConsoleOutput);

echo '___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_OUTPUT___';

echo json_encode(__('*'));

echo '___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_END_OUTPUT___';

上記のような長々としたプログラムを文字列で指定しているんですねぇ。。

余談ですが、上記プログラムをどうやって調べたかというと、Laravel側でpid指定でpsコマンドを実行することで判明しました。
あまりに長いコマンドにびっくりしました😅

Docker環境の何が問題なのか?

Docker環境でなければ、「php -r {code}」が実行されることに何の問題もありません。

しかし、Docker環境では上記コマンドを実行するとどうなると思いますか?

ホスト側のphpプロセスとして動作してしまいますよね。
しかし、Laravelアプリケーションとしての環境が構築されているのはdockerコンテナ側ですよね。

つまり、Laravelアプリケーションとして構築されていないホスト側の環境で定期コマンドが実行されてしまいます。

そうすると、予期せぬエラーが発生してしまうことがあります。

対応

結論として以下のように設定します。


まず、PHP Commandの方から説明します。
以下のように設定します。

LaravelExtraIntellisense.phpCommand
docker exec -w baseディレクトリ  -u ユーザー名 -t コンテナ名 php -r "{code}"

筆者のLaravel8+Sail環境では以下のようになります。

LaravelExtraIntellisense.phpCommand
docker exec -w /var/www/html  -u sail -t example-app_laravel.test_1 php -r "{code}"

次に、Base Path For Codeを以下のように設定します。

LaravelExtraIntellisense.basePathForCode
/var/www/html

動作確認

設定はしたけれども、ちゃんと動作しているかどうかわからない、では困りますよね。
以下のように設定して、標準出力をファイル出力して確認してみましょう。

docker exec -w /var/www/html  -u sail -t example-app_laravel.test_1 php -r "{code}" > ~/tmp.log"

待つこと1分。
出力されたファイル内容が以下のようでしたら設定変更は成功しています。

tmp.log
Laravel Framework  [32m8.62.0 [39m

・・・やたら長いので割愛・・・

___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_OUTPUT___["App\\Models\\Membership","App\\Models\\SocialUser","App\\Models\\Team","App\\Models\\TeamInvitation","App\\Models\\User"]___VSCODE_LARAVEL_EXTRA_INSTELLISENSE_END_OUTPUT___

まとめ

筆者の環境では、redisを使用しているので、phpredisが必要です。
dockerコンテナ側にはphpredisがインストールされていますが、ホスト側にはインストールされていませんでした。
定期コマンドが実行されるたびに、Laravelのサービスプロバイダを初期化する過程で "redisに接続できない" ってエラーが発生していたんですよね😭

そんな裏事情は露知らず・・・なんで1分間隔でエラーが発生するんだろう?
誰がプロセスを実行しているんだろう?
なんでredisに接続できないのかな?
わからないことだらけでした。
調査を続けていくと・・・問題はredisへの接続自体とは全く別のところにありました😲

システム開発の世界ではこういったケースは多いですよね・・・😅
問題となる現象とその原因が表面的には全く繋がりがない、ってケースです。

絡まりあった糸を地道に解きほぐすかのようなデバッグ作業でした😵‍💫

今後は純粋にLaravelを楽しめたらいいなと思います😄

Discussion