Protone Media logo

Hey! Did you hear about Launcher? 🚀

It's an easy-to-use deployment tool to deploy your Laravel apps containerized with Docker. Launcher is remarkably easy, and still, you can fully customize it to your needs. Start launching your sites in just minutes using our free 14-day trial.

Blade, Requests, Routing, and Validation: New features since the Laravel 8.0 release in September 2020 (1/2)

Following last week's blog post about Jobs and Queues, here's an overview of new features and improvements when it comes to Blade, Requests, Routing and Validation.

I got most code examples and explanations from the PRs and official documentation.

Requests and Routing

v8.17.0 Added dd() and dump() to the request object (#35384)

Quickly inspect the request input.

public function index(Request $request)
{
    // before:
    dd($request->all());

    // after:
    $request->dd();

    $request->dd(['name', 'age']);

    $request->dd('name', 'age');
}

v8.26.0 Added Route::missing() (#36035)

Typically, a 404 HTTP response will be generated if an implicitly bound resource model is not found. With the missing method you may change this behavior:

Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
    ->name('locations.view')
    ->missing(fn($request) => Redirect::route('locations.index', null, 301));

v8.55.0 Added Support withTrashed on routes (#38348)

This allows you to specify a single route that allows soft deleted models when resolving implicit model bindings:

Route::post('/user/{user}', function (ImplicitBindingModel $user) {
    return $user;
})->middleware(['web'])->withTrashed();

v8.56.0 Added fullUrlWithoutQuery method to Request (#38482)

Get the full URL for the request without the given query string parameters.

// When the current URL is 
// https://example.com/?color=red&shape=square&size=small

request()->fullUrlWithoutQuery('color');
// https://example.com/?shape=square&size=small

request()->fullUrlWithoutQuery(['color', 'size']);
// https://example.com/?shape=square

Blade Templates

v8.19.0 Added Illuminate\View\ComponentAttributeBag::has() (#35562)

Allows to determine if a given attribute is present on a component.

@if ($attributes->has('class'))
    <div>Class Attribute Present</div>
@endif

v8.27.0 Conditionally merge classes into a Blade Component attribute bag (#36131)

Inspired by Vue's :class syntax, this PR adds a class() method to the ComponentAttributeBag class. It merges the given classes into the attribute bag.

<div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}>

As of v8.51, you can use the class directive as well:

<div @class(['p-4', 'bg-red' => $hasError])>

v8.45.0 Adds class handling for Blade echo statements (#37478)

This PR adds a new Blade::stringable() method that allows the user to add intercepting closures for any class. The returned value will be outputted in Blade.

// AppServiceProvider
Blade::stringable(Money::class, fn($object) => $object->formatTo('en_GB'));
Blade::stringable(Carbon::class, fn($object) => $object->format('d/m/Y')));
<dl>
    <dt>Total</dt>
    <dd>{{ $product->total }}</dd> <!-- This is a money object, but will be outputted as an en_GB formatted string -->
    <dt>Created at</dt>
    <dd>{{ $product->created_at }}</dd> <!-- This is a Carbon object, but will be outputted as English date format -->
</dl>

v8.64.0 Added @aware blade directive (#39100)

You may use the @aware directive to access data from a parent component inside a child component. For example, imagine a parent <x-menu> and child <x-menu.item>:

<x-menu color="purple">
    <x-menu.item>...</x-menu.item>
    <x-menu.item>...</x-menu.item>
</x-menu>

By using the @aware directive, you can make the color prop available inside as well:

<!-- /resources/views/components/menu/item.blade.php -->
@aware(['color' => 'gray'])

<li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}>
    {{ $slot }}
</li>

Validation

v8.32.0 Added prohibited_if and prohibited_unless validation rules (#36516)

The field under validation must be empty or not present if the anotherfield field is equal to any value.

Validator::validate([
    'is_deceased' => false,
    'date_of_death' => '2021-01-01'
], [
    'date_of_death' => 'prohibited_unless:is_deceased,true'
]);

v8.34.0 Added prohibited validation rule (#36667)

The field under validation must be empty or not present.

Validator::validate([
    'name' => 'hello-world',
    'key' => 'random-key',
], [
    'name' => 'required|max:255',
    'key' => 'prohibited',
]);

v8.39.0 Added password validation rule (#36960)

To ensure that passwords have an adequate level of complexity, you may use Laravel's Password rule object:

Validator::validate([
    'password' => '123123',
], [
    'password' => ['required', 'confirmed', Password::min(8)
        ->mixedCase()
        ->letters()
        ->numbers()
        ->symbols()
        ->uncompromised(),
    ],
]);

v8.47.0 Copy password rule to current_password (#37650)

To prevent communication problems with the new Password rule object, the password rule was renamed to current_password with the intention of removing it in Laravel 9.

v8.52.0 Added Unique::withoutTrashed() (#38124)

This PR adds a helper method to the unique validation rule for working with models which can be soft deleted.

// Before
Rule::unique('users')->whereNull('deleted_at');

// After
Rule::unique('users')->withoutTrashed();

v8.54.0 Added withoutTrashed on Exists rule (#38314)

In addition to the unique rule in the example above, you may also use the withoutTrashed method on the exists rule.

// Before
Rule::exists('users')->whereNull('deleted_at');

// After
Rule::exists('users')->withoutTrashed();

v8.53.0 Added accepted_if validation rule (#38210)

In addition to the accepted rule, you can now use this rule if another field under validation is equal to a specified value.

Validator::validate([
    'newsletter_subscription' => '1',
    'newsletter_terms' => '0',
], [
    'newsletter_subscription' => 'required|boolean',
    'newsletter_terms' => 'accepted_if:newsletter_subscription,1',
]);

v8.57.0 Added exclude validation rule (#38537)

The field under validation will be excluded from the request data returned by the validate and validated methods. There are exclude_if, exclude_unless, and exclude_without rules as well.

Validator::validate([
    'role' => 'guest',
    'email' => '[email protected]',
], [
    'role' => ['required', 'in:user,guest'],
    'email' => ['required_if:role,user', 'exclude_unless:role:user', 'email'],
]);

v8.58.0 Added prohibits validation (#38612)

If the field under validation is present, no fields in anotherfield can be present, even if empty.

Validator::validate([
    'email' => '[email protected]',
    'emails' => ['[email protected]', '[email protected]']
], [
    'email' => 'prohibits:emails'
]);

v8.55.0 Added Conditional rules (#38361)

You may use Rule::when() to create a new conditional rule set.

Validator::validate([
    'password' => '123456',
], [
    'password' => ['required', 'string', Rule::when(true, ['min:5', 'confirmed'])],
]);

v8.55.0 Added Validated subsets (#38366)

You may now retrieve a portion of the validated input data:

$validator->safe()->only(['name', 'email']);
$validator->safe()->except([...]);

This works on Form Requests as well:

$formRequest->safe()->only([...]);
$formRequest->safe()->except([...]);

Related posts

Want to stay up-to-date on Laravel news and packages?

Pascal Baljet on Twitter

Follow me on Twitter: @pascalbaljet

Pascal Baljet on Twitter

Subscribe to my YouTube channel

© 2013-2022 Protone Media B.V.