piksera/ziggy

生成一个Blade指令,导出你所有的命名Laravel路由。同时提供一个在JavaScript中的route()助手函数。

安装: 5

依赖: 0

建议者: 0

安全: 0

星星: 0

关注者: 1

分支: 0

公开问题: 0

语言:JavaScript

dev-main 2024-09-07 08:38 UTC

This package is auto-updated.

Last update: 2024-09-07 08:40:23 UTC


README

Ziggy - Use your Laravel named routes in JavaScript

Ziggy – 在JavaScript中使用你的Laravel路由

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

Ziggy提供了一个JavaScript route()助手函数,其工作方式类似于Laravel的,使得在JavaScript中使用你的Laravel命名路由变得容易。

Ziggy支持从5.4版本开始的所有Laravel版本,以及所有现代浏览器。

安装

使用composer require tightenco/ziggy将Ziggy安装到你的Laravel应用中。

将@routes Blade指令添加到你的主布局(在应用JavaScript之前),现在全局范围内将可以使用route()助手函数!

默认情况下,@routes Blade指令的输出包括应用程序所有路由及其参数的列表。此路由列表包含在页面HTML中,可以被最终用户查看。要配置包含在此列表中的路由,或在不同的页面上显示和隐藏不同的路由,请参阅过滤路由

使用

route()助手函数

Ziggy的route()助手函数与Laravel的route()助手函数类似——你可以传递一个路由的名称和你想要传递给路由的参数,它将返回一个URL。

基本用法

// routes/web.php

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

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

带参数

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

带多个参数

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

带查询参数

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

如果你有一个与路由参数同名查询参数,请将其嵌套在_query键下

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

与Laravel的route()助手函数类似,Ziggy自动将布尔查询参数编码为查询字符串中的整数

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

带默认参数值

请参阅Laravel关于默认路由参数值的文档

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

实际的AJAX示例

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

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

Router类

不带参数调用Ziggy的route()助手函数将返回JavaScript Router类的实例,该类具有一些其他有用的属性和方法。

检查当前路由: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

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

检查是否存在路由:route().has()

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

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

检索当前路由参数: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' }

注意:使用route().params检索到的参数值始终以字符串的形式返回。

路由模型绑定

Ziggy支持Laravel的路由模型绑定,甚至可以识别自定义路由键名称。如果你将JavaScript对象作为route()的其中一个路由参数传递,Ziggy将使用已注册的路由模型绑定键来查找对象中的参数值,并将其插入到URL中(如果路由模型绑定键不存在,则回退到id键)。

// 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 还支持在路由定义中为范围绑定使用自定义键 自定义键(需要 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支持

非官方的 Ziggy TypeScript 类型定义由 benallfree 维护,作为 Definitely Typed 的一部分,可以通过 npm install @types/ziggy-js 安装。

高级设置

JavaScript框架

如果您不使用 Blade 或不希望使用 @routes 指令,Ziggy 提供了一个 Artisan 命令来输出其配置和路由到文件:php artisan ziggy:generate。默认情况下,此命令将您的路由存储在 resources/js/ziggy.js 中,但您可以通过传递不同的值作为 Artisan 命令的参数或设置 ziggy.output.path 配置值来自定义此路径。或者,您可以从 Laravel API 的端点返回 Ziggy 的配置作为 JSON(见下文 从 API 端点检索 Ziggy 的路由和配置 中的示例,了解如何设置此功能)。

php artisan ziggy:generate 生成的文件将类似于以下内容

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

您可以创建一个别名来简化导入 Ziggy 的核心源文件

// 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'),
        },
    },
});

最后,像其他 JavaScript 库一样导入和使用 Ziggy。由于 Ziggy 配置对象在此设置中不可用全局,您通常必须手动将配置对象传递给 route() 函数

// app.js

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

// ...

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

Vue

Ziggy 包含一个 Vue 插件,使您可以在 Vue 应用程序中轻松使用 route() 助手

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);

如果您使用上述 ziggy 导入别名,请确保将其更新为 vendor/tightenco/ziggy/dist/vue.es.js(Vite)或 vendor/tightenco/ziggy/dist/vue(Laravel Mix)。

注意:如果您在视图中使用 @routes Blade 指令,Ziggy 的配置将已经在全局范围内可用,因此您不需要导入 Ziggy 配置对象并将其传递给 use()

现在您可以在 Vue 组件和模板中的任何位置使用 route(),如下所示

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

React

要使用 React 与 Ziggy,首先导入 route() 函数和您的 Ziggy 配置。由于 Ziggy 配置对象在此设置中不可用全局,您必须手动将配置对象传递给 route() 函数

// app.js

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

// ...

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

我们正在努力为 Ziggy 添加一个 Hook 来使其更简洁,但到目前为止,请确保将配置对象作为上面显示的 route() 函数的第四个参数传递。

注意:如果您在视图中包含 @routes Blade 指令,则 route 助手将已经在全局范围内可用,包括在您的 React 应用程序中,因此您不需要在任何地方导入 routeZiggy

SPA或单独的仓库

Ziggy 的 route() 助手函数也作为 NPM 包提供,用于管理独立于 Laravel 后端的 JavaScript 项目(即,没有 Composer 或 vendor 目录)。您可以使用 npm install ziggy-js 安装此 NPM 包。

为了使此函数可用,您的路由在前端可用,您可以运行 php artisan ziggy:generate 并将生成的路由文件添加到项目中,或者您可以从 Laravel API 的端点返回 Ziggy 的配置作为 JSON(见下文 从 API 端点检索 Ziggy 的路由和配置 中的示例,了解如何设置此功能)。

然后,像上面一样导入和使用 Ziggy

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

过滤路由

Ziggy 支持过滤提供给您的 JavaScript 的路由,这对于您不想包含在发送回客户端的响应源中的某些路由非常有用。过滤路由是可选的——默认情况下,Ziggy 包含您应用程序的所有命名路由。

基本过滤

为了设置基本的路由过滤,在你的 Laravel 应用中创建一个名为 config/ziggy.php 的配置文件,并定义一个 以下列之一作为路由名称模式数组的 onlyexcept 设置。

注意:您必须选择其中之一。同时设置 onlyexcept 将完全禁用过滤并返回所有命名路由。

// config/ziggy.php

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

您还可以在路由过滤器中使用星号作为通配符。在下面的示例中,admin.* 将排除名为 admin.loginadmin.register 的路由。

// config/ziggy.php

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

使用分组进行过滤

您还可以使用配置文件中的 groups 键定义您希望在不同位置可用的路由组。

// config/ziggy.php

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

然后,您可以通过将组名传递给 @routes Blade 指令来公开特定的组。

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

@routes('author')

要公开多个组,您可以传递一个组名数组。

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

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

注意:将组名传递给 @routes 指令将始终优先于您的其他 onlyexcept 设置。

其他

TLS/SSL 终止和受信任的代理

如果您的应用程序使用 TLS/SSL 终止 或位于负载均衡器或代理后面,或者托管在提供此类服务的平台上,Ziggy 可能会生成使用 http 而不是 https 方案的 URL,即使您的应用程序 URL 使用 https。为了避免这种情况,请根据 配置受信任的代理 的文档设置您的 Laravel 应用程序的 TrustProxies 中间件。

使用 @routes 与内容安全策略

内容安全策略(CSP)可能会阻止内联脚本,包括 Ziggy 的 @routes Blade 指令输出的脚本。如果您有一个 CSP 并使用 nonce 标记安全的内联脚本,您可以传递 nonce 作为 @routes 指令的第二个参数,它将被添加到 Ziggy 的脚本标签中。

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

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

禁用 route() 辅助函数

如果您只想使用 @routes 指令来在 JavaScript 中公开您的应用程序的路由,但不需要 route() 辅助函数,请将 skip-route-function 配置值设置为 true

// config/ziggy.php

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

从 API 端点检索 Ziggy 的路由和配置

Ziggy 可以轻松地从 Laravel 应用程序的端点返回其配置对象作为 JSON。例如,您可以设置一个类似下面的 /api/ziggy 路由:

// routes/api.php

use Tightenco\Ziggy\Ziggy;

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

然后,客户端可以使用 HTTP 请求检索配置

// app.js

import route from 'ziggy-js';

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

// ...

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

当您的应用程序路由更改时重新生成路由文件

如果您通过运行 php artisan ziggy:generate 将 Ziggy 路由导出为文件,您可能希望监视应用程序的路由文件,并在它们更新时自动重新运行命令。下面的示例是 Laravel Mix 插件,但可以在不使用 Mix 的情况下实现类似的功能。感谢 Nuno Rodrigues 提供了 想法和示例实现

代码示例

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();

贡献

要开始为 Ziggy 贡献,请查看 贡献指南

致谢

感谢 Caleb PorzioAdam WathanJeffrey Way 帮助巩固这一想法。

安全

请查看我们如何报告安全漏洞的 安全策略

许可协议

Ziggy 是在 MIT 许可下发布的开源软件。有关更多信息,请参阅 LICENSE