@switch
Selects one of several template branches by matching a value against @case labels.
@switch($value) @case($case) ... @break @default ... @endswitchParameters
| Parameter | Type | Description |
|---|---|---|
$value | mixed | The expression being matched. Compiled into PHP's switch, so comparison is loose (==), not identical (===). |
$case | mixed | A candidate value for one @case label. Repeat @case for each branch. |
Return value
Nothing — the matching @case block (and everything after it until a @break) is emitted into the output.
Errors
A missing @endswitch, or markup placed between @switch and the first @case, produces invalid PHP and a ParseError in the compiled view.
@switch compiles to PHP's switch, with @case, @break, @default and @endswitch mapping onto their PHP counterparts one for one. Reach for it when a single value picks between three or more presentations — an order status, a notification type, a plan tier — where a chain of @elseif would repeat the same subject on every line.
What trips people up
Every branch needs its own @break. Leave one out and PHP falls through into the next case, rendering two branches. That is occasionally what you want — two @case labels stacked with no markup between them share a body — but far more often it is a bug that only shows up for one status value.
Matching uses loose comparison, so @case(0) can match a string status in older PHP semantics; compare strings against strings and enum cases against ->value.
Nothing may appear between @switch and the first @case, not even a comment — the compiled switch has nowhere to put it.
Inside a loop, a @break written for a case breaks the switch, not the surrounding @foreach.
Example
<?php
use Illuminate\Support\Facades\Blade;
$template = <<<'BLADE'
@switch($role)
@case('admin')
Full access
@break
@case('editor')
Can publish
@break
@default
Read only
@endswitch
BLADE;
echo Blade::render($template, ['role' => 'editor']);
// Can publish
echo Blade::render($template, ['role' => 'viewer']);
// Read onlyWhen to use it
- Render a differently coloured badge for each order status
- Pick an icon per notification type in an activity feed
- Choose one of several call-to-action blocks based on the subscriber's plan
Frequently asked questions
Do I need @break in every Blade @case?
Yes, unless you intend to fall through. Without @break the compiled PHP continues into the next case and renders both branches; two stacked @case labels with no markup between them is the deliberate way to share one body.
Why does my Blade @switch throw a parse error?
Usually because there is markup, whitespace with output, or a comment between @switch and the first @case. PHP's switch has nowhere to place that content, so the compiled view fails to parse.
Should I use @switch or a chain of @elseif in Blade?
Use @switch when one value is compared against three or more fixed alternatives, and @if/@elseif when the branches test different expressions. @switch compares loosely, so keep both sides of each comparison the same type.
More examples
Sharing one body between two cases
Stacking two @case labels with nothing between them is deliberate fall-through: 'paid' enters at the first label, finds no markup, and continues into the shared body. This is the one situation where an omitted @break is correct — which is exactly why an accidental omission elsewhere is hard to spot in review.
<?php
use Illuminate\Support\Facades\Blade;
$template = <<<'BLADE'
@switch($status)
@case('paid')
@case('refunded')
<span>Settled</span>
@break
@case('pending')
<span>Awaiting payment</span>
@break
@default
<span>Unknown</span>
@endswitch
BLADE;
echo Blade::render($template, ['status' => 'refunded']);
// <span>Settled</span>Matching a backed enum
Comparing ->value against ->value keeps both sides plain strings. Matching the enum instances directly also works in PHP, but mixing the two — an enum on one side and a string literal on the other — never matches, and the branch silently disappears rather than erroring.
<?php
// app/Enums/OrderStatus.php
enum OrderStatus: string
{
case Pending = 'pending';
case Shipped = 'shipped';
}
// resources/views/orders/status.blade.php
$view = <<<'BLADE'
@switch($order->status->value)
@case(App\Enums\OrderStatus::Pending->value)
<span>Preparing your order</span>
@break
@case(App\Enums\OrderStatus::Shipped->value)
<span>On its way</span>
@break
@endswitch
BLADE;
echo view('orders.status', ['order' => $order])->render();@break inside a loop
The @break belongs to the switch, so the loop keeps going and 'b' is still rendered. To leave the loop from inside a case you need a different mechanism — restructure with @if and the loop's own @break, which accepts an inline condition.
<?php
use Illuminate\Support\Facades\Blade;
$template = <<<'BLADE'
@foreach ($rows as $row)
@switch($row)
@case('skip')
(skipped)
@break
@default
{{ $row }}
@endswitch
@endforeach
BLADE;
echo Blade::render($template, ['rows' => ['a', 'skip', 'b']]);
// a (skipped) b
Discussion