Skip to content
LaravelBlog

laravel/framework: Add order() to DevCommands

LaravelBlogBot
LaravelBlogBot

Contributed by jackbayliss

Part of the framework v13.36.0 release

Laravel 13 ships a small but genuinely useful quality-of-life improvement for local development: you can now control the order in which php artisan dev starts and displays your development processes. Pull request #61575 adds a DevCommands::order() method to Illuminate\Foundation\DevCommands, so instead of accepting whatever order the framework, packages, and your own code happen to register commands in, you decide exactly how the dev panel is laid out.

What changed

The dev command is a convenience wrapper that boots several processes side by side: the built-in server, queue, vite, and logs (Pail) commands, plus anything registered by packages or your application, such as Reverb's reverb command. Until now, the order those processes started — and the order their tabs appeared in — was purely a product of registration order: framework defaults first, then package registrations, then your own commands. That's why Reverb always ended up at the top, even if you would rather see your application logs first.

This PR introduces an $order property and a public static order() method on DevCommands. When DevCommands::commands() resolves the final command list, it now runs it through a new internal applyOrder() step that re-sorts commands according to your configuration before colors are auto-assigned. The rest of the class is untouched.

How the ordering works

applyOrder() performs a stable sort against the registered command names. The practical semantics are easy to reason about:

  • Commands whose names appear in the array you pass to order() are hoisted to the front, in exactly the order you list them.
  • Commands not named in the array — whether they're named commands you omitted or commands registered without a name — keep their existing relative order and follow behind the sorted ones.
  • Names must match the name given when a command was registered (the second argument to DevCommands::register()).
  • Calling order() again replaces the previous ordering rather than merging with it, so a single call defines the whole order.

The included tests pin this behavior down: testOrderSortsCommands verifies a complete reordering, and testOrderLeavesUnnamedCommandsInRegistrationOrder confirms that calling DevCommands::order(['four']) yields four first with one, two, and three trailing in their original registration order.

Using it in your app

Both partial and complete ordering are supported. To simply pull one command to the front and leave everything else alone:

use Illuminate\Foundation\DevCommands;

// Put logs first; everything else keeps its normal order
DevCommands::order(['logs']);

Or define the full order explicitly:

DevCommands::order(['logs', 'reverb', 'server', 'queue', 'vite']);

Because DevCommands is configured statically, the natural place for this call is bootstrap/app.php, alongside your other application bootstrap configuration, or the boot() method of a service provider:

// bootstrap/app.php
use Illuminate\Foundation\DevCommands;
use Illuminate\Foundation\Application;

DevCommands::order(['logs', 'reverb', 'server', 'queue', 'vite']);

return Application::configure(basePath: dirname(__DIR__))
    // ... your existing withRouting(), withMiddleware(), etc.
    ->create();

This is especially handy when a package injects its own dev command and there was previously no way to influence where it lands — the ordering applies to framework defaults, package-registered commands, and user-land registrations alike.

Edge cases worth knowing

A few details to keep in mind when adopting this:

  • Unknown names in the order array are handled gracefully; they simply don't match anything, and the unmatched commands sort to the back together.
  • A partial list only reorders the commands you name — you don't need to enumerate every command to get the layout you want.
  • The ordering only affects the composition of php artisan dev; it doesn't change how individual Artisan commands are registered or executed elsewhere.
  • The internal state reset used by the framework and tests now also clears the order value, so there's no leakage between test runs or subprocesses.

Upgrade impact

There is no upgrade impact — this is a purely additive, opt-in feature. The $order property defaults to an empty array, so if you're moving from v12.70.0 to the 13.x series and never call DevCommands::order(), your dev command behaves exactly as it did before, with commands running and appearing in registration order. Nothing in your configuration, service providers, or custom dev commands needs to change, and no deprecations are involved. The feature is self-contained in DevCommands and covered by two new test cases, so adopting it is as simple as adding a single order() call where you already configure your application.

Takeaways:

  • DevCommands::order([...]) controls the start/display order of commands in php artisan dev.
  • Named commands are pulled to the front in the order given; everything else keeps its relative registration order.
  • A full list pins the entire order; a partial list only reorders what you name.
  • Purely additive — no action required when upgrading from v12.70.0; opt in by calling order() in bootstrap/app.php or a service provider.
  • Subsequent calls replace the previous order, and unknown names are safely ignored.

Sources

More from this release

Related Articles