Laravel 13.30: chunkBy() and Storage Path Hardening | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Collections chunkBy() and Storage Path Hardening in Laravel 13.30        On this page       1. [  What's New in Laravel 13.30 ](#whats-new-in-laravel-1330)
2. [  chunkBy() for Collections and Lazy Collections ](#codechunkbycode-for-collections-and-lazy-collections)
3. [  Storage::path() Now Rejects Path Traversal ](#codestoragepathcode-now-rejects-path-traversal)
4. [  Worker Stop Reasons in queue:work ](#worker-stop-reasons-in-codequeueworkcode)
5. [  Other Notable Changes ](#other-notable-changes)
6. [  Key Takeaways ](#key-takeaways)

  ![Collections chunkBy() and Storage Path Hardening in Laravel 13.30](https://cdn.msaied.com/622/59bd72aa94848dfb195df6dcfb498e43.png)

 [  Laravel ](https://msaied.com/articles?category=laravel)  #Laravel 13.30   #Collections   #Storage   #Queue   #Security  

 Collections chunkBy() and Storage Path Hardening in Laravel 13.30 
===================================================================

     1 Sep 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   What's New in Laravel 13.30  ](#whats-new-in-laravel-1330)
2. [  02   chunkBy() for Collections and Lazy Collections  ](#codechunkbycode-for-collections-and-lazy-collections)
3. [  03   Storage::path() Now Rejects Path Traversal  ](#codestoragepathcode-now-rejects-path-traversal)
4. [  04   Worker Stop Reasons in queue:work  ](#worker-stop-reasons-in-codequeueworkcode)
5. [  05   Other Notable Changes  ](#other-notable-changes)
6. [  06   Key Takeaways  ](#key-takeaways)

 What's New in Laravel 13.30
---------------------------

Laravel 13.30 landed on September 2, 2026 with a focused set of developer-experience improvements and one notable security hardening. Here is a breakdown of the headline changes.

---

### `chunkBy()` for Collections and Lazy Collections

The existing `chunkWhile()` method splits a collection whenever a callback returns `false`. The most common pattern was comparing the current item against the last item in the chunk being built:

```php
$products->chunkWhile(
    fn ($value, $key, $chunk) => $value->parent == $chunk->last()->parent
);

```

The new `chunkBy()` method encodes that comparison directly. Pass a key name or a callback, and a new chunk starts whenever the resolved value changes:

```php
$products->chunkBy('parent');

collect([1, 1, 2, 2, 1, 1])->chunkBy(fn ($value) => $value);
// [[1, 1], [2, 2], [1, 1]]

```

The key is resolved through `data_get()`, so dot notation works (`chunkBy('address.city')`). Original keys are preserved inside each chunk. Contributed by [@JosephSilber](https://github.com/JosephSilber) in [\#61357](https://github.com/laravel/framework/pull/61357).

---

### `Storage::path()` Now Rejects Path Traversal

Every Flysystem-backed filesystem call normalizes paths and throws `PathTraversalDetected` when a path resolves outside the disk root — except `Storage::path()`, which previously just concatenated the prefix:

```php
Storage::get('../../../.env');  // rejected
Storage::path('../../../.env'); // resolved outside the disk root

```

This mattered anywhere user input reached `path()`, for example:

```php
response()->download(Storage::path($request->query('path')));

```

`path()` now runs the argument through `WhitespacePathNormalizer` — the same normalizer every other Flysystem call uses — before prefixing. Anything that escapes the disk root throws `PathTraversalDetected`. Code relying on `..` segments in `path()` will now receive an exception. Contributed by [@KIKOmanasijev](https://github.com/KIKOmanasijev) in [\#61343](https://github.com/laravel/framework/pull/61343).

---

### Worker Stop Reasons in `queue:work`

`queue:work` now prints the reason a worker exits as its final line:

```yaml
2026-09-01 13:20:40 Worker STOPPED Memory limit exceeded

```

With `--json`, the reason is emitted as a structured record:

```json
{"level":"warning","status":"stopped","reason":"memory","exit_code":12,"jobs_processed":2,"memory":1.2,"timestamp":"2026-09-01T13:20:40.118273+00:00"}

```

Nine exit scenarios are covered, including memory limit exceeded, maximum jobs exceeded, restart signal received, and job timed out. Nothing is written under `--quiet` or `--silent`. Contributed by [@jackbayliss](https://github.com/jackbayliss) in [\#61339](https://github.com/laravel/framework/pull/61339).

---

### Other Notable Changes

- **`DevCommands::withoutVendorCommands()` / `withoutDefaultCommands()`** — filter `dev` commands by origin instead of naming every command explicitly.
- **Native `sqlsrv:` DSN strings** — `sqlsrv:Server=host,1433;Database=db;Encrypt=true` is now parsed correctly instead of being mangled by `parse_url()`.
- **`Artisan::commandNamed()`** — resolves a single command by name without constructing every registered command.
- **Cloud queue totals** — `totalPendingSize()`, `totalDelayedSize()`, and `totalReservedSize()` are now implemented on the Laravel Cloud queue driver.
- **`route:cache` facade fix** — the global facade application is restored after `route:cache` bootstraps its throwaway container, preventing `Route is not bound` errors during `php artisan optimize`.
- **`Request::clamp()` non-numeric fallback** — inputs like `?per-page=foo` now fall through to the default instead of returning a 500.

---

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

- `chunkBy()` replaces verbose `chunkWhile()` callbacks when grouping by a stable key or computed value.
- `Storage::path()` now enforces the same path-traversal protection as every other storage method — audit any code that passes user input to `path()`.
- Queue worker exit reasons appear in console output without any listener setup.
- Native SQL Server DSN strings are parsed correctly for the first time.
- `Artisan::commandNamed()` avoids the performance cost of constructing all commands just to find one.

---

[Source: Laravel News — Laravel 13.30.0](https://laravel-news.com/laravel-13-30-0)

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fcollections-chunkby-and-storage-path-hardening-in-laravel-1330&text=Collections+chunkBy%28%29+and+Storage+Path+Hardening+in+Laravel+13.30) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fcollections-chunkby-and-storage-path-hardening-in-laravel-1330) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  What is the difference between chunkBy() and chunkWhile() in Laravel collections?        `chunkWhile()` splits a collection wherever a callback returns false, requiring you to manually compare the current item with the last item in the current chunk. `chunkBy()` wraps that pattern: you pass a key name or callback, and a new chunk starts automatically whenever the resolved value changes. It also supports dot notation via `data_get()`. 

      Q02  Why is the Storage::path() change in Laravel 13.30 a security improvement?        Before 13.30, `Storage::path()` skipped path normalization and simply concatenated the disk prefix with the given string. This meant passing `../../../.env` returned a valid native path outside the disk root, even though `Storage::get()` and other methods would have rejected the same input. The fix runs the argument through `WhitespacePathNormalizer` and throws `PathTraversalDetected` for any path that escapes the disk root, matching the behavior of every other filesystem call. 

      Q03  How do I see why a Laravel queue worker stopped without registering a listener?        In Laravel 13.30 and later, `queue:work` prints the stop reason as its final line automatically, for example `Worker STOPPED Memory limit exceeded`. With the `--json` flag the reason is included in a structured JSON record. Nothing is output under `--quiet` or `--silent`. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Statamic Sidecar: Edit Markdown Sites from the Control Panel Without Migration](https://cdn.msaied.com/624/6df15b406d700ea26fb98c6ad4779195.png) Statamic Markdown CMS 

### Statamic Sidecar: Edit Markdown Sites from the Control Panel Without Migration

Statamic's new Sidecar product lets you manage any static site generator's Markdown files through the Statamic...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 2 Sep 2026     3 min read  

  Read    

 ](https://msaied.com/articles/statamic-sidecar-edit-markdown-sites-from-the-control-panel-without-migration) [ ![Laravel Macro-Free Extensibility: Extending Eloquent Builder with Custom Query Objects](https://cdn.msaied.com/621/b0c176a363378658e83bb44ed379879b.png) laravel eloquent clean-architecture 

### Laravel Macro-Free Extensibility: Extending Eloquent Builder with Custom Query Objects

Skip global macros and reach for typed, testable query objects that encapsulate reusable Eloquent constraints...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 2 Sep 2026     1 min read  

  Read    

 ](https://msaied.com/articles/laravel-macro-free-extensibility-extending-eloquent-builder-with-custom-query-objects) [ ![Livewire v3 Performance: Computed Properties, Dehydration Budgets, and Wire:model Lazy](https://cdn.msaied.com/620/e4d958595b3e6a6b47c586df3f972938.png) livewire laravel performance 

### Livewire v3 Performance: Computed Properties, Dehydration Budgets, and Wire:model Lazy

Stop over-fetching on every request cycle. This deep-dive covers Livewire v3 computed property memoisation, co...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 2 Sep 2026     3 min read  

  Read    

 ](https://msaied.com/articles/livewire-v3-performance-computed-properties-dehydration-budgets-and-wiremodel-lazy) 

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

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
