⬆️ Go to main menu ⬅️ Previous (Migrations) ➡️ Next (Routing)
- $loop variable in foreach
- You can use Blade to generate more than HTML
- Short attribute syntax for Blade Components
- Does view file exist?
- Error code Blade pages
- View without controllers
- Blade @auth
- Two-level $loop variable in Blade
- Create Your Own Blade Directive
- Blade Directives: IncludeIf, IncludeWhen, IncludeFirst
- Use Laravel Blade-X variable binding to save even more space
- Blade components props
- Blade Autocomplete typehint
- Component Syntax Tip
- Automatically highlight nav links
- Cleanup loops
- Simple way to tidy up your Blade views
- Checked blade directive
- Selected blade directive
Inside of foreach loop, check if current entry is first/last by just using $loop
variable.
@foreach ($users as $user)
@if ($loop->first)
This is the first iteration.
@endif
@if ($loop->last)
This is the last iteration.
@endif
<p>This is user {{ $user->id }}</p>
@endforeach
There are also other properties like $loop->iteration
or $loop->count
.
Learn more on the official documentation.
You can use it to generate any dynamic string or file you want. For example, a shell script or a sitemap file.
You only need to call the render()
method on a view to get the result as a string.
$script = view('deploy-script')->render();
$ssh = $this->createSshConnection();
info("Executing deploy script...");
$process = $ssh->execute(explode("\n", $script));
Tip given by @cosmeescobedo
Available from Laravel 9.32.
Current syntax:
<x-profile :user-id="$userId"></x-profile>
Short syntax:
<x-profile :$userId></x-profile>
You can check if View file exists before actually loading it.
if (view()->exists('custom.page')) {
// Load the view
}
You can even load an array of views and only the first existing will be actually loaded.
return view()->first(['custom.dashboard', 'dashboard'], $data);
If you want to create a specific error page for some HTTP code, like 500 - just create a blade file with this code as filename, in resources/views/errors/500.blade.php
, or 403.blade.php
etc, and it will automatically be loaded in case of that error code.
If you want route to just show a certain view, don't create a Controller method, just use Route::view()
function.
// Instead of this
Route::get('about', 'TextsController@about');
// And this
class TextsController extends Controller
{
public function about()
{
return view('texts.about');
}
}
// Do this
Route::view('about', 'texts.about');
Instead of if-statement to check logged in user, use @auth
directive.
Typical way:
@if(auth()->user())
// The user is authenticated.
@endif
Shorter:
@auth
// The user is authenticated.
@endauth
The opposite is @guest
directive:
@guest
// The user is not authenticated.
@endguest
In Blade's foreach you can use $loop variable even in two-level loop to reach parent variable.
@foreach ($users as $user)
@foreach ($user->posts as $post)
@if ($loop->parent->first)
This is first iteration of the parent loop.
@endif
@endforeach
@endforeach
It’s very easy - just add your own method in app/Providers/AppServiceProvider.php
. For example, if you want to have this for replace <br>
tags with new lines:
<textarea>@br2nl($post->post_text)</textarea>
Add this directive to AppServiceProvider’s boot()
method:
public function boot()
{
Blade::directive('br2nl', function ($string) {
return "<?php echo preg_replace('/\<br(\s*)?\/?\>/i', \"\n\", $string); ?>";
});
}
If you are not sure whether your Blade partial file actually would exist, you may use these condition commands:
This will load header only if Blade file exists
@includeIf('partials.header')
This will load header only for user with role_id 1
@includeWhen(auth()->user()->role_id == 1, 'partials.header')
This will try to load adminlte.header, if missing - will load default.header
@includeFirst('adminlte.header', 'default.header')
// Using include, the old way
@include("components.post", ["title" => $post->title])
// Using Blade-X
<x-post link="{{ $post->title }}" />
// Using Blade-X variable binding
<x-post :link="$post->title" />
Tip given by @anwar_nairi
// button.blade.php
@props(['rounded' => false])
<button {{ $attributes->class([
'bg-red-100 text-red-800',
'rounded' => $rounded
]) }}>
{{ $slot }}
</button>
// view.blade.php
// Non-rounded:
<x-button>Submit</x-button>
// Rounded:
<x-button rounded>Submit</x-button>
Tip given by @godismyjudge95
@php
/* @var App\Models\User $user */
@endphp
<div>
// your ide will typehint the property for you
{{$user->email}}
</div>
Tip given by @freekmurze
Did you know that if you pass colon (:) before the component parameter, you can directly pass variables without print statement {{ }}
?
<x-navbar title="{{ $title }}"/>
// you can do instead
<x-navbar :title="$title"/>
Tip given by @sky_0xs
Automatically highlight nav links when exact URL matches, or pass a path or route name pattern.
A Blade component with request and CSS classes helpers makes it ridiculously simple to show active/inactive state.
class NavLink extends Component
{
public function __construct($href, $active = null)
{
$this->href = $href;
$this->active = $active ?? $href;
}
public function render(): View
{
$classes = ['font-medium', 'py-2', 'text-primary' => $this->isActive()];
return view('components.nav-link', [
'class' => Arr::toCssClasses($classes);
]);
}
protected function isActive(): bool
{
if (is_bool($this->active)) {
return $this->active;
}
if (request()->is($this->active)) {
return true;
}
if (request()->fullUrlIs($this->active)) {
return true;
}
return request()->routeIs($this->active);
}
}
<a href="{{ $href }}" {{ $attributes->class($class) }}>
{{ $slot }}
</a>
<x-nav-link :href="route('projects.index')">Projects</x-nav-link>
<x-nav-link :href="route('projects.index')" active="projects.*">Projects</x-nav-link>
<x-nav-link :href="route('projects.index')" active="projects/*">Projects</x-nav-link>
<x-nav-link :href="route('projects.index')" :active="$tab = 'projects'">Projects</x-nav-link>
Tip given by @mpskovvang
Did you know the Blade @each
directive can help cleanup loops in your templates?
// good
@foreach($item in $items)
<div>
<p>Name: {{ $item->name }}
<p>Price: {{ $item->price }}
</div>
@endforeach
// better (HTML extracted into partial)
@each('partials.item', $items, 'item')
Tip given by @kirschbaum_dev
A simple way to tidy up your Blade views!
Use the forelse loop
, instead of a foreach loop
nested in an if statement
<!-- if/loop combination -->
@if ($orders->count())
@foreach($orders as $order)
<div>
{{ $order->id }}
</div>
@endforeach
@else
<p>You haven't placed any orders yet.</p>
@endif
<!-- Forelse alternative -->
@forelse($orders as $order)
<div>
{{ $order->id }}
</div>
@empty
<p>You haven't placed any orders yet.</p>
@endforelse
Tip given by @alexjgarrett
In Laravel 9, you'll be able to use the cool new "checked" Blade directive.
This is going to be a nice addition that we can use to clean up our Blade views a little bit
// Before Laravel 9:
<input type="radio" name="active" value="1" {{ old('active', $user->active) ? 'checked' : '' }}/>
<input type="radio" name="active" value="0" {{ old('active', $user->active) ? '' : 'checked' }}/>
// Laravel 9
<input type="radio" name="active" value="1" @checked(old('active', $user->active))/>
<input type="radio" name="active" value="0" @checked(!old('active', $user->active))/>
Tip given by @AshAllenDesign
In Laravel 9, you'll be able to use the cool new "selected" Blade directive for HTML select elements.
This is going to be a nice addition that we can use to clean up our Blade views a little bit
// Before Laravel 9:
<select name="country">
<option value="India" {{ old('country') ?? $country == 'India' ? 'selected' : '' }}>India</option>
<option value="Pakistan" {{ old('country') ?? $country == 'Pakistan' ? 'selected' : '' }}>Pakistan</option>
</select>
// Laravel 9
<select name="country">
<option value="India" @selected(old('country') ?? $country == 'India')>India</option>
<option value="Pakistan" @selected(old('country') ?? $country == 'Pakistan')>Pakistan</option>
</select>
Tip given by @VijayGoswami