Laravel 13: Features, Helpers &amp; Upgrade Notes | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://msaied.com) - [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [About](https://msaied.com#about)

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

Menu
----

Close 

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

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

 1. [Home](https://msaied.com)
2. /
3. [Articles](https://msaied.com/articles)
4. /
5. Laravel 13: New Features, Helpers, and Upgrade Notes

 Laravel 13: New Features, Helpers, and Upgrade Notes
=====================================================

 Laravel 13 ships with async-first primitives, a leaner application skeleton, and several quality-of-life helpers. Here is what changed, why it matters, and how to upgrade without surprises.

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

ShareCopy linkCopied

 ![Laravel 13: New Features, Helpers, and Upgrade Notes](https://cdn.msaied.com/736/98f6737af2ba4cdcc7400bc7fcab2439.png) 

  On this page +1. [Laravel 13: What Actually Changed and Why It Matters](#laravel-13-what-actually-changed-and-why-it-matters)
2. [Leaner Application Skeleton](#leaner-application-skeleton)
3. [Typed Configuration via config() Return Types](#typed-configuration-via-codeconfigcode-return-types)
4. [Str::password() and Str::ulid() Improvements](#codestrpasswordcode-and-codestrulidcode-improvements)
5. [Fluent Uri Value Object](#fluent-codeuricode-value-object)
6. [Queue withoutDelay() and onceWithoutOverlapping() Improvements](#queue-codewithoutdelaycode-and-codeoncewithoutoverlappingcode-improvements)
7. [Upgrade Path](#upgrade-path)
8. [Key Takeaways](#key-takeaways)

 Laravel 13: What Actually Changed and Why It Matters
----------------------------------------------------

Laravel 13 continues the framework's push toward expressive, type-safe, async-capable PHP. Rather than cataloguing every merged PR, this article focuses on the changes that affect day-to-day application architecture.

---

Leaner Application Skeleton
---------------------------

The default `app/` directory ships without `Http/Kernel.php` and `Console/Kernel.php`. Both were deprecated in Laravel 12 and are now fully removed. Middleware registration, scheduling, and bootstrapping all live in `bootstrap/app.php`.

```php
// bootstrap/app.php — the single source of truth
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->web(append: [\App\Http\Middleware\HandleInertiaRequests::class]);
        $middleware->throttleApi('60,1');
    })
    ->withExceptions(function (Exceptions $exceptions) {
        $exceptions->render(fn (PaymentException $e, Request $r) =>
            response()->json(['error' => $e->getMessage()], 402)
        );
    })
    ->create();

```

If you are upgrading from Laravel 11 or earlier, keep your kernel classes until you migrate their logic into `bootstrap/app.php`, then delete them.

---

Typed Configuration via `config()` Return Types
-----------------------------------------------

Laravel 13 ships a `Config::typed()` helper (and the `config_typed()` global) that returns a value cast to a specific type, throwing `\InvalidArgumentException` on mismatch rather than silently returning `null`.

```php
// Throws if the value is not a string
$dsn = Config::typed('services.redis.dsn', 'string');

// Works with enums too
$env = Config::typed('app.env', AppEnvironment::class);

```

This pairs well with readonly DTOs and eliminates defensive `(string)` casts scattered across service constructors.

---

`Str::password()` and `Str::ulid()` Improvements
------------------------------------------------

`Str::password()` now accepts a `symbols` parameter so you can restrict the character set for systems with legacy password rules:

```php
$password = Str::password(length: 20, symbols: '!@#$');

```

`Str::ulid()` gains an optional `Carbon` seed, making time-ordered IDs deterministic in tests:

```php
$ulid = Str::ulid(now()->setTimestamp(1_700_000_000));

```

---

Fluent `Uri` Value Object
-------------------------

The new `Uri` class (backed by `League\Uri`) replaces ad-hoc string manipulation:

```php
use Illuminate\Support\Uri;

$uri = Uri::of('https://api.example.com/v1/users')
    ->withQuery(['page' => 2, 'per_page' => 50])
    ->withPath('/v2/users');

// https://api.example.com/v2/users?page=2&per_page=50
echo $uri;

```

This is immutable — each `with*` call returns a new instance — making it safe to share a base URI across multiple request builders.

---

Queue `withoutDelay()` and `onceWithoutOverlapping()` Improvements
------------------------------------------------------------------

Job middleware received two quality-of-life additions:

```php
// Skip the configured delay when dispatching from a test
MyJob::dispatch()->withoutDelay();

// Named overlap key with automatic expiry on failure
class ProcessReport implements ShouldQueue
{
    use Dispatchable;

    public function middleware(): array
    {
        return [
            (new WithoutOverlapping($this->reportId))
                ->expireAfter(300)
                ->releaseAfter(10),
        ];
    }
}

```

`expireAfter` ensures the lock is released even if the worker crashes — previously you had to manage this manually with a cache key.

---

Upgrade Path
------------

1. **Bump `composer.json`** — `"laravel/framework": "^13.0"`.
2. **Remove kernel classes** — migrate logic to `bootstrap/app.php`.
3. **Audit `config()` calls** — replace unsafe casts with `Config::typed()` where you own the config key.
4. **Check removed helpers** — `str_contains`, `str_starts_with`, and `str_ends_with` global aliases were already native PHP 8; confirm nothing in your codebase polyfills them.
5. **Run `php artisan about`** — the output now includes middleware stack and scheduled task counts, useful for a quick sanity check post-upgrade.

---

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

- The kernel-less skeleton is now the only skeleton; plan your upgrade accordingly.
- `Config::typed()` enforces config contracts at runtime, not at the call site.
- The `Uri` value object eliminates a whole class of string-manipulation bugs.
- `WithoutOverlapping::expireAfter()` closes a long-standing gap in job deduplication reliability.
- Upgrading from Laravel 12 is straightforward; upgrading from 10 or earlier requires kernel migration first.

- [laravel](https://msaied.com/articles?search=laravel)
- [laravel-13](https://msaied.com/articles?search=laravel-13)
- [upgrade](https://msaied.com/articles?search=upgrade)
- [queues](https://msaied.com/articles?search=queues)
- [helpers](https://msaied.com/articles?search=helpers)

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

  Do I need to remove my Http/Kernel.php immediately when upgrading to Laravel 13?No. Laravel 13 will throw an error only if the kernel class conflicts with the new bootstrap/app.php registration. The safest path is to migrate all middleware and exception handling into bootstrap/app.php first, verify behaviour, then delete the kernel files.

   Is the new Uri class a drop-in replacement for the Http\\Client request builder?No. Uri is a value object for constructing and manipulating URIs as strings. It does not send HTTP requests. Use it to build URLs before passing them to Http::get() or similar methods.

   Does Config::typed() work with nested dot-notation keys?Yes. It resolves the key using the same dot-notation as config(), then asserts the resolved value matches the requested type, throwing InvalidArgumentException if it does not.

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

[Mohamed Said](https://msaied.com#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://msaied.com#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 New in 12: First-Class Typed Config, Fluent Routing, and Upgrade Notes](https://msaied.com/articles/laravel-new-in-12-first-class-typed-config-fluent-routing-and-upgrade-notes)  

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

1. [Laravel 13: What Actually Changed and Why It Matters](#laravel-13-what-actually-changed-and-why-it-matters)
2. [Leaner Application Skeleton](#leaner-application-skeleton)
3. [Typed Configuration via config() Return Types](#typed-configuration-via-codeconfigcode-return-types)
4. [Str::password() and Str::ulid() Improvements](#codestrpasswordcode-and-codestrulidcode-improvements)
5. [Fluent Uri Value Object](#fluent-codeuricode-value-object)
6. [Queue withoutDelay() and onceWithoutOverlapping() Improvements](#queue-codewithoutdelaycode-and-codeoncewithoutoverlappingcode-improvements)
7. [Upgrade Path](#upgrade-path)
8. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

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

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

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

 [ ![](https://cdn.msaied.com/735/2b11b2815a5984a8e3ab654b67f9af60.png)  · 4 min read### Laravel New in 12: First-Class Typed Config, Fluent Routing, and Upgrade Notes

3 Oct 2026 ](https://msaied.com/articles/laravel-new-in-12-first-class-typed-config-fluent-routing-and-upgrade-notes) [ ![](https://cdn.msaied.com/731/7cabd03b86a18f1db2c9ff7de1510270.png)  · 3 min read### Laravel Octane + FrankenPHP: Request Lifecycle, Shared State, and Safe Singleton Patterns

3 Oct 2026 ](https://msaied.com/articles/laravel-octane-frankenphp-request-lifecycle-shared-state-and-safe-singleton-patterns) [ ![](https://cdn.msaied.com/728/b96439f5ef5f084b44d736951875f964.png)  · 3 min read### Eloquent Custom Relations: Polymorphic Pivots, Has-One-Of-Many, and Raw Join Relations

2 Oct 2026 ](https://msaied.com/articles/eloquent-custom-relations-polymorphic-pivots-has-one-of-many-and-raw-join-relations) 

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

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

 [Discuss your project ↗](https://msaied.com#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://msaied.com)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/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://msaied.com/sitemap.xml)
