• Stars
    star
    3,816
  • Rank 11,535 (Top 0.3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Use your Laravel routes in JavaScript.

Ziggy - Use your Laravel named 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() helper function that works like Laravel's, making it easy to use your Laravel named routes in JavaScript.

Ziggy supports all versions of Laravel from 5.4 onward, and all modern browsers.

Installation

Install Ziggy into your Laravel app with composer require tightenco/ziggy.

Add the @routes Blade directive to your main layout (before your application's JavaScript), and the route() helper function will now 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

The route() helper

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

Basic usage

// routes/web.php

Route::get('posts', fn (Request $request) => /* ... */)->name('posts.index');
// app.js

route('posts.index'); // 'https://ziggy.test/posts'

With parameters

// routes/web.php

Route::get('posts/{post}', fn (Request $request, Post $post) => /* ... */)->name('posts.show');
// app.js

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'

With multiple parameters

// routes/web.php

Route::get('events/{event}/venues/{venue}', fn (Request $request, Event $event, Venue $venue) => /* ... */)->name('events.venues.show');
// app.js

route('events.venues.show', [1, 2]);                 // 'https://ziggy.test/events/1/venues/2'
route('events.venues.show', { event: 1, venue: 2 }); // 'https://ziggy.test/events/1/venues/2'

With query parameters

// routes/web.php

Route::get('events/{event}/venues/{venue}', fn (Request $request, Event $event, Venue $venue) => /* ... */)->name('events.venues.show');
// app.js

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

If you have a query parameter with the same name as a route parameter, nest it under a _query key:

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

Like Laravel's route() helper, Ziggy automatically encodes boolean query parameters as integers in the query string:

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

With default parameter values

See the Laravel documentation on default route parameter values.

// routes/web.php

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

URL::defaults(['locale' => $request->user()->locale ?? 'de']);
// app.js

route('posts.show', 1); // 'https://ziggy.test/de/posts/1'

Practical AJAX example

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

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

The Router class

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

Checking the current route: route().current()

// 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

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

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

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

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

// App has only one named route, 'home'

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

Retrieving the current route params: route().params

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

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

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

Route-model binding

Ziggy supports Laravel route-model binding, and can even recognize custom route key names. If you pass route() a JavaScript object as one of the route parameters, Ziggy will use the registered route-model binding keys for that route to find the parameter value in the object and insert it into the URL (falling back to an id key if there is one and the route-model binding key isn't present).

// app/Models/Post.php

class Post extends Model
{
    public function getRouteKeyName()
    {
        return 'slug';
    }
}
// app/Http/Controllers/PostController.php

class PostController
{
    public function show(Request $request, Post $post)
    {
        return view('posts.show', ['post' => $post]);
    }
}
// routes/web.php

Route::get('blog/{post}', [PostController::class, 'show'])->name('posts.show');
// app.js

const post = {
    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 name:

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

Ziggy also supports custom keys for scoped bindings in the route definition (requires Laravel 7+):

// routes/web.php

Route::get('authors/{author}/photos/{photo:uuid}', fn (Request $request, Author $author, Photo $photo) => /* ... */)->name('authors.photos.show');
// app.js

const photo = {
    uuid: '714b19e8-ac5e-4dab-99ba-34dc6fdd24a5',
    filename: 'sunset.jpg',
}

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

TypeScript support

Unofficial TypeScript type definitions for Ziggy are maintained by benallfree as part of Definitely Typed, and can be installed with npm install @types/ziggy-js.

Advanced Setup

JavaScript frameworks

If you are not using Blade, or would prefer not to use the @routes directive, Ziggy provides an Artisan command to output its config and routes to a file: php artisan ziggy:generate. By default this command stores your routes at resources/js/ziggy.js, but you can customize this path by passing a different value as an argument to the Artisan command or setting the ziggy.output.path config value. Alternatively, you can return Ziggy's config as JSON from an endpoint in your Laravel API (see Retrieving Ziggy's routes and config from an API endpoint below for an example of how to set this up).

The file generated by php artisan ziggy:generate will look something like this:

// ziggy.js

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

export { Ziggy };

You can optionally create an alias to make importing Ziggy's core source files easier:

// vite.config.js
export default defineConfig({
    resolve: {
        alias: {
            ziggy: 'vendor/tightenco/ziggy/dist',
            // 'vendor/tightenco/ziggy/dist/vue.es.js' if using the Vue plugin
        },
    },
});
// webpack.mix.js

// Mix v6
const path = require('path');

mix.alias({
    ziggy: path.resolve('vendor/tightenco/ziggy/dist'),
    // 'vendor/tightenco/ziggy/dist/vue' if using the Vue plugin
});

// Mix v5
const path = require('path');

mix.webpackConfig({
    resolve: {
        alias: {
            ziggy: path.resolve('vendor/tightenco/ziggy/dist'),
        },
    },
});

Finally, import and use Ziggy like any other JavaScript library. Because the Ziggy config object is not available globally in this setup, you'll usually have to pass it to the route() function manually:

// app.js

import route from 'ziggy';
import { Ziggy } from './ziggy';

// ...

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

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';
import { Ziggy } from './ziggy';
import App from './App';

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

// Vue 2
import Vue from 'vue'
import { ZiggyVue } from 'ziggy';
import { Ziggy } from './ziggy';

Vue.use(ZiggyVue, Ziggy);

If you use this plugin with the ziggy import alias shown above, make sure to update the alias to vendor/tightenco/ziggy/dist/vue.es.js (Vite) or vendor/tightenco/ziggy/dist/vue (Laravel Mix).

Note: If you use the @routes Blade directive in your views, Ziggy's configuration will already be available globally, so you don't need to import the Ziggy config object and pass it into use().

Now you can use route() anywhere in your Vue components and templates, like so:

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

React

To use Ziggy with React, start by importing the route() function and your Ziggy config. Because the Ziggy config object is not available globally in this setup, you'll have to pass it to the route() function manually:

// app.js

import route from 'ziggy';
import { Ziggy } from './ziggy';

// ...

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

We're working on adding a Hook to Ziggy to make this cleaner, but for now make sure you pass the configuration object as the fourth argument to the route() function as shown above.

Note: If you include the @routes Blade directive in your views, the route() helper will already be available globally, including in your React app, so you don't need to import route or Ziggy anywhere.

SPAs or separate repos

Ziggy's route() helper function is also 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 routes file to your project, or you can return Ziggy's config as JSON from an endpoint in your Laravel API (see Retrieving Ziggy's routes and config from an API endpoint below for an example of how to set this up).

Then, import and use Ziggy as above:

// app.js

import route from 'ziggy-js';

import { Ziggy } from './ziggy';
// or...
const response = await fetch('/api/ziggy');
const Ziggy = await response.json();

// ...

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

Filtering Routes

Ziggy supports filtering the routes it makes available to your JavaScript, which is great if you have certain routes that you don't want to be included and visible in the source of the response sent back to clients. Filtering routes is optional—by default, Ziggy includes all your application's named routes.

Basic filtering

To set up basic route filtering, create a config file in your Laravel app at config/ziggy.php and define either an only or except setting as 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 also use asterisks as wildcards in route filters. In the example below, admin.* will exclude routes named admin.login and admin.register:

// config/ziggy.php

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

Filtering using 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 avoid this happening, set up your Laravel app's TrustProxies middleware 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 as as the second argument to the @routes directive and it will be added to Ziggy's script tag:

// PHP ^8.0
@routes(nonce: 'your-nonce-here')

// PHP <=7.4
@routes(null, 'your-nonce-here')

Disabling the route() helper

If you only want to use the @routes directive to make your app's routes available in JavaScript, but don't need the route() helper function, set the skip-route-function config value to true:

// config/ziggy.php

return [
    'skip-route-function' => true,
];

Retrieving Ziggy's routes and config from an API endpoint

Ziggy can easily return its config object as JSON from an endpoint in your Laravel app. For example, you could set up an /api/ziggy route that looks something like this:

// routes/api.php

use Tightenco\Ziggy\Ziggy;

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

Then, client-side, you could retrieve the config with an HTTP request:

// app.js

import route from 'ziggy-js';

const response = await fetch('/api/ziggy');
const Ziggy = await response.toJson();

// ...

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

Re-generating the routes file when your app routes change

If you're exporting your Ziggy routes as a file by running php artisan ziggy:generate, you may want to watch your app's route files and re-run the command automatically whenever they're updated. 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!

Code example

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.

More Repositories

1

jigsaw

Simple static sites with Laravel’s Blade.
PHP
2,115
star
2

takeout

Docker-based development-only dependency manager. macOS, Linux, and WSL2-only and installs via PHP's Composer... for now.
PHP
1,590
star
3

collect

A Collections-only split from Laravel's Illuminate Support
PHP
1,506
star
4

parental

Use single table inheritance in your Laravel app
PHP
1,327
star
5

mailthief

A fake mailer for Laravel Applications for testing mail.
PHP
685
star
6

lambo

Quick new application creation with Laravel and Valet
PHP
612
star
7

tlint

Tighten linter for Laravel conventions.
PHP
517
star
8

duster

Automatic configuration for Laravel apps to apply Tighten's standard linting & code standards.
PHP
409
star
9

novapackages

PHP
334
star
10

quicksand

Easily schedule regular cleanup of old soft-deleted Eloquent data.
PHP
294
star
11

gistlog

GistLog - simple, easy blogging based on GitHub gists
CSS
274
star
12

symposium

Management of proposals, bios, photos, etc. for conference speakers.
PHP
177
star
13

nova-google-analytics

Google Analytics integration with Laravel Nova
PHP
161
star
14

onramp

Easing the onramp for new or non-PHP developers to become Laravel devs.
PHP
157
star
15

overload

Method overloading in PHP
PHP
115
star
16

nova-stripe

Easily show information about Stripe charges and balances in your Nova dashboard
JavaScript
103
star
17

giscus

Notifications for Gist Comments
PHP
103
star
18

laravelversions

PHP
94
star
19

jigsaw-blog-template

Starter template for a blog, using Jigsaw by Tighten
Blade
91
star
20

confomo

ConFOMO is a simple tool that makes it easy to track your friends at conferences.
JavaScript
74
star
21

ozzie

Open source project monitor for Tighten
PHP
56
star
22

nova-package-development

A forum for talking about the process of Nova Package Development
52
star
23

jigsaw-docs-template

Starter template for a documentation site, using Jigsaw by Tighten
Blade
44
star
24

craft-build-query

A plugin for Craft CMS, demonstrating how to build complex or optimized queries by modifying an ElementCriteriaModel.
PHP
39
star
25

liftoff

A quick start for Laravel development in a new environment
Shell
38
star
26

builtwithjigsaw

A list of sites built with Jigsaw
Blade
35
star
27

react-gif-search-engine

React GIF Search Engine
JavaScript
33
star
28

react-gif-search-engine-old

JavaScript
32
star
29

jigsaw-site

Jigsaw Documentation Site
Blade
30
star
30

blink-my-lights

Quick proof-of-concept for flashing/blinking lights with Laravel and IFTTT
PHP
26
star
31

laravelm1

Tracking what works and doesn't in the Laravel ecosystem on M1
Blade
25
star
32

configs

Standard config files for Tighten projects
PHP
24
star
33

built-with-laravel

Real organizations and companies building with Laravel.
PHP
24
star
34

nova-releases

A package to provide a card and a tool giving information about Nova releases, including whether you're current
Vue
20
star
35

consoles

Quick shortcut list to API developer consoles
PHP
19
star
36

json-api-examples

Implementing JSON:API in laravel
18
star
37

laravel-react-demo

Demo of how to include React components in a Laravel project with Elixir
PHP
17
star
38

laravel-mix-jigsaw

Laravel Mix plugin for Jigsaw.
JavaScript
16
star
39

nova-package-discovery

Nova card for showing stats from novapackages.com
PHP
16
star
40

simplecast-php

Simplecast PHP SDK
PHP
15
star
41

php-package-skeleton

Tighten's PHP Package skeleton -- inspired by & some source from spatie/skeleton-php
Shell
15
star
42

checkmate

Check the version of all your Laravel apps and notify if they're out of date
PHP
14
star
43

tighten-coding-standard

A PHP Code_Sniffer configuration for Tighten's coding standard.
PHP
14
star
44

saasaas

SaaSaaS - create your next "AirBnB for ___" idea
PHP
14
star
45

laravel-elixir-webpack-react

A package to provide support for compiling React JSX files in Laravel Elixir 6
JavaScript
13
star
46

podcast-subscriber

Easy podcast subscriber app
PHP
10
star
47

laravel-mix-react

Easy alternative Laravel Mix configuration for projects using React
JavaScript
10
star
48

laravel-preset-jest

Front-end presets that include Jest for React and Vue
PHP
9
star
49

laraveldrivers

List all third-party Laravel drivers
PHP
9
star
50

blade-style-guide

"PSR-Blade"--style guide for Laravel Blade
9
star
51

easy-embeddable-polls

easy-static-polls
Vue
8
star
52

valet-fallback

Fallback web site for Valet
PHP
8
star
53

phpreleases-action

GitHub action that integrates with the PHP Releases API.
7
star
54

dev-battle-1-react

Tighten Co. Senior Dev Battle - React app
PHP
7
star
55

dev-battle-1-vue

Tighten Co. Senior Dev Battle - Vue app[
JavaScript
6
star
56

duster-action

Dockerfile
6
star
57

react-native-time-input

A simple time input component with autoformatting.
TypeScript
6
star
58

jigsaw-collections-demo

CSS
5
star
59

tlint-plugin

TLint PHPStorm Plugin
Kotlin
4
star
60

gif-gif-vue

Samantha Geitz Jest testing in Vue Laracon talk
PHP
4
star
61

hyperspoon

Lua
4
star
62

gif-gif-react

React version of Samantha Geitz's Jest Testing Laracon talk
PHP
4
star
63

postit

PHP
3
star
64

laravel-elixir-elm

JavaScript
3
star
65

pickr-api

PHP
3
star
66

laravel-tricks

Laravel Tricks rewrite
PHP
3
star
67

tallstack

The new web site for tallstack.dev
PHP
2
star
68

jazz

JavaScript-inspired development utilities
PHP
2
star
69

nova-tighten-themes

Tighten's Nova Themes
CSS
2
star
70

learnwebdevelopment

LearnWebDevelopment.org
CSS
2
star
71

tlint-sublime-plugin

tlint-sublime-plugin
Python
2
star
72

intro-to-react

Intro to React workshop given by Samantha Geitz at PeersConf 2018
JavaScript
2
star
73

omgphp

OMGPHP.com
CSS
1
star
74

borsh-php

1
star
75

phpreleases

API endpoints with support information for PHP major/minor versions and releases 5.6 and later
PHP
1
star
76

pickr-nativescript

NativeScript version of Pickr for Tighten Dev Battle 2
CSS
1
star
77

automation-scripts

Lua
1
star
78

pickr-reactnative

JavaScript
1
star
79

mon-petit

PHP
1
star
80

whyphp

CSS
1
star
81

laravelstar

Vue
1
star
82

dev-battle-landing

Landing page for the Tighten Dev Battle
PHP
1
star