Détail du package

ziggy-js

tighten299.6kMIT2.5.3

Use your Laravel named routes in JavaScript.

laravel, routes, ziggy

readme

Ziggy - Use your Laravel routes in JavaScript

Ziggy – Use your Laravel routes in JavaScript

GitHub Actions Status Latest Version on Packagist Downloads on Packagist Latest Version on NPM Downloads on NPM

Ziggy provides a JavaScript route() function that works like Laravel's, making it a breeze to use your named Laravel routes in JavaScript.

Installation

Install Ziggy in your Laravel app with Composer:

composer require tightenco/ziggy

Add the @routes Blade directive to your main layout (before your application's JavaScript), and the route() helper function will be available globally!

By default, the output of the @routes Blade directive includes a list of all your application's routes and their parameters. This route list is included in the HTML of the page and can be viewed by end users. To configure which routes are included in this list, or to show and hide different routes on different pages, see Filtering Routes.

Usage

route() function

Ziggy's route() function works like Laravel's route() helper—you can pass it the name of a route, and the parameters you want to pass to the route, and it will generate a URL.

Basic usage

Route::get('posts', fn (Request $request) => /* ... */)->name('posts.index');
route('posts.index'); // 'https://ziggy.test/posts'

Parameters

Route::get('posts/{post}', fn (Post $post) => /* ... */)->name('posts.show');
route('posts.show', 1);           // 'https://ziggy.test/posts/1'
route('posts.show', [1]);         // 'https://ziggy.test/posts/1'
route('posts.show', { post: 1 }); // 'https://ziggy.test/posts/1'

Multiple parameters

Route::get('venues/{venue}/events/{event}', fn (Venue $venue, Event $event) => /* ... */)
    ->name('venues.events.show');
route('venues.events.show', [1, 2]);                 // 'https://ziggy.test/venues/1/events/2'
route('venues.events.show', { venue: 1, event: 2 }); // 'https://ziggy.test/venues/1/events/2'

Query parameters

Ziggy adds arguments that don't match any named route parameters as query parameters:

Route::get('venues/{venue}/events/{event}', fn (Venue $venue, Event $event) => /* ... */)
    ->name('venues.events.show');
route('venues.events.show', {
    venue: 1,
    event: 2,
    page: 5,
    count: 10,
});
// 'https://ziggy.test/venues/1/events/2?page=5&count=10'

If you need to pass a query parameter with the same name as a route parameter, nest it under the special _query key:

route('venues.events.show', {
    venue: 1,
    event: 2,
    _query: {
        event: 3,
        page: 5,
    },
});
// 'https://ziggy.test/venues/1/events/2?event=3&page=5'

Like Laravel, Ziggy automatically encodes boolean query parameters as integers in the query string:

route('venues.events.show', {
    venue: 1,
    event: 2,
    _query: {
        draft: false,
        overdue: true,
    },
});
// 'https://ziggy.test/venues/1/events/2?draft=0&overdue=1'

Default parameter values

Ziggy supports default route parameter values (Laravel docs).

Route::get('{locale}/posts/{post}', fn (Post $post) => /* ... */)->name('posts.show');
// app/Http/Middleware/SetLocale.php

URL::defaults(['locale' => $request->user()->locale ?? 'de']);
route('posts.show', 1); // 'https://ziggy.test/de/posts/1'

Examples

HTTP request with axios:

const post = { id: 1, title: 'Ziggy Stardust' };

return axios.get(route('posts.show', post)).then((response) => response.data);

Router class

Calling Ziggy's route() function with no arguments will return an instance of its JavaScript Router class, which has some other useful properties and methods.

Check the current route: route().current()

// Laravel route called 'events.index' with URI '/events'
// Current window URL is https://ziggy.test/events

route().current();               // 'events.index'
route().current('events.index'); // true
route().current('events.*');     // true
route().current('events.show');  // false

route().current() optionally accepts parameters as its second argument, and will check that their values also match in the current URL:

// Laravel route called 'venues.events.show' with URI '/venues/{venue}/events/{event}'
// Current window URL is https://myapp.com/venues/1/events/2?hosts=all

route().current('venues.events.show', { venue: 1 });           // true
route().current('venues.events.show', { venue: 1, event: 2 }); // true
route().current('venues.events.show', { hosts: 'all' });       // true
route().current('venues.events.show', { venue: 6 });           // false

Check if a route exists: route().has()

// Laravel app has only one named route, 'home'

route().has('home');   // true
route().has('orders'); // false

Retrieve the current route params: route().params

// Laravel route called 'venues.events.show' with URI '/venues/{venue}/events/{event}'
// Current window URL is https://myapp.com/venues/1/events/2?hosts=all

route().params; // { venue: '1', event: '2', hosts: 'all' }

Note: parameter values retrieved with route().params will always be returned as strings.

Route-model binding

Ziggy supports Laravel's route-model binding, and can even recognize custom route key names. If you pass route() a JavaScript object as a route parameter, Ziggy will use the registered route-model binding keys for that route to find the correct parameter value inside the object. If no route-model binding keys are explicitly registered for a parameter, Ziggy will use the object's id key.

// app/Models/Post.php

class Post extends Model
{
    public function getRouteKeyName()
    {
        return 'slug';
    }
}
Route::get('blog/{post}', function (Post $post) {
    return view('posts.show', ['post' => $post]);
})->name('posts.show');
const post = {
    id: 3,
    title: 'Introducing Ziggy v1',
    slug: 'introducing-ziggy-v1',
    date: '2020-10-23T20:59:24.359278Z',
};

// Ziggy knows that this route uses the 'slug' route-model binding key:

route('posts.show', post); // 'https://ziggy.test/blog/introducing-ziggy-v1'

Ziggy also supports custom keys for scoped bindings declared directly in a route definition:

Route::get('authors/{author}/photos/{photo:uuid}', fn (Author $author, Photo $photo) => /* ... */)
    ->name('authors.photos.show');
const photo = {
    uuid: '714b19e8-ac5e-4dab-99ba-34dc6fdd24a5',
    filename: 'sunset.jpg',
}

route('authors.photos.show', [{ id: 1, name: 'Ansel' }, photo]);
// 'https://ziggy.test/authors/1/photos/714b19e8-ac5e-4dab-99ba-34dc6fdd24a5'

TypeScript

Ziggy includes TypeScript type definitions, and an Artisan command that can generate additional type definitions to enable route name and parameter autocompletion.

To generate route types, run the ziggy:generate command with the --types or --types-only option:

php artisan ziggy:generate --types

To make your IDE aware that Ziggy's route() helper is available globally, and to type it correctly, add a declaration like this in a .d.ts file somewhere in your project:

import { route as routeFn } from 'ziggy-js';

declare global {
    var route: typeof routeFn;
}

If you don't have Ziggy's NPM package installed, add the following to your jsconfig.json or tsconfig.json to load Ziggy's types from your vendor directory:

{
    "compilerOptions": {
        "paths": {
            "ziggy-js": ["./vendor/tightenco/ziggy"]
        }
    }
}

JavaScript frameworks

[!NOTE] Many applications don't need the additional setup described here—the @routes Blade directive makes Ziggy's route() function and config available globally, including within bundled JavaScript files.

If you are not using the @routes Blade directive, you can import Ziggy's route() function and configuration directly into JavaScript/TypeScript files.

Generating and importing Ziggy's configuration

Ziggy provides an Artisan command to output its config and routes to a file:

php artisan ziggy:generate

This command places your configuration in resources/js/ziggy.js by default, but you can customize this path by passing an argument to the Artisan command or setting the ziggy.output.path config value.

The file ziggy:generate creates looks something like this:

// resources/js/ziggy.js

const Ziggy = {
    url: 'https://ziggy.test',
    port: null,
    routes: {
        home: {
            uri: '/',
            methods: [ 'GET', 'HEAD'],
            domain: null,
        },
        login: {
            uri: 'login',
            methods: ['GET', 'HEAD'],
            domain: null,
        },
    },
};

export { Ziggy };

Importing the route() function

You can import Ziggy like any other JavaScript library. Without the @routes Blade directive Ziggy's config is not available globally, so it must be passed to the route() function manually:

import { route } from '../../vendor/tightenco/ziggy';
import { Ziggy } from './ziggy.js';

route('home', undefined, undefined, Ziggy);

To simplify importing the route() function, you can create an alias to the vendor path:

// vite.config.js

export default defineConfig({
    resolve: {
        alias: {
            'ziggy-js': path.resolve('vendor/tightenco/ziggy'),
        },
    },
});

Now your imports can be shortened to:

import { route } from 'ziggy-js';

Vue

Ziggy includes a Vue plugin to make it easy to use the route() helper throughout your Vue app:

import { createApp } from 'vue';
import { ZiggyVue } from 'ziggy-js';
import App from './App.vue';

createApp(App).use(ZiggyVue);

Now you can use the route() function anywhere in your Vue components and templates:

<a class="nav-link" :href="route('home')">Home</a>

With <script setup> in Vue 3 you can use inject to make the route() function available in your component script:

<script setup>
import { inject } from 'vue';

const route = inject('route');
</script>

If you are not using the @routes Blade directive, import Ziggy's configuration too and pass it to .use():

import { createApp } from 'vue';
import { ZiggyVue } from 'ziggy-js';
import { Ziggy } from './ziggy.js';
import App from './App.vue';

createApp(App).use(ZiggyVue, Ziggy);

If you're using TypeScript, you may need to add the following declaration to a .d.ts file in your project to avoid type errors when using the route() function in your Vue component templates:

declare module 'vue' {
    interface ComponentCustomProperties {
        route: typeof routeFn;
    }
}

React

Ziggy includes a useRoute() hook to make it easy to use the route() helper in your React app:

import React from 'react';
import { useRoute } from 'ziggy-js';

export default function PostsLink() {
    const route = useRoute();

    return <a href={route('posts.index')}>Posts</a>;
}

If you are not using the @routes Blade directive, import Ziggy's configuration too and pass it to useRoute():

import React from 'react';
import { useRoute } from 'ziggy-js';
import { Ziggy } from './ziggy.js';

export default function PostsLink() {
    const route = useRoute(Ziggy);

    return <a href={route('posts.index')}>Posts</a>;
}

You can also make the Ziggy config object available globally, so you can call useRoute() without passing Ziggy's configuration to it every time:

// app.js
import { Ziggy } from './ziggy.js';
globalThis.Ziggy = Ziggy;

SPAs or separate repos

Ziggy's route() function is available as an NPM package, for use in JavaScript projects managed separately from their Laravel backend (i.e. without Composer or a vendor directory). You can install the NPM package with npm install ziggy-js.

To make your routes available on the frontend for this function to use, you can either run php artisan ziggy:generate and add the generated config file to your frontend project, or you can return Ziggy's config as JSON from an endpoint in your Laravel API (see Retrieving Ziggy's config from an API endpoint below for an example of how to set this up).

Filtering Routes

Ziggy supports filtering the list of routes it outputs, which is useful if you have certain routes that you don't want to be included and visible in your HTML source.

[!IMPORTANT] Hiding routes from Ziggy's output is not a replacement for thorough authentication and authorization. Routes that should not be accessibly publicly should be protected by authentication whether they're filtered out of Ziggy's output or not.

Including/excluding routes

To set up route filtering, create a config file in your Laravel app at config/ziggy.php and add either an only or except key containing an array of route name patterns.

Note: You have to choose one or the other. Setting both only and except will disable filtering altogether and return all named routes.

// config/ziggy.php

return [
    'only' => ['home', 'posts.index', 'posts.show'],
];

You can use asterisks as wildcards in route filters. In the example below, admin.* will exclude routes named admin.login, admin.register, etc.:

// config/ziggy.php

return [
    'except' => ['_debugbar.*', 'horizon.*', 'admin.*'],
];

Filtering with groups

You can also define groups of routes that you want make available in different places in your app, using a groups key in your config file:

// config/ziggy.php

return [
    'groups' => [
        'admin' => ['admin.*', 'users.*'],
        'author' => ['posts.*'],
    ],
];

Then, you can expose a specific group by passing the group name into the @routes Blade directive:

{{-- authors.blade.php --}}

@routes('author')

To expose multiple groups you can pass an array of group names:

{{-- admin.blade.php --}}

@routes(['admin', 'author'])

Note: Passing group names to the @routes directive will always take precedence over your other only or except settings.

Other

TLS/SSL termination and trusted proxies

If your application is using TLS/SSL termination or is behind a load balancer or proxy, or if it's hosted on a service that is, Ziggy may generate URLs with a scheme of http instead of https, even if your app URL uses https. To fix this, set up your Laravel app's trusted proxies according to the documentation on Configuring Trusted Proxies.

Using @routes with a Content Security Policy

A Content Security Policy (CSP) may block inline scripts, including those output by Ziggy's @routes Blade directive. If you have a CSP and are using a nonce to flag safe inline scripts, you can pass the nonce to the @routes directive and it will be added to Ziggy's script tag:

@routes(nonce: 'your-nonce-here')

Disabling the route() helper

If you only want to use the @routes directive to make Ziggy's configuration available in JavaScript, but don't need the route() helper function, set the ziggy.skip-route-function config to true.

Retrieving Ziggy's config from an API endpoint

If you need to retrieve Ziggy's config from your Laravel backend over the network, you can create a route that looks something like this:

// routes/api.php

use Tighten\Ziggy\Ziggy;

Route::get('ziggy', fn () => response()->json(new Ziggy));

Re-generating the routes file when your app routes change

If you are generating your Ziggy config as a file by running php artisan ziggy:generate, you may want to re-run that command when your app's route files change. The example below is a Laravel Mix plugin, but similar functionality could be achieved without Mix. Huge thanks to Nuno Rodrigues for the idea and a sample implementation. See #655 or vite-plugin-ziggy for Vite examples.

<summary>Laravel Mix plugin example</summary>

js const mix = require('laravel-mix'); const { exec } = require('child_process'); mix.extend('ziggy', new class { register(config = {}) { this.watch = config.watch ?? ['routes/**/*.php']; this.path = config.path ?? ''; this.enabled = config.enabled ?? !Mix.inProduction(); } boot() { if (!this.enabled) return; const command = () => exec( `php artisan ziggy:generate ${this.path}`, (error, stdout, stderr) => console.log(stdout) ); command(); if (Mix.isWatching() && this.watch) { ((require('chokidar')).watch(this.watch)) .on('change', (path) => { console.log(`${path} changed...`); command(); }); }; } }()); mix.js('resources/js/app.js', 'public/js') .postCss('resources/css/app.css', 'public/css', []) .ziggy();

Contributing

To get started contributing to Ziggy, check out the contribution guide.

Credits

Thanks to Caleb Porzio, Adam Wathan, and Jeffrey Way for help solidifying the idea.

Security

Please review our security policy on how to report security vulnerabilities.

License

Ziggy is open-source software released under the MIT license. See LICENSE for more information.

changelog

Changelog

All notable changes to this project will be documented in this file.

This project adheres to Semantic Versioning, and the format of this changelog is based on Keep a Changelog.

Breaking changes are marked with ⚠️.

Unreleased

v2.5.3 - 2025-05-17

Fixed

v2.5.2 - 2025-02-27

Changed

v2.5.1 - 2025-01-31

Fixed

v2.5.0 - 2025-01-22

Added

Fixed

v2.4.2 - 2025-01-02

Fixed

v2.4.1 - 2024-11-21

Fixed

  • Fix qs type dependencies

v2.4.0 - 2024-11-09

Added

Fixed

Changed

v2.3.1 - 2024-10-17

Fixed

Changed

v2.3.0 - 2024-07-21

Added

Changed

v2.2.1 - 2024-05-16

Fixed

v2.2.0 - 2024-05-16

Added

Fixed

v2.1.0 - 2024-03-26

Added

Fixed

v2.0.5 - 2024-03-19

Fixed

v2.0.4 - 2024-03-05

Fixed

v2.0.3 - 2024-02-20

Fixed

v2.0.2 - 2024-02-20

Fixed

v2.0.1 - 2024-02-20

Fixed

v2.0.0 - 2024-02-20

See UPGRADING for detailed upgrade instructions.

Changed

  • Changed PHP package namespace from Tightenco\Ziggy to Tighten\Ziggy.
  • Updated JavaScript package to only provide named exports.
  • Moved Vue and React integrations to root of JavaScript module.
  • Updated builds to only use ES Modules.
  • Updated minimum dependency versions to Laravel 9 and PHP 8.1.

Removed

  • Made makeDirectory method of CommandRouteGenerator class private.
  • Removed deprecated JavaScript check() method.

v1.8.2 - 2024-02-20

Added

Fixed

Changed

v1.8.1 - 2023-10-12

Fixed

Changed

v1.8.0 - 2023-10-06

Added

v1.7.0 - 2023-10-04

Added

Fixed

v1.6.2 - 2023-08-18

Fixed

v1.6.1 - 2023-08-04

Fixed

v1.6.0 - 2023-05-12

Added

v1.5.2 - 2023-05-05

Added

Fixed

v1.5.1 - 2023-04-22

Fixed

v1.5.0 - 2022-09-23

Added

Changed

Fixed

v1.4.6 - 2022-04-08

Fixed

v1.4.5 - 2022-03-25

Fixed

v1.4.4 - 2022-03-11

Added

Fixed

v1.4.3 - 2022-01-28

Added

Fixed

v1.4.2 - 2021-10-01

Fixed

  • Fix route().current() matching route names with multiple periods (#466)

v1.4.1 - 2021-09-24

Fixed

  • Fix undefined error if there's no global Ziggy variable (#462)
  • Fix payload caching for Octane (#460)

v1.4.0 - 2021-08-25

Added

  • Add support for parameters inside single route segments (#444)

v1.3.6 - 2021-08-25

Fixed

  • Fix nested object query params (#451)

v1.3.5 - 2021-07-20

Fixed

  • Fix route model binding with abstract class (#445)

v1.3.4 - 2021-07-06

Fixed

  • Fix property mangling and implement ES5 compatibility (#442)

v1.3.3 - 2021-07-02

Fixed

v1.3.2 - 2021-07-01

Fixed

  • Remove Babel preset to correctly transpile to ES5 by default (d781b16)

v1.3.1 - 2021-06-19

Changed

  • Use Object.assign() to merge routes (#429)

v1.3.0 - 2021-06-17

Added

  • Make location configurable (adds better support for SSR) (#432)

v1.2.0 - 2021-05-24

Added

v1.1.0 - 2021-04-02

Added

  • Prepare for Laravel Octane (#415)

v1.0.5 - 2021-02-05

Added

  • Add support for appending 'extra' parameters to the query string (#390)

Changed

  • Remove source maps (#395)

Fixed

  • Use Laravel's Reflector class to get model parameter class name (#396)

v1.0.4 - 2020-12-06

Fixed

  • Fix bug where route().current() could incorrectly return true on URLs with no parameters (#377)
  • Fix several other bugs in route().current() with params (#379)
  • Revert #334, default Ziggy's url back to url('/') instead of the APP_URL environment variable (#386)

v1.0.3 - 2020-11-20

Fixed

  • Filter out unnamed cached routes with randomly generated names (#370)
  • Fix collision with JavaScript built-in method names like shift by casting empty defaults to an object (#371)

v1.0.2 - 2020-11-13

Fixed

  • Make ziggy:generate URL behaviour consistent with Ziggy class and Blade directive (#361)
  • Fix route().current() error on unknown/unnamed routes (#362)

v1.0.1 - 2020-11-10

Fixed

  • Fix route().current() on routes at the domain root (#356)

v1.0.0 - 2020-11-06

Added

Changed

  • ⚠️ Update ziggy:generate output path for Laravel 5.7+ resources directory structure, thanks @Somethingideally! (#269)
  • ⚠️ Update automatic id parameter detection to check for higher priority named route parameters and allow passing id as a query parameter (#301)
  • ⚠️ Rename the RoutePayload class to Ziggy and remove its compile method in favour of constructing a new instance and calling ->toArray() or ->toJson() (#305)
    • Resolve the application router instance internally instead of passing it into the constructor – new Ziggy(...) now takes only 2 arguments, $group and $url
    • Change the default value of basePort from false to null
    • Remove the getRoutePayload() methods on the BladeRouteGenerator and CommandRouteGenerator classes
  • ⚠️ Rename all whitelist and blacklist functionality to only and except (#300)
  • Use Jest instead of Mocha for JS tests (#309)
  • Use microbundle instead of Webpack to build and distribute Ziggy (#312)
  • ⚠️ Default Ziggy's baseUrl to the value of the APP_URL environment variable instead of url('/') (#334)
  • ⚠️ Return a literal string from the route() function when any arguments are passed to it (#336)
  • ⚠️ Rename namedRoutesroutes, defaultParametersdefaults, baseUrlurl, and basePortport (#338)
  • ⚠️ Make the filter() method on the Ziggy class return an instance of that class instead of a collection of routes (#341)
  • ⚠️ Make the nameKeyedRoutes(), resolveBindings(), applyFilters(), and group() methods on the Ziggy class, and the generate() method on the CommandRouteGenerator class, private (#341)
  • ⚠️ Export from index.js instead of route.js (#344)
  • ⚠️ Encode boolean query parameters as integers (#345)
  • ⚠️ Ensure .current() respects the value of the absolute option (#353)

Deprecated

  • Deprecate the with() and check() methods (#330)

Removed

  • ⚠️ Remove Route Facade macros Route::only() and Route::except() (previously Route::whitelist() and Route::blacklist()) (#306)
  • ⚠️ Remove the following undocumented public properties and methods from the Router class returned by the route() function (#330):
    • name, absolute, ziggy, urlBuilder, template, urlParams, queryParams, and hydrated
    • normalizeParams(), hydrateUrl(), matchUrl(), constructQuery(), extractParams(), parse(), and trimParam()
  • ⚠️ Remove the UrlBuilder class (#330)
  • ⚠️ Remove the url() method now that route(...) returns a string (#336)
  • ⚠️ Remove the baseDomain and baseProtocol properties on the Ziggy config object (#337)
  • ⚠️ Remove the appendRouteToList(), isListedAs(), except(), and only() methods from the Ziggy class (#341)

Fixed

  • Fix automatic id parameter detection by also excluding routes with an optional id parameter ({id?}), thanks @Livijn! (#263)
  • Fix port not being added to URL for routes with subdomains (#293)
  • Fix getting parameters of routes in apps installed in subfolders (#302)
  • Ensure fallback routes are always last, thanks @davejamesmiller! (#310)
  • Allow getting the route name with current() when the current URL has a query string (#330)

v0.9.4 - 2020-06-05

Fixed

v0.9.3 - 2020-05-08

Added

  • Add support for passing a CSP nonce attribute to the @routes Blade directive to be set on the script tag, thanks @tminich! (#287)

Changed

  • Improve support for using Ziggy with server-side rendering, thanks @emielmolenaar! (#260)
  • Avoid resolving the Blade compiler unless necessary, thanks @axlon! (#267)
  • Use dist/js/route.js as the npm package's main target, thanks @ankurk91 and @benallfree! (#276)
  • Readme and quality-of-life improvements (#289)

Fixed

  • Ensure Ziggy's assets are always generated in the correct location (#290)

For previous changes see the Releases page.