Laravel 12: Typed Config, Slim Skeleton &amp; Upgrade | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. Laravel New in 12: First-Class Typed Config, Slim Skeletons, and Upgrade Notes

 Laravel New in 12: First-Class Typed Config, Slim Skeletons, and Upgrade Notes
===============================================================================

 Laravel 12 ships with typed configuration objects, a leaner application skeleton, and several quality-of-life improvements. This article walks through the practical impact on real codebases.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 9 Jul 2026 · Updated 9 Jul 2026 · 3 min read

ShareCopy linkCopied

 ![Laravel New in 12: First-Class Typed Config, Slim Skeletons, and Upgrade Notes](https://cdn.msaied.com/401/bd0219f2cb584b037df76f985db348f8.png) 

  On this page +1. [What Actually Changed in Laravel 12](#what-actually-changed-in-laravel-12)
2. [Typed Configuration Objects](#typed-configuration-objects)
3. [Testing Becomes Trivial](#testing-becomes-trivial)
4. [The Slimmer Skeleton](#the-slimmer-skeleton)
5. [Collection and Helper Additions](#collection-and-helper-additions)
6. [collect()-&gt;intersectAssoc()](#codecollect-gtintersectassoccode)
7. [Str::chopStart() / Str::chopEnd()](#codestrchopstartcode-codestrchopendcode)
8. [Upgrade Notes Worth Acting On](#upgrade-notes-worth-acting-on)
9. [Key Takeaways](#key-takeaways)

 What Actually Changed in Laravel 12
-----------------------------------

Laravel 12 is a focused release rather than a sweeping rewrite. The headline additions are **typed configuration objects**, a significantly slimmer default application skeleton, and a handful of helper and collection improvements. If you are running Laravel 11 on PHP 8.2+, the upgrade path is straightforward — but a few structural decisions deserve deliberate attention.

---

Typed Configuration Objects
---------------------------

The most architecturally interesting addition is first-class support for binding typed config objects into the service container. Instead of scattering `config('services.stripe.key')` calls throughout your codebase, you can now define a plain PHP object and register it once.

```php
// app/Config/StripeConfig.php
readonly class StripeConfig
{
    public function __construct(
        public string $key,
        public string $webhookSecret,
        public bool $testMode,
    ) {}
}

```

```php
// AppServiceProvider::register()
$this->app->singleton(StripeConfig::class, fn () => new StripeConfig(
    key: config('services.stripe.key'),
    webhookSecret: config('services.stripe.webhook_secret'),
    testMode: (bool) config('services.stripe.test_mode', false),
));

```

Now any class that type-hints `StripeConfig` receives a fully resolved, IDE-friendly object — no more string-keyed lookups, no more silent `null` surprises when a key is missing.

### Testing Becomes Trivial

```php
it('charges the card in test mode', function () {
    $this->app->instance(StripeConfig::class, new StripeConfig(
        key: 'sk_test_fake',
        webhookSecret: 'whsec_fake',
        testMode: true,
    ));

    // act and assert...
});

```

No more `Config::set()` scattered across test files.

---

The Slimmer Skeleton
--------------------

Laravel 12 ships with far fewer stub files in a fresh `laravel new` project. Several files that previously lived in `app/Http/Middleware/` are now consolidated or removed entirely, with their logic folded into the framework itself.

**What is gone from the default skeleton:**

- `TrimStrings`, `ConvertEmptyStringsToNull`, and `PreventRequestsDuringMaintenance` middleware stubs — they still run, but you no longer own copies unless you publish them.
- The `app/Http/Kernel.php` file is absent; middleware registration lives in `bootstrap/app.php` (introduced in Laravel 11, now the only way).

If your upgrade path involves a legacy `Kernel.php`, the migration is mechanical:

```php
// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->append(\App\Http\Middleware\MyCustomMiddleware::class);
        $middleware->remove(\Illuminate\Http\Middleware\TrimStrings::class);
    })
    ->create();

```

---

Collection and Helper Additions
-------------------------------

### `collect()->intersectAssoc()`

A long-requested method that compares both keys and values:

```php
$a = collect(['color' => 'red', 'size' => 'M']);
$b = collect(['color' => 'red', 'size' => 'L']);

$a->intersectAssoc($b); // ['color' => 'red']

```

### `Str::chopStart()` / `Str::chopEnd()`

Clean alternatives to `ltrim`/`rtrim` for specific substrings:

```php
Str::chopStart('/api/v1/users', '/api'); // '/v1/users'
Str::chopEnd('report.csv.tmp', '.tmp'); // 'report.csv'

```

---

Upgrade Notes Worth Acting On
-----------------------------

1. **PHP minimum is 8.2.** Drop any `7.x`/`8.0`/`8.1` compatibility shims.
2. **`Model::preventLazyLoading()` is on by default in `local`.** Audit your resources and Nova/Filament panels for N+1s before upgrading.
3. **`assertJsonPath` now validates strict types.** Tests that previously passed with loose comparisons may fail — fix the assertions, not the strictness.
4. **Vite 6 is the default.** If you pinned `vite` in `package.json`, bump it and review your `vite.config.js` for deprecated plugin options.

---

Key Takeaways
-------------

- Typed config objects eliminate string-keyed `config()` calls and make test overrides explicit.
- The slimmer skeleton reduces noise; understand which middleware moved into the framework before upgrading.
- `Str::chopStart/chopEnd` and `intersectAssoc` are small but immediately useful.
- `preventLazyLoading` being on by default in local is a gift — let it surface your N+1s now.
- The upgrade from Laravel 11 is low-risk if you already adopted `bootstrap/app.php` middleware registration.

- [laravel](https://www.msaied.com/public/articles?search=laravel)
- [laravel-12](https://www.msaied.com/public/articles?search=laravel-12)
- [php](https://www.msaied.com/public/articles?search=php)
- [upgrade](https://www.msaied.com/public/articles?search=upgrade)

 Frequently asked questions 
---------------------------

  Is Laravel 12 a long-term support release?No. Laravel 12 follows the standard release cycle with 18 months of bug fixes and 2 years of security fixes. Only even-numbered releases on the LTS cadence (like Laravel 6 and 9) have received extended support historically, though the project has moved away from formal LTS designations.

   Do typed config objects replace the config() helper entirely?No. The config() helper still works and is appropriate for simple lookups. Typed config objects shine when multiple classes share the same configuration group, when you want IDE autocompletion, or when you need clean test overrides via app()-&gt;instance().

   Will my existing Laravel 11 app break if lazy loading prevention is now on by default?Only in the local environment, and only if you have genuine N+1 relationships being accessed without eager loading. It will throw a LazyLoadingViolationException. Fix the underlying queries with with() calls rather than disabling the guard.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleLaravel API Resources: Sparse Fieldsets, Conditional Relationships, and Versioning](https://www.msaied.com/public/articles/laravel-api-resources-sparse-fieldsets-conditional-relationships-and-versioning-1) [Next articleLaravel 13: New Features, Helpers, and Practical Upgrade Notes](https://www.msaied.com/public/articles/laravel-13-new-features-helpers-and-practical-upgrade-notes-1)  

   On this page
-------------

1. [What Actually Changed in Laravel 12](#what-actually-changed-in-laravel-12)
2. [Typed Configuration Objects](#typed-configuration-objects)
3. [Testing Becomes Trivial](#testing-becomes-trivial)
4. [The Slimmer Skeleton](#the-slimmer-skeleton)
5. [Collection and Helper Additions](#collection-and-helper-additions)
6. [collect()-&gt;intersectAssoc()](#codecollect-gtintersectassoccode)
7. [Str::chopStart() / Str::chopEnd()](#codestrchopstartcode-codestrchopendcode)
8. [Upgrade Notes Worth Acting On](#upgrade-notes-worth-acting-on)
9. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
