Laravel『Invalid Blade Directive』の原因と対処法

Laravel『Invalid Blade Directive』の原因と対処法

Laravelの「Invalid Blade Directive」は、Bladeテンプレート内で使ったディレクティブ(@xxxx)が未定義、スペルミス、または引数/構文がBladeの期待と合っていないときに発生する。代表例は「@auth/@guest/@can などの書き間違い」「独自ディレクティブを登録したつもりが反映されていない」「パッケージのディレクティブがサービスプロバイダ未読込で使えない」「Bladeキャッシュが古い」「@php/@endphp の閉じ忘れ・括弧の不整合で別ディレクティブ扱いになる」など。まずは“その @ディレクティブが標準か、独自か、パッケージ由来か”を確定させ、登録場所とキャッシュを点検する。

症状と発生条件(典型例)

よくあるメッセージ例。

InvalidArgumentException: Unknown directive [admin]
InvalidArgumentException: Unknown directive [role]
Invalid Blade directive: @admin

発生条件の典型:
・Bladeに存在しない @xxxx を書いた(typo含む)
・独自 @xxxx を AppServiceProvider などで登録したが、実行されていない
・config:cache / optimize により変更が反映されていない
・本番のみ発生(キャッシュ、デプロイ差分、サービスプロバイダ差)
・パッケージのディレクティブ(例:@role)を使っているが、パッケージ未導入/未設定

まず確認:ディレクティブが標準か(typoを潰す)

最初に疑うべきはスペルミスや名称の思い違い。
例:@auth / @guest / @can / @cannot / @csrf / @method / @error / @isset / @empty などは標準。
よくあるtypo例。

@auht   // authのtypo
@gest   // guestのtypo
@cann   // canのtypo
@endauthh // endauthのtypo

閉じディレクティブの対応も確認する(@auth なら @endauth)。

原因1:独自ディレクティブを登録していない(または登録名が違う)

発生条件:
・Blade::directive(‘admin’, …) を書いていないのに @admin を使っている
・登録名は admin だがテンプレート側は @isAdmin のように違う名前
対処:AppServiceProvider などで directive を登録する。

// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Blade;

public function boot(): void
{
    Blade::directive('admin', function () {
        return "<?php if(auth()->check() && auth()->user()->is_admin): ?>";
    });

    Blade::directive('endadmin', function () {
        return "<?php endif; ?>";
    });
}

Blade側。

@admin
    <p>管理者だけ表示</p>
@endadmin

条件分岐を自作するより、@can/@auth で足りるケースも多い(既存機能のほうが事故が少ない)。

原因2:Blade::if を使うべきケースで directive にしてしまい構文が崩れる

条件系は Blade::if のほうが書きやすく、@end… の対応も自動で揃えやすい。
発生条件:
・directive で @role(…) のような括弧引数を雑に処理して、生成PHPが壊れる
対処:Blade::if を使う。

// AppServiceProvider.php
use Illuminate\Support\Facades\Blade;

public function boot(): void
{
    Blade::if('admin', function () {
        return auth()->check() && auth()->user()->is_admin;
    });
}

Blade側。

@admin
  <p>管理者</p>
@endadmin

原因3:パッケージ由来ディレクティブ(@role 等)が未導入/未設定

発生条件:
・@role/@permission などを使っているが、権限系パッケージが入っていない
・入っているが、サービスプロバイダが読み込まれていない/設定が未publish
対処:
・そのディレクティブを提供するパッケージが導入され、プロバイダが有効か確認
・まずは一時的に標準の @can に置き換えて挙動を確認して切り分ける

@can('viewAdmin', $user)
  ...
@endcan

パッケージ依存のディレクティブは、環境差(本番だけcomposer installが違う等)で壊れやすい。

原因4:サービスプロバイダが実行されていない(登録場所/キャッシュ/オートディスカバリ)

発生条件:
・AppServiceProvider の boot に書いたが、別ファイル/別クラスに書いて読まれていない
・config/app.php の providers を手でいじって読み込みを壊した
・本番で config:cache によりプロバイダ差分が反映されていない
対処:
・登録場所を AppServiceProvider::boot に寄せる
・キャッシュをクリアして反映させる

php artisan config:clear
php artisan cache:clear
php artisan view:clear

最適化運用なら、クリア後に再生成する。

php artisan config:cache

原因5:Bladeキャッシュが壊れている/古い(viewキャッシュ)

発生条件:
・ディレクティブを追加したのに反映されない
・デプロイで resources/views は更新されているが、compiled view が古い
対処:viewキャッシュをクリアする。

php artisan view:clear

さらに疑わしい場合は optimize を避け、問題が再現するか確認する。

原因6:ディレクティブの構文ミス(括弧、クォート、閉じ忘れ)

発生条件:
・@if( の閉じ括弧が無い
・@php … @endphp の閉じ忘れ
・@foreach/@endforeach の対応崩れで、以降が“別の謎ディレクティブ”として解釈される
対処:直前の行から構文整合を確認する。特に以下は崩れやすい。

@if($a === 'x'  // ) が無い
    ...
@endif

@php
  $x = 1;
// @endphp が無い

エラーに出ているディレクティブが「本当の原因箇所」とは限らず、直前の構文崩れが原因であることがある。

サンプル:引数付き独自ディレクティブ(directive版)

括弧引数を扱う場合、生成するPHPを安全に組み立てる。

// AppServiceProvider.php
use Illuminate\Support\Facades\Blade;

public function boot(): void
{
    Blade::directive('feature', function ($expression) {
        // $expression には "(...)" が文字列として入る
        return "<?php if(app('feature')->enabled{$expression}): ?>";
    });

    Blade::directive('endfeature', function () {
        return "<?php endif; ?>";
    });
}

Blade側。

@feature('new_ui')
  <p>新UI</p>
@endfeature

expressionの扱いを雑にすると、生成PHPが壊れて別エラーになるため、複雑な条件は Blade::if のほうが安全。

チェックリスト(上から順に確認する)

1) その @xxxx は標準ディレクティブか?単純なtypo/閉じ忘れではないか
2) 独自なら、Blade::directive / Blade::if が AppServiceProvider::boot に登録されているか
3) 登録名とテンプレートで使っている名前が完全一致しているか(@end… 含む)
4) パッケージ由来の @role 等なら、パッケージ導入・プロバイダ有効化・本番のcomposer差分が無いか
5) config/view キャッシュが残っていないか(config:clear, cache:clear, view:clear)
6) エラー行の直前に括弧/クォート/ディレクティブの対応崩れが無いか