Overview
Ziggy supports Laravel’s URL::defaults() feature, which allows you to set default values for route parameters. This is particularly useful for multi-tenant applications or when you need to inject contextual values (like locale) into routes automatically.
Laravel’s URL::defaults()
In Laravel, you can use URL::defaults() to set default parameter values that apply to all route generation:
use Illuminate\Support\Facades\ URL ;
URL :: defaults ([ 'locale' => 'en' ]);
These defaults are typically set in middleware, so they can be based on the current request:
// app/Http/Middleware/SetLocale.php
namespace App\Http\Middleware ;
use Closure ;
use Illuminate\Support\Facades\ URL ;
class SetLocale
{
public function handle ( $request , Closure $next )
{
$locale = $request -> user () -> locale ?? 'de' ;
URL :: defaults ([ 'locale' => $locale ]);
return $next ( $request );
}
}
Using Defaults with Ziggy
When you set defaults with URL::defaults(), Ziggy automatically includes them in its configuration. These defaults are then applied when generating URLs in JavaScript:
Route :: get ( '{locale}/posts/{post}' , fn ( Post $post ) => /* ... */ ) -> name ( 'posts.show' );
// In middleware or service provider
URL :: defaults ([ 'locale' => $request -> user () -> locale ?? 'de' ]);
// JavaScript - locale is automatically filled in
route ( 'posts.show' , 1 );
// 'https://ziggy.test/de/posts/1'
You don’t need to pass the locale parameter explicitly—Ziggy automatically uses the default value from Laravel.
How It Works
Ziggy’s PHP code includes default parameters in its configuration:
Default Parameters in Ziggy.php
public function toArray () : array
{
return [
'url' => $this -> url ,
'port' => parse_url ( $this -> url , PHP_URL_PORT ) ?? null ,
'defaults' => app ( 'url' ) -> getDefaultParameters (),
'routes' => $this -> applyFilters ( $this -> group ) -> toArray (),
];
}
The defaults key contains all parameter defaults set via URL::defaults().
Applying Defaults in Router.js
_defaults ( route ) {
return route . parameterSegments
. filter (({ name }) => this . _config . defaults [ name ])
. reduce (
( result , { name }, i ) => ({ ... result , [name]: this . _config . defaults [ name ] }),
{},
);
}
When generating a URL, Ziggy:
Identifies which route parameters have defaults
Includes those defaults in the parameter object
Merges explicit parameters over defaults
Overriding Defaults
You can override default values by passing explicit parameters:
// Default locale is 'de'
URL :: defaults ([ 'locale' => 'de' ]);
// Use the default
route ( 'posts.show' , { post: 1 });
// 'https://ziggy.test/de/posts/1'
// Override the default
route ( 'posts.show' , { post: 1 , locale: 'fr' });
// 'https://ziggy.test/fr/posts/1'
Explicit parameters always take precedence over defaults.
Multiple Default Parameters
You can set defaults for multiple parameters:
URL :: defaults ([
'locale' => 'en' ,
'country' => 'US' ,
]);
Route :: get ( '{locale}/{country}/products/{product}' , fn ( Product $product ) => /* ... */ )
-> name ( 'products.show' );
route ( 'products.show' , 1 );
// 'https://ziggy.test/en/US/products/1'
route ( 'products.show' , { product: 1 , locale: 'de' });
// 'https://ziggy.test/de/US/products/1'
// ✅ Only locale is overridden, country uses default
Common Use Cases
Multi-Language Sites
Set the user’s locale as a default parameter:
// app/Http/Middleware/SetLocale.php
public function handle ( $request , Closure $next )
{
$locale = session ( 'locale' , config ( 'app.locale' ));
app () -> setLocale ( $locale );
URL :: defaults ([ 'locale' => $locale ]);
return $next ( $request );
}
// routes/web.php
Route :: prefix ( '{locale}' ) -> group ( function () {
Route :: get ( 'posts' , [ PostController :: class , 'index' ]) -> name ( 'posts.index' );
Route :: get ( 'posts/{post}' , [ PostController :: class , 'show' ]) -> name ( 'posts.show' );
});
// JavaScript - locale is always included
route ( 'posts.index' );
// 'https://ziggy.test/en/posts'
route ( 'posts.show' , 1 );
// 'https://ziggy.test/en/posts/1'
Multi-Tenant Applications
Set the tenant identifier as a default:
// app/Http/Middleware/SetTenant.php
public function handle ( $request , Closure $next )
{
$tenant = $request -> user () -> tenant ;
URL :: defaults ([ 'tenant' => $tenant -> slug ]);
return $next ( $request );
}
Route :: domain ( '{tenant}.myapp.com' ) -> group ( function () {
Route :: get ( 'dashboard' , [ DashboardController :: class , 'index' ]) -> name ( 'dashboard' );
Route :: get ( 'settings' , [ SettingsController :: class , 'index' ]) -> name ( 'settings' );
});
// JavaScript - tenant is automatically included
route ( 'dashboard' );
// 'https://acme.myapp.com/dashboard'
route ( 'settings' );
// 'https://acme.myapp.com/settings'
API Versioning
URL :: defaults ([ 'version' => 'v2' ]);
Route :: prefix ( '{version}/api' ) -> group ( function () {
Route :: get ( 'posts' , [ ApiController :: class , 'posts' ]) -> name ( 'api.posts' );
});
route ( 'api.posts' );
// 'https://ziggy.test/v2/api/posts'
Defaults with Route-Model Binding
Defaults work seamlessly with route-model binding:
URL :: defaults ([ 'locale' => 'en' ]);
Route :: get ( '{locale}/posts/{post:slug}' , fn ( Post $post ) => /* ... */ )
-> name ( 'posts.show' );
const post = {
id: 1 ,
slug: 'introducing-ziggy' ,
title: 'Introducing Ziggy' ,
};
route ( 'posts.show' , post );
// 'https://ziggy.test/en/posts/introducing-ziggy'
// ✅ Both locale default and slug binding work together
Defaults in the Generated Config
When you generate Ziggy’s configuration file, defaults are included:
php artisan ziggy:generate
// resources/js/ziggy.js
const Ziggy = {
url: 'https://ziggy.test' ,
port: null ,
defaults: { locale: 'en' , country: 'US' },
routes: {
'posts.show' : {
uri: '{locale}/{country}/posts/{post}' ,
methods: [ 'GET' , 'HEAD' ],
parameters: [ 'locale' , 'country' , 'post' ],
},
},
};
export { Ziggy };
If your defaults change based on the current user or request (like in the multi-tenant example), you should use the @routes Blade directive instead of generating a static file. This ensures defaults are always current.
Parameter Priority
When generating a URL, Ziggy merges parameters in this order (later sources override earlier ones):
Default parameters from URL::defaults()
Explicit parameters passed to route()
// With defaults: { locale: 'en', country: 'US' }
route ( 'products.show' , { product: 1 , locale: 'fr' });
// Result: { locale: 'fr', country: 'US', product: 1 }
// ^^^^^^^^^^^ overridden ^^^^^^^^^^^ from default
Parameter Merging Implementation
_parse ( params = {}, route = this . _route ) {
// ... parameter parsing logic ...
return {
... this . _defaults ( route ), // 1. Start with defaults
... this . _substituteBindings ( params , route ), // 2. Add/override with explicit params
};
}
Best Practices
Set defaults in middleware
This ensures defaults are based on the current request context: // ✅ Middleware - runs for each request
public function handle ( $request , Closure $next )
{
URL :: defaults ([ 'locale' => $request -> user () -> locale ]);
return $next ( $request );
}
// ❌ Service provider - runs once on boot
public function boot ()
{
URL :: defaults ([ 'locale' => 'en' ]); // Static, can't use request context
}
Use the @routes directive for dynamic defaults
If your defaults change per-user or per-request: {{-- ✅ Fresh defaults for each page load --}}
@routes
{{-- ❌ Stale defaults from when file was generated --}}
< script src = " {{ asset ('js/ziggy.js') }} " ></ script >
Document required defaults
If your app relies on certain defaults being set, document this clearly: /**
* This middleware sets the required 'tenant' default parameter.
* All route generation assumes this default is present.
*/
class SetTenant
{
// ...
}
Debugging Defaults
You can inspect Ziggy’s current defaults in JavaScript:
const ziggyConfig = route (). config ;
console . log ( ziggyConfig . defaults );
// { locale: 'en', country: 'US' }
Or in Laravel:
use Tighten\Ziggy\ Ziggy ;
$config = ( new Ziggy ) -> toArray ();
dd ( $config [ 'defaults' ]);
// ['locale' => 'en', 'country' => 'US']
Next Steps
Router Class Learn about Ziggy’s Router class and its methods
Filtering Routes Control which routes are included in Ziggy