All rules

Sheath rule

blade-valid-directive-arguments

Core directives must carry the arguments Blade expects; missing or invalid arguments cause parse or render-time failures.
Package
Core
Category
Blade
Default severity
error by default
Auto-fix
Manual fix

#Why

Blade compiles every known directive it meets, arguments or not, sane or not. Nothing warns at compile time; the page breaks at first render, and the error points into storage/:

<p>You should @if something is wrong</p> -> if: invalid PHP
<style>@use "sass:math";</style> -> use ; invalid PHP
<form>@method</form> -> echo method_field; fatals at render
@vite -> app(Vite::class)(); ArgumentCountError
@if() -> if(): invalid PHP
@method(/* nothing */) -> method_field(); ArgumentCountError
@lang() -> translator->get(); ArgumentCountError
@include(‘partials.nav’) -> make(‘partials.nav’) fatals at render
@foreach($items) -> ViewCompilationException at render

Most bare occurrences are not Blade at all: prose that happens to say @if, JSDoc's @error, SCSS's @use/@each, CSS that mentions a directive name. Blade compiles them anyway. The @@ escape (@@if) hands the text to the page as written.

Two argument defects get the same treatment because Blade accepts them silently: smart quotes (‘ ’ “ ”) compile into PHP that fails at first render with an undefined-constant error, and directive arguments must open their ( on the same line as the directive. A newline in between compiles the bare directive and renders the parenthesized text as page output.

#Examples

#Bad

<p>You should @if something is wrong check twice.</p>
<style>@use "sass:math";</style>
<form>@method</form>
@vite
@include(‘partials.nav’)
@foreach($items)
<li>Missing the as clause</li>
@endforeach
@if
($condition)
<p>Arguments on the next line are not arguments</p>
@endif
<style>div:empty { color: red } @empty</style>

#Good

@if($user->isAdmin())
<p>Admin</p>
@endif
@foreach($items as $item)
<li>{{ $item }}</li>
@endforeach
@include('partials.nav')
{{-- The escape for prose, CSS, and JS that collide with directive names --}}
<p>You should @@if something is wrong check twice.</p>
<style>@@use "sass:math";</style>
{{-- Bare forms that are legitimate Blade are never reported --}}
@auth
<p>Signed in</p>
@endauth
@once
<script src="widget.js"></script>
@endonce
@csrf
{{-- Unknown names pass through Blade untouched --}}
<p>Email john@stillat.com, or find @john on Slack.</p>
<style>@media (min-width: 640px) { .cards { display: flex; } }</style>
{{-- Blade's argument matcher understands strings, so this is fine --}}
@if($label == ')')
<p>Closing paren</p>
@endif

#What Is Checked

The following checks apply to core directives whose bare form always miscompiles, including @if, @foreach, @include, @section, @method, @json, @error, @use, @vite, @can, and the rest of their families. Supported Laravel families also include @session, @context, @fragment, @hasstack, @pushif, @includeisolated, @extendsfirst, and @componentfirst.

  1. Missing arguments. This is usually a prose, JSDoc, or SCSS/CSS collision, or the newline mistake above.
  2. Arguments opening on the next line. Blade only attaches arguments whose ( starts on the same line.
  3. Arguments that are not valid PHP. Validation applies whenever a known directive supplies them, including directives such as @auth and @guest whose arguments are optional. Loop syntax such as @for($i = 0; $i < 10; $i++) and @foreach($items as $item) is accepted.

@dd and @dump still require same-line parentheses, but they accept an empty argument list. Calls such as @dd() and @dump() therefore have valid arguments. See blade-no-debug for restricting debug calls.

For @foreach/@forelse specifically, the arguments must satisfy Blade's own as test, or the view throws Malformed @foreach statement at first render. Smart quotes outside PHP strings and comments are reported; Unicode quote characters inside an ordinary quoted PHP string or comment are valid and are left alone.

Directives that are legitimately bare (@auth, @guest, @once, @csrf, @production, @php, @verbatim, @else, every @end*, ...) are never in the requires-arguments set, and unknown directive names are never reported at all. The bare @lang ... @endlang translation block is also valid, while the standalone @lang() form is not: it compiles to translator->get() without the required translation key. When an optional directive does supply arguments, those arguments must still be valid PHP. @empty is context-dependent: its bare form is only valid as a @forelse branch. Anywhere else, including CSS's div:empty or prose, Blade compiles the forelse empty branch, emitting a stray endforeach with no loop to close, so a bare @empty outside @forelse is reported.

@vite requires an entrypoint on the same line. Blade compiles a bare @vite to a call to Illuminate\Foundation\Vite with zero arguments, and that invokable requires its $entrypoints argument, so the view throws an ArgumentCountError when rendered.

#Notes

  • An unclosed prose @if also lacks a matching terminator. Escape prose as @@if, and see blade-unclosed-directives for block-pairing requirements.
  • PHP validation reports only arguments that PHP rejects.
  • No auto-fix is available because a bare @if may be prose to escape or a directive missing its condition.

#Related Rules