4,000 emails/month for free | Mailtrap sends real emails now!

Laravel 9.18 Released

Published on by

Laravel 9.18 Released image

Never Miss a Laravel Release 🚀

Sign up and get an email with each new Laravel release

The Laravel team released 9.18 jam-packed with amazing features and quality-of-life improvements. Let's look at the high-level details of the standout features now available in Laravel 9!

Improve file attachments for mail and notifications

Tim MacDonald contributed attachable objects, which you can use to implement attachments with models:

namespace App\Models;
 
use Illuminate\Contracts\Mail\Attachable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Mail\Attachment;
 
class Photo extends Model implements Attachable
{
/**
* Get the attachable representation of the model.
*
* @return \Illuminate\Mail\Attachment
*/
public function toMailAttachment()
{
return Attachment::fromPath('/path/to/file');
}
}

When building an email message, you can pass an instance of the model via the attach() method:

public function build()
{
return $this->view('photos.resized')
->attach($this->photo);
}

See the new attachable objects documentation for complete details on this beneficial feature!

Invokable validation classes

Tim MacDonald contributed invokable validation classes:

This PR aims to introduce a new class based validation implementation that mixes the brevity + simplicity of Closure based rules with the shareable, extendable, and chainable nature of class based rules by introducing an Invokable validation rule.

Here's an example implementation from Pull Request #42689:

class InvokableQuantity implements InvokableRule
{
public function __invoke($attribute, $value, $fail)
{
if (! is_array($value)) {
return $fail('validation.quantity.must_be_an_object')->translate();
}
 
if (! array_key_exists('magnitude', $value)) {
$fail('validation.quantity.missing_magnitude')->translate();
}
 
if (! array_key_exists('units', $value)) {
$fail('validation.quantity.missing_units')->translate();
}
}
}

Predis 2.0

Dries Vints contributed support for Predis 2.0. Predis 2.0.0 is a maintenance release, so nothing should break.

Define nested "with" relations via a nested array

Tim MacDonald contributed a way to define nested eager loading relationships via a nested array:

// Using dot notation
$books = Book::with('author.contacts')->get();
 
// Nested array
$books = Book::with([
'author' => [
'contacts',
'publisher',
],
])->get();

Add host methods to the Illuminate Request object

Pull Request #42797 provides three convenience methods on the Illuminate Request instance to access underlying Symphony methods:

$request->host(); // getHost()
$request->httpHost(); // getHttpHost()
$request->schemeAndHttpHost(); // getSchemeAndHttpHost()

Invokable validation rules can push messages to nested attributes

Tim MacDonald contributed the ability for invokable validation rules to push errors to nested and other attributes:

class UserRule implements InvokableRule
{
public function __invoke($attribute, $value, $fail)
{
if (! is_array($attribute) || array_is_list($attribute)) {
return $fail('Must be an object.'); // apply to $attribute
}
 
if (! array_key_exists('name', $attribute)) {
return $fail("{$attribute}.name", 'Is required.'); // apply to nested attribute
}
 
/* ... */
}
}

Given the above implementation, here's a usage example:

Validator::make(
[
'user_1' => ['xxxx'],
'user_2' => ['age' => 23],
],
[
'user_1' => [new UserRule()],
'user_2' => [new UserRule()],
]
);
 
// errors...
[
'user_1' => ['Must be an object.'],
'user_2.name' => ['Is required.'],
]

Introduce fake() helper

Tim MacDonald contributed a global fake() helper function that allows you to easily access a singleton faker instance. Using this helper is helpful when prototyping, testing, and generating factory and seed data:

@for($i = 0; $i < 10; $i++)
<dl>
<dt>Name</dt>
<dd>{{ fake()->name() }}</dd>
 
<dt>Phone</dt>
<dd>{{ fake()->phoneNumber() }}</dd>
 
</dl>
@endfor

Here's an example of locale-specific faker usage:

fake()->name() // config('app.faker_locale') ?? 'en_US'
fake('en_AU')->name() // en_AU

Cumulative query duration limit callback

Tim MacDonald contributed a callback handler after a cumulative query limit duration:

DB::handleExceedingCumulativeQueryDuration(Interval::seconds(5), function (Connection $connection) {
Log::warning("Database queries exceeded 5 seconds on {$connection->getName()}");
});

To learn more about this feature, check out the official documentation for cumulative query time. Also, check out Pull Request #42744 for implementation details and discussion around this feature.

Release Notes

You can see the complete list of new features and updates below and the diff between 9.17.0 and 9.18.0 on GitHub. The following release notes are directly from the changelog:

v9.18.0

Added

  • Improve file attachment for mail and notifications (#42563)
  • Introduce Invokable validation classes (#42689)
  • Predis v2.0 (#42577)
  • Added Illuminate/View/Compilers/Concerns/CompilesConditionals::compileReadonly() (#42717)
  • Apply where's from union query builder in cursor pagination (#42651)
  • Added ability to define "with" relations as a nested array (#42690)
  • Added ability to set backoff in broadcast events (#42737)
  • Added host(), httpHost(), schemeAndHttpHost() to Request (#42797)
  • Allow invokable rules to push messages to nested (or other) attributes (#42801)
  • Adds compilePushIf and compileEndpushIf functions to View compiler (#42762)
  • Added: Allow removing token during tests (#42841)
  • Added predefined_constants to reservedNames array in Illuminate/Console/GeneratorCommand (#42832)
  • Handle collection creation around a single enum (#42839)
  • Allow for nullable morphs in whereNotMorphedT (#42878)
  • Introduce a fake() helper to resolve faker singletons, per locale (#42844)
  • Allow handling cumulative query duration limit per DB connection (#42744)
  • Add invokable option to make rule command (#42742)

Fixed

  • Fix deprecation error in the route:list command (#42704)
  • Fixed Request offsetExists without routeResolver (#42754)
  • Fixed: Loose comparison causes the value not to be saved (#42793)
  • Fixed: Fix database session driver keeps resetting CSRF token (#42782)
  • Fixed: Arr::map - Fix map-by-reference w/ built-ins (#42815)
  • Fixed league/flysystem suggest (#42872)

Changed

  • Start session in TestResponse to allow marshalling of error bag from JSON (#42710)
  • Rename methods in Illuminate/Broadcasting/BroadcastManager (753e9fd)
  • Avoid throwing on invalid mime-type in Illuminate/Filesystem/FilesystemAdapter::mimeType() (#42761)
  • Do not resolve already set headers in Illuminate/Filesystem/FilesystemAdapter (#42760)
  • Standardise invokable rule translation functionality (#42873)
  • Clear cast cache when setting attributes using arrow (#42852)
Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
Curotec

Curotec helps software teams hire the best Laravel developers in Latin America. Click for rates and to learn more about how it works.

Visit Curotec
Curotec logo

Curotec

World class Laravel experts with GenAI dev skills. LATAM-based, embedded engineers that ship fast, communicate clearly, and elevate your product. No bloat, no BS.

Curotec
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $3200/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
Cut PHP Code Review Time & Bugs into Half with CodeRabbit logo

Cut PHP Code Review Time & Bugs into Half with CodeRabbit

CodeRabbit is an AI-powered code review tool that specializes in PHP and Laravel, running PHPStan and offering automated PR analysis, security checks, and custom review features while remaining free for open-source projects.

Cut PHP Code Review Time & Bugs into Half with CodeRabbit
Get expert guidance in a few days with a Laravel code review logo

Get expert guidance in a few days with a Laravel code review

Expert code review! Get clear, practical feedback from two Laravel devs with 10+ years of experience helping teams build better apps.

Get expert guidance in a few days with a Laravel code review
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Harpoon: Next generation time tracking and invoicing logo

Harpoon: Next generation time tracking and invoicing

The next generation time-tracking and billing software that helps your agency plan and forecast a profitable future.

Harpoon: Next generation time tracking and invoicing
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit

The latest

View all →
Laravel Altitude - Opinionated Claude Code agents and commands for TALL stack development image

Laravel Altitude - Opinionated Claude Code agents and commands for TALL stack development

Read article
JSON:API Resource in Laravel 12.45 image

JSON:API Resource in Laravel 12.45

Read article
Caching With MongoDB for Faster Laravel Apps image

Caching With MongoDB for Faster Laravel Apps

Read article
Laravel 12.44 Adds HTTP Client afterResponse() Callbacks image

Laravel 12.44 Adds HTTP Client afterResponse() Callbacks

Read article
Handle Nested Data Structures in PHP with the Data Block Package image

Handle Nested Data Structures in PHP with the Data Block Package

Read article
Detect and Clean Up Unchanged Vendor Files with Laravel Vendor Cleanup image

Detect and Clean Up Unchanged Vendor Files with Laravel Vendor Cleanup

Read article