All rules

Sheath rule

blade-component-required-props

Calls to safely resolved local anonymous Blade components must provide every @props entry that has no default.
Package
Core
Category
Blade
Default severity
error by default
Auto-fix
Manual fix

#Why

Laravel treats a numeric @props entry as required and a string-keyed entry as optional, even when that default is null, false, an empty string, or an empty array. Explicit integer keys and integer-string keys are numeric entries, so 0 => 'title' and '1' => 'userId' are required declarations too. Finding a definitely missing required prop at the call site avoids a render-time undefined variable without inventing requirements for dynamic or third-party components.

#Examples

Given this local component:

{{-- resources/views/components/card.blade.php --}}
@props([
'title',
'userId',
'theme' => 'light',
])

These calls are flagged:

<x-card />
<x-card title="Profile" />

These calls are valid:

<x-card title="Profile" user-id="42" />
<x-card title="Profile" :user-id="$user->id" />
<x-card title="Profile">
<x-slot:user-id>{{ $user->id }}</x-slot:user-id>
</x-card>

Camel-case and kebab-case spellings are matched using Blade's component attribute convention. Static named slots also provide same-named variables to the component view and therefore satisfy matching @props entries.

#When the Rule Reports

The rule reports only when all of the following are true:

  • the linted call is under resources/views;
  • the tag resolves to a conventional local anonymous component using Laravel's precedence, starting with components/<name>.blade.php, then components/<name>/index.blade.php, then components/<name>/<last-name>.blade.php;
  • exactly one @props declaration contains a fully static array shape; and
  • neither an explicit attribute on every known render path nor a matching static named slot supplies the required value.

Class components, dynamic components, package components (x-package::name), unresolved components, dynamic prop declarations, and calls containing opaque attribute bags or spreads are not checked. When local filenames or registered metadata make class-component resolution ambiguous, the call is not reported.

Nested anonymous components resolve by dot notation. For example, <x-forms.field> resolves to components/forms/field.blade.php.

#Defaults

Every keyed declaration has a default and is therefore optional:

@props([
'title', // required
'subtitle' => null, // optional
'disabled' => false, // optional
'class' => '', // optional
'items' => [], // optional
])

#Related rules