The New Era of Laravel Upgrades Laravel 13 introduces a seismic change in how developers maintain their codebases with the arrival of Laravel Boost. This AI-driven tool promises a hands-off upgrade path directly from the terminal. However, the venerable Laravel Shift remains the community standard for automated migrations. Choosing between them isn't just about speed; it's about the technical philosophy you want to apply to your project's evolution. Laravel Boost: The Speed of Compatibility The core Laravel team designed Boost for efficiency. By running a simple AI skill command, it handles the heavy lifting of dependency management and fundamental breaking changes. In practice, Boost identifies the bare minimum required to make your application functional on the new version. It updates the `composer.json` for core framework components, adjusts CSRF middleware names, and updates config cache settings. It then validates these changes with a test suite. It's a quick, pragmatic approach, but it often leaves the deeper, more cosmetic or structural improvements of the skeleton untouched. Laravel Shift: The Deterministic Deep Clean Shift takes a different path by focusing on a "native-first" philosophy. It doesn't just make your code work; it makes it look like it was born in Laravel 13. This service performs dozens of micro-tasks, such as introducing new PHP attributes for Eloquent, indexing expiration columns in cache tables, and cleaning up factory definitions. It even bumps minor frontend dependencies and first-party packages that Boost overlooks. Because Shift uses a deterministic engine rather than probabilistic AI, it delivers a consistent, albeit opinionated, result every time. Critical Analysis: Trade-offs and Pain Points Boost wins on convenience but lacks thoroughness. It might miss PHP 8.3 version bumps or secondary package updates. Shift, while comprehensive, can feel intrusive. It occasionally forces specific code styles or PHP attributes that might not align with your team's internal standards. Reviewing a Shift PR requires a discerning eye to revert unwanted stylistic changes. The Final Verdict Use Boost for small, internal projects where speed is king and technical debt is low. For production-grade applications, Laravel Shift remains essential. It ensures your skeleton stays modern and identifies obscure changes buried deep in the framework's release notes. Shift isn't just an upgrader; it's a comprehensive code reviewer.
Jason McCreary
People
Laravel (5 mentions) features his technical methodology in "Rapid Laravel Development with Blueprint" while Laravel Daily (1 mention) compares his flagship tool against competitors in "I Tried Laravel 13 Upgrade With Boost /upgrade vs Laravel Shift."
- Mar 23, 2026
- Jan 24, 2026
- Aug 27, 2025
- Oct 29, 2024
- Aug 13, 2024
Beyond the Vocabulary: Understanding Test Doubles Testing often feels like a steep mountain to climb because of the dense academic language surrounding it. Jason McCreary simplifies this by breaking down the five essential types of test doubles defined by Martin Fowler. Understanding these is the first step toward writing cleaner tests in Laravel. * **Dummies**: These are placeholders. You pass them into functions to satisfy parameter lists, but you never actually use their values. * **Fakes**: These have real working implementations but take shortcuts. A classic example is using an in-memory database instead of a full MySQL instance. * **Stubs**: These provide "canned answers." They respond to specific calls with pre-defined data but don't care about anything else. * **Spies**: Think of these as stubs that take notes. They record what happened so you can verify it later. * **Mocks**: The strictest form. They are pre-programmed with expectations and will actively throw an exception if they receive a call they didn't expect. The Power of Laravel Facade Fakes For years, Laravel facades faced criticism for being "untestable" because of their static nature. This hasn't been true for a decade. Laravel provides built-in fake implementations for almost every major service, including Mail, Bus, and Event. When you call `Mail::fake()`, you aren't just ignoring emails. You are swapping the real mailer in the service container with a `MailFake` instance. This fake records every mailable sent, allowing you to make powerful assertions without actually hitting an SMTP server. ```php public function test_post_store_sends_welcome_email() { Mail::fake(); // Perform the action $this->post('/posts', ['title' => 'New Post']); // Assert the mailable was sent to the right person Mail::assertQueued(NewPostMailable::class, function ($mail) { return $mail->hasTo('[email protected]'); }); } ``` Preventing the "Stray Request" Foot-Gun One of the most dangerous aspects of testing is the "stray request." This happens when your test accidentally hits a real production API or sends a real email because you forgot to fake a specific service. Jason McCreary highlights a brilliant feature in the HTTP client: `preventStrayRequests()`. By adding `Http::preventStrayRequests()` to your base test case's `setUp` method, the framework will throw an exception the moment any code attempts to make an external request that hasn't been explicitly faked. This turns your fake into a mock, providing a "tracer bullet" that illuminates hidden dependencies in your code. It’s a best practice that ensures your tests stay fast, deterministic, and isolated from the outside world. Advanced Techniques: Real-Time Facades and Mockery Sometimes you need to test a custom service class that doesn't have a built-in Laravel fake. You have two primary paths: traditional dependency injection mocking or the "real-time facade." Using the Mock Helper Laravel's `mock()` helper streamlines the process of creating a Mockery object and binding it into the container. It’s much cleaner than manual Mockery syntax. ```php $this->mock(LanguageAI::class, function ($mock) { $mock->shouldReceive('analyze')->once()->andReturn(true); }); ``` The Real-Time Facade Magic If you prefer the clean, static syntax of facades but don't want to create a dedicated Facade class, you can use a real-time facade. By simply prefixing your import with `Facades\`, Laravel generates a facade on the fly. ```php use Facades\App\Services\LanguageAI; // In your code or test: LanguageAI::expects('analyze') ->with('post body') ->andReturn(true); ``` Critical Distinction: ShouldReceive vs. Expects A common mistake is using `shouldReceive()` when you actually mean `expects()`. The difference is vital for test integrity. * `shouldReceive()` is permissive. If the method is never called, the test still passes. This leads to "false confidence"—you think you're testing a feature that isn't actually running. * `expects()` is strict. It acts as a true mock. If the method isn't called exactly as specified, the test fails. Always lean toward `expects()` to ensure your code is actually executing the logic you intend to verify. Being strict in your tests leads to total confidence in your production deployments.
Jul 27, 2023