@switch

Selects one of several template branches by matching a value against @case labels.

Signature
@switch($value) @case($case) ... @break @default ... @endswitch

Parameters

ParameterTypeDescription
$valuemixedThe expression being matched. Compiled into PHP's switch, so comparison is loose (==), not identical (===).
$casemixedA 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

Example · php
<?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 only

When 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.

Example · php
<?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.

Example · php
<?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.

Example · php
<?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

  • Be the first to comment on this lesson.