Laravel 12.8, weekly updates, and weekly tip

Laravel 12.8

Lots of releases last week, both for patches and I assume for Wayfinder. With a fast-follow patch release today, we jump all the way to Laravel 12.8.1.

  • Add whereAttachedTo() to query builder in #55245
  • Make Illuminate\Support\Uri macroable in #55260
  • Add Eloquent Resource helper functions to Model/Collections in #55107
  • Add createMany mass-assignment variants to HasOneOrMany in #55262
  • Add fromJson() to Collection in #55310
  • Introduce automatic eager loading in #53655
  • Introduce Rule::anyOf() for validating against multiple rules in #55191
  • Allow merging model attributes before insert via Model::fillAndInsert() in #55038
  • Add Http::failedRequest() in #55241
  • Add pathSegments() to Uri in #55250

You may review the full branch diff on GitHub for a complete list of changes.

This version bump and update is automated for subscribers to a Shifty Plan. If you don't have one of those, be sure to bump your constraint and run composer update to get the latest features.

Weekly Journal

Last week I worked mostly on some internal items for laravelshift.com. This culminated in a Twitter video series on Friday. I did this mostly as motivation to make a quick Workbench task.

It automates the conversion to the new #[Scope] attribute added in Laravel 12.5. It seems PHP attributes are gaining more traction within Laravel. Plus, I love to streamline code.

In addition, the Laravel 12.x Shift already automates adopting other PHP attributes in models. So I figured why not add this too.

All of these are available to run independently (for free) using the Shift Workbench. And, as noted, are included in both the Laravel 12.x Shift and Laravel Fixer.

Yesterday I spent a bit of time on WPPM. I haven't given this project much attention. But it does get occasional use. A few bug reports came across recently. So I took a minute to improve the exception handling.

This week I'm switching gears with the livestreams. I'll likely do a few on Blueprint. I want to ensure it's generating the latest Laravel code, such as using these new attributes. I'll also squash a few bugs.

Weekly Tip

I stumbled upon another testing gotcha. This relates to testing time. Specifically comparing the "frozen time" with an Eloquent model's datetime.

Here's an condensed example:

$package = Package::factory()->create();
$slug = $this->faker()->slug(2);
 
$now = now();
Carbon::setTestNow($now);
 
$package->slug = $slug;
$package->save();
 
$package->refresh();
$this->assertTrue($now->equalTo($package->updated_at));

The assertion will fail. The problem is the sub-second precision. The $now I created with Carbon has sub-second precision. $package->updated_at does not.

This is because the database is not storing with sub-second precision. So even though updated_at is initially set with our frozen time, when it is refreshed from the database the sub-seconds are 0.

Here's a dump of their values:

// $now: 2025-04-08 13:04:18.021521 UTC (+00:00)
// updated_at: 2025-04-08 13:04:18.0 UTC (+00:00)

As always, I'm thinking about a way to make this a bit smoother. Having Laravel's setTestNow automatically chop the sub-seconds might swing this gotcha the other direction. So it'd be a gotcha when you actually want to test sub-second precision.

So I'll probably end up throwing a little helper into jasonmccreary/laravel-test-assertions. Something that automatically creates a frozen time at the start of second and returns it.

Effectively condensing the following lines into one:

$now = now()->startOfSecond();
Carbon::setTestNow($now);

As always, I'm interested to know how you've worked around this…