#Blade @once — Render Something Exactly One Time
The problem. You have a component or partial that gets included many times on a page (say, a date-picker widget used in 12 places), but its supporting <script> or <style> block only needs to appear once. Naively, it gets dumped 12 times.
The fix. @once renders its contents only the first time it's hit during a request, no matter how many times that code runs.
1@once
2 @push('scripts')
3 <script src="/js/datepicker.js"></script>
4 @endpush
5@endonce
Include the widget 50 times; the script tag still shows up exactly once.
#Blade @class and @style — Conditional CSS Without the Mess
The problem. Building a class string based on conditions turns into ugly ternaries jammed inside the attribute: class="btn {{ $active ? 'btn-active' : '' }} {{ $disabled ? 'opacity-50' : '' }}".
The fix. @class takes an array where the value is a condition — the class is included only when its condition is true.
1<div @class([
2 'card',
3 'card-featured' => $post->is_featured,
4 'card-draft' => ! $post->published,
5 'opacity-50' => $post->archived,
6])>
@style does the same thing for inline styles.
#@aware — Let Child Components See a Parent's Data
The problem. You build a parent component like <x-menu color="blue"> and inside it are <x-menu.item> children that need to know the color. Passing color down to every single child by hand is tedious.
The fix. @aware lets a child component read a prop that was passed to its parent, without re-passing it.
1{{-- resources/views/components/menu/item.blade.php --}}
2@aware(['color' => 'gray'])
3
4<li class="text-{{ $color }}-600">
5 {{ $slot }}
6</li>
Now every <x-menu.item> automatically picks up the parent menu's color.
#Gate::before() — Global Authorization Overrides (Hello, Super-Admin)
The problem. You have dozens of permission checks scattered across the app, and you want an admin to bypass all of them. Editing every single policy to add "...unless they're an admin" is error-prone.
The fix. Gate::before() runs before every authorization check. Return true and the user is allowed through everything.
1Gate::before(function ($user, $ability) {
2 if ($user->isSuperAdmin()) {
3 return true; // skip all other checks
4 }
5 // return nothing → let the normal checks run
6});
There's a matching Gate::after() for granting access as a fallback after normal checks decline.
#Gate::allowIf() / denyIf() — Inline One-Off Checks
The problem. Sometimes you need a quick authorization check that doesn't justify a whole policy class.
The fix. Inline gate helpers for simple true/false cases.
1Gate::allowIf(fn ($user) => $user->id === $comment->user_id);
2// throws a 403 automatically if the condition is false
#Policy response() With a Message — Explain Why Access Was Denied
The problem. A plain 403 tells the user "no" but not "why." "You can't edit this because the deadline passed" is far more useful than a blank forbidden page.
The fix. Return a Response from your policy method with a custom message (and even a code).
1use Illuminate\Auth\Access\Response;
2
3public function update(User $user, Post $post): Response
4{
5 return $post->deadline->isFuture()
6 ? Response::allow()
7 : Response::deny('The editing deadline has passed.');
8}
That message surfaces in the thrown exception, so your error page can show something meaningful.
#config() With a Default and Runtime Overrides
The problem. Reading config is easy, but two things trip people up: what happens when a key is missing, and needing to tweak a config value at runtime (e.g. in a test).
The fix. config() takes a default as its second argument, and passing an array sets values.
1// Read with a fallback if the key doesn't exist
2$timeout = config('services.api.timeout', 30);
3
4// Set at runtime (great in tests or feature toggles)
5config(['services.api.timeout' => 5]);
#env() Only in Config — and App::environment() for Checks
The problem. People sprinkle env() throughout the app, then get burned when config caching (php artisan config:cache) makes those env() calls return null in production.
The fix. Rule: call env() only inside config/*.php files. Everywhere else, read from config(). To branch on environment, use App::environment() instead of checking env('APP_ENV').
1use Illuminate\Support\Facades\App;
2
3if (App::environment('local', 'staging')) {
4 // show debug toolbar, seed fake data, etc.
5}
6
7if (App::environment('production')) {
8 // real payment gateway
9}
#whenNotNull() / unless() on Requests and Builders
The problem. Conditional logic like "apply this filter only if the parameter was actually provided" leads to nested if blocks that break up otherwise clean chains.
The fix. unless() is the mirror of when() — it runs when the condition is false — and requests expose whenFilled() / whenHas() for exactly this.
1$query->unless($request->boolean('include_archived'), function ($q) {
2 $q->where('archived', false); // hide archived unless asked
3});
4
5$request->whenFilled('email', function ($email) {
6 // only runs if 'email' was present and non-empty
7});
#upsert() — Insert-or-Update Many Rows in One Query
The problem. You have a batch of rows and want to insert the new ones while updating any that already exist. Looping with updateOrCreate() fires one or two queries per row — brutal for large batches.
The fix. upsert() does the whole batch in a single query.
1Product::upsert(
2 [
3 ['sku' => 'A1', 'price' => 100, 'stock' => 5],
4 ['sku' => 'A2', 'price' => 200, 'stock' => 3],
5 ],
6 ['sku'], // column(s) that identify a duplicate
7 ['price', 'stock'] // columns to update if it already exists
8);
One round-trip to the database instead of hundreds.
#lazyById() for Memory-Safe Iteration With Modification
The problem. In Part 2 we met cursor() for low-memory iteration and chunkById() for safe modification during iteration. What if you want both — stream a huge table one row at a time and modify as you go?
The fix. lazyById() gives you a LazyCollection that paginates by primary key under the hood.
1User::where('active', false)
2 ->lazyById(200)
3 ->each(fn ($user) => $user->delete());
Low memory footprint, and no skipped rows even though you're deleting.
#withExists() — Check Existence Without Loading the Relation
The problem. You want to know whether each post has any comments, but you don't need the comments themselves. Loading them all just to check is wasteful; withCount() counts them all when you only care about "any or none."
The fix. withExists() adds a lightweight boolean flag.
1$posts = Post::withExists('comments')->get();
2
3foreach ($posts as $post) {
4 if ($post->comments_exists) { // true / false
5 // ...
6 }
7}
#Wrap-Up
The standouts this round: @class and @once clean up real Blade pain you hit daily, Gate::before() is the clean way to do super-admin, policy Response::deny() turns useless 403s into helpful messages, and upsert() replaces slow per-row loops with a single query. And if you took the env()-only-in-config rule to heart, you've dodged one of the most common "it works locally but breaks in production" bugs there is.