logo

菜单

概述

默认情况下,Nova 的左侧主导航菜单会显示应用程序的所有仪表板、资源以及你已注册的任何自定义工具。

Default Menu

在呈现主菜单时,Nova 将根据应用程序的 App\Providers\NovaServiceProvider 类中的 dashboards 方法返回的仪表盘顺序来排列仪表盘。

Nova 还将根据 Resource 类中定义的 group 属性 自动将您的资源分组到默认的「资源」菜单部分下。此外,你注册的任何自定义工具都将按照应用程序的 NovaServiceProvider 中定义的顺序列出。

自定义主菜单

虽然 Nova 的默认主菜单足以满足大多数应用程序的需求,但有时你可能希望根据自己的喜好完全自定义菜单。因此,Nova 允许你通过 Nova::mainMenu 方法定义自己的主菜单。通常,应在应用程序的 App\Providers\NovaServiceProvider 类的 boot 方法中调用此方法:

php
<?php

namespace App\Providers;

use App\Nova\License;
use App\Nova\Release;
use App\Nova\Series;
use App\Nova\User;
use Illuminate\Http\Request;
use Laravel\Nova\Dashboards\Main;
use Laravel\Nova\Menu\Menu;
use Laravel\Nova\Menu\MenuItem;
use Laravel\Nova\Menu\MenuSection;
use Laravel\Nova\Nova;
use Laravel\Nova\NovaApplicationServiceProvider;

class NovaServiceProvider extends NovaApplicationServiceProvider
{
    /**
     * 引导任何应用服务。
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        Nova::mainMenu(function (Request $request) {
            return [
                MenuSection::dashboard(Main::class)->icon('chart-bar'),

                MenuSection::make('Customers', [
                    MenuItem::resource(User::class),
                    MenuItem::resource(License::class),
                ])->icon('user')->collapsable(),

                MenuSection::make('Content', [
                    MenuItem::resource(Series::class),
                    MenuItem::resource(Release::class),
                ])->icon('document-text')->collapsable(),
            ];
        });
    }
}

Custom Menu

自定义用户菜单

Nova 还允许你自定义右上角导航区域的「用户」菜单。你可以通过调用 Nova::userMenu 方法自定义 Nova 的用户菜单。该方法通常在应用程序的 App\Providers\NovaServiceProviderboot 方法中调用:

php
<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Laravel\Nova\Menu\Menu;
use Laravel\Nova\Menu\MenuItem;
use Laravel\Nova\Nova;
use Laravel\Nova\NovaApplicationServiceProvider;

class NovaServiceProvider extends NovaApplicationServiceProvider
{
    /**
     * 引导任何应用服务。
     *
     * @return void
     */
    public function boot()
    {
        Nova::userMenu(function (Request $request, Menu $menu) {
            if ($request->user()->subscribed()) {
                $menu->append(
                    MenuItem::make('Subscriber Dashboard')
                        ->path('/subscribers/dashboard')
                );
            }

            $menu->prepend(
                MenuItem::make(
                    'My Profile',
                    "/resources/users/{$request->user()->getKey()}"
                )
            );

            return $menu;
        });
    }
}

用户菜单注销链接

默认情况下,Nova 配置为在用户菜单中显示「注销」链接。此链接不可删除。

用户菜单项

Nova 的用户菜单只支持 MenuItem 对象。在用户菜单内使用 MenuSectionMenuGroup 会引发 Exception 异常。

追加/预置菜单

你可以调用 Menu 实例上的 appendprepend 方法来预先添加或追加新项目。这些方法通常在定制用户菜单时最有用,因为您通常不想完全替换现有菜单:

php
Nova::userMenu(function (Request $request, Menu $menu) {
    return $menu
        ->append(MenuItem::externalLink('API Docs', 'http://example.com'))
        ->prepend(MenuItem::link('My Profile', '/resources/users/'.$request->user()->getKey()));
    });

菜单栏目

菜单部分代表一个顶级导航项目,通常与代表菜单中项目类型的相应图标一起显示。你可以通过调用 MenuSection::make 方法创建一个新的菜单部分。该方法接受菜单部分的名称和应放置在该部分中的菜单组/项目数组:

php
use App\Nova\Dashboards\Sales;
use App\Nova\Lenses\MostValuableUsers;
use App\Nova\License;
use App\Nova\Refund;
use App\Nova\User;
use Illuminate\Http\Request;
use Laravel\Nova\Menu\Menu;
use Laravel\Nova\Menu\MenuGroup;
use Laravel\Nova\Menu\MenuItem;
use Laravel\Nova\Menu\MenuSection;
use Laravel\Nova\Nova;

Nova::mainMenu(function (Request $request, Menu $menu) {
    return [
        MenuSection::make('Business', [
            MenuGroup::make('Licensing', [
                MenuItem::dashboard(Sales::class),
                MenuItem::resource(License::class),
                MenuItem::resource(Refund::class),
                MenuItem::externalLink('Stripe Payments', 'https://dashboard.stripe.com/payments?status%5B%5D=successful'),
            ]),

            MenuGroup::make('Customers', [
                MenuItem::lens(User::class, MostValuableUsers::class),
            ]),
        ]),
    ];
});

与显示链接列表不同,你可以指出菜单部分应该只是一个指向另一个位置的大而突出的链接。为此,你可以在定义菜单部分时调用 path 方法:

php
use Laravel\Nova\Menu\MenuSection;

MenuSection::make('Dashboard')->path('/dashboards/main')

为方便起见,如果你创建的菜单部分只是作为指向 Nova 面板的大型强调链接,你可以调用MenuSection::dashboard方法:

php
use App\Nova\Dashboards\Sales;
use Laravel\Nova\Menu\MenuSection;

MenuSection::dashboard(Sales::class),

由于你经常要创建指向 Nova 资源的链接,因此可以使用 resource 方法快速创建指向给定资源的适当路径的链接:

php
use App\Nova\User;
use Laravel\Nova\Menu\MenuSection;

MenuSection::resource(User::class)

同样,你也可以通过 lens 方法创建指向 Nova 镜头的链接:

php
use App\Nova\Lenses\MostValuableUsers;
use App\Nova\User;
use Laravel\Nova\Menu\MenuSection;

MenuSection::lens(User::class, MostValuableUsers::class)

作为链接的菜单部分

定义为 collapseable 的菜单部分不支持同时作为链接。当菜单部分为 collapseable 时,在其上调用 path 将导致不显示链接。

菜单栏目图标

你可以在定义菜单部分时调用 icon 方法,自定义菜单部分显示的图标:

php
use Laravel\Nova\Menu\MenuSection;

MenuSection::make('Resources', [
    // 项目
])->icon('briefcase')

Nova 使用由 Steve Schoger 制作的免费 Heroicons 图标集。因此,在向 icon 方法提供图标名称时,只需指定其中一个图标的名称即可。

菜单栏目徽章

你可以通过调用 MenuSection 上的 withBadge 方法并指定徽章的选项,为菜单部分添加可视化徽章:

php
use App\Models\Issue;
use Laravel\Nova\Menu\MenuSection;
use Laravel\Nova\Badge;

// 直接传递字符串
MenuSection::make('New Issues')
    ->path('/resources/issues/lens/new-issues')
    ->withBadge('New!', 'success')
    ->icon('document-text')

// 直接传递 Laravel\Nova\Badge 实例
MenuSection::make('New Issues')
    ->path('/resources/issues/lens/new-issues')
    ->withBadge(Badge::make('New!', 'info'))
    ->icon('document-text')

// 使用闭包解决值问题
MenuSection::make('New Issues')
    ->path('/resources/issues/lens/new-issues')
    ->withBadge(fn () => Issue::count(), 'warning')
    ->icon('document-text')

按照条件显示徽章

使用 withBadgeIf 方法,可以有条件地添加徽章,前提是满足给定条件:

php
use App\Models\Issue;
use Laravel\Nova\Menu\MenuSection;
use Laravel\Nova\Badge;

// 直接传递字符串...
MenuSection::make('New Issues')
    ->path('/resources/issues/lens/new-issues')
    ->withBadgeIf('New!', 'info', fn () => Issue::count() > 0)

// 传递 Laravel\Nova\Badge 实例...
MenuSection::make('New Issues')
    ->path('/resources/issues/lens/new-issues')
    ->withBadgeIf(Badge::make('New!', 'info'), fn () => Issue::count() > 0)

// 使用闭包解决值问题...
MenuSection::make('New Issues')
    ->path('/resources/issues/lens/new-issues')
    ->withBadgeIf(fn() => 'New!', 'info', fn () => Issue::count() > 0)

可折叠菜单栏目

你可以在定义菜单部分时调用 collapsable 方法,使你的菜单部分可折叠。为方便起见,Nova 会在两次请求之间记住部分的打开状态:

php
use Laravel\Nova\Menu\MenuSection;

MenuSection::make('Resources', [
    //
])->collapsable()

菜单组

有时,你可能需要在菜单部分和菜单项之间增加一个逻辑层次。在这种情况下,菜单组就是完美的解决方案。通过菜单组,你可以在各自强调的标题下对菜单项进行分组:

php
use App\Nova\Dashboards\Sales;
use App\Nova\License;
use App\Nova\Refund;
use Illuminate\Http\Request;
use Laravel\Nova\Menu\MenuGroup;
use Laravel\Nova\Menu\MenuItem;
use Laravel\Nova\Menu\MenuSection;

MenuSection::make('Business', [
    MenuGroup::make('Licensing', [
        MenuItem::dashboard(Sales::class),
        MenuItem::resource(License::class),
        MenuItem::resource(License::class),
        MenuItem::externalLink('Stripe Payments', 'https://dashboard.stripe.com/payments?status%5B%5D=successful'),
    ]),
]),

可折叠菜单组

你可以通过调用组上的 collapsable 方法使您的菜单组可折叠。为方便起见,Nova 会在两次请求之间记住组的打开状态:

php
MenuGroup::make('Resources', [
    //
])->collapsable()

菜单项目

菜单项表示可添加到自定义 Nova 菜单的应用程序内部和外部区域的不同类型链接。Nova 提供了几种方便的方法来创建不同类型的菜单项。

首先,要创建指向 Nova 内部区域的链接,可以调用 MenuItem 类上的 link 方法:

php
use Laravel\Nova\Menu\MenuItem;

MenuItem::link('Cashier', '/cashier')

资源菜单项

由于你经常要创建指向 Nova 资源的链接,因此可以使用 resource 方法快速创建指向给定资源的适当路径的链接:

php
use App\Nova\User;
use Laravel\Nova\Menu\MenuItem;

MenuItem::resource(User::class)

过滤器资源菜单项

要创建一个应用了预定义过滤器的 Nova 资源链接,可以使用 filter 方法,传入过滤器的实例和应接收的值。由于过滤器可用于多个资源,你还必须为菜单项传递一个名称,因为它不会自动生成:

php
use App\Nova\User;
use Laravel\Nova\Menu\MenuItem;
use \App\Nova\Filters\NameFilter;

MenuItem::filter('Filtered Users', User::class, NameFilter::make(), 'Hemp');

通过过滤资源菜单项使用多个过滤器

你还可以向一个资源菜单项传递多个过滤器。例如,假设你想创建一个菜单项,链接到 User 资源,显示电子邮件以 @laravel.com 结尾且状态为 active 的用户:

php
use App\Nova\User;
use Laravel\Nova\Menu\MenuItem;
use \App\Nova\Filters\EmailFilter;
use \App\Nova\Filters\StatusFilter;

MenuItem::filter('Filtered Users', User::class)
    ->applies(EmailFilter::make(), '@laravel.com')
    ->applies(StatusFilter::make(), 'active');

将构造函数参数传递给过滤资源菜单项

Nova 过滤器还可以接收构造函数参数,以便在不同资源中重复使用过滤器。要在创建过滤资源菜单项时传递参数,只需将参数提供给过滤器的 make 方法即可:

php
use App\Nova\User;
use Laravel\Nova\Menu\MenuItem;
use App\Nova\Filters\ColumnFilter;

MenuItem::filter('Active Laravel Users', User::class)
    ->applies(ColumnFilter::make('name'), 'Hemp');

镜头菜单项

你也可以通过 lens 方法创建指向 Nova 镜头的链接:

php
use App\Nova\Lenses\MostValuableUsers;
use App\Nova\User;
use Laravel\Nova\Menu\MenuItem;

MenuItem::lens(User::class, MostValuableUsers::class)

仪表板菜单项

你也可以通过调用 dashboard 方法来创建指向任何 自定义 Nova 仪表板 的链接:

php
use App\Nova\Dashboards\Main;
use Laravel\Nova\Menu\MenuItem;

MenuItem::dashboard(Main::class)

外部链接菜单项

要创建一个将用户引导到 Nova 应用程序完全外部位置的链接,可以使用 externalLink 工厂方法:

php
use Laravel\Nova\Menu\MenuItem;

MenuItem::externalLink('Documentation', 'https://nova.laravel.com/docs')

要指定外部链接应在单独的标签页中打开,可以在菜单项上调用 openInNewTab 方法:

php
MenuItem::externalLink('Documentation', 'https://nova.laravel.com/docs')->openInNewTab();

你还可以调用 method 辅助器来传递 HTTP 方法、请求数据以及点击链接时应发送到应用程序的任何 HTTP 头信息。这通常对注销链接等项目非常有用,因为这些链接应该是 POST 请求:

php
use Laravel\Nova\Menu\MenuItem;

MenuItem::externalLink('Logout', 'https://api.yoursite.com/logout')
    ->method(
        'POST',
        data: ['user' => 'hemp'],
        headers: ['API_TOKEN' => 'abcdefg1234567']
    )

菜单项徽章

你可以通过调用 MenuItem 上的 withBadge 方法并指定徽章的选项,为菜单项添加可视化徽章:

php
use App\Nova\Dashboards\Issue;
use Laravel\Nova\Menu\MenuItem;
use Laravel\Nova\Badge;

// 直接传递字符串
MenuItem::dashboard(Issue::class)
    ->withBadge('New!', 'info')

// 直接传递 Laravel\Nova\Badge 实例
MenuItem::dashboard(Issue::class)
    ->withBadge(Badge::make('New!', 'info'))

// 使用闭包解决值问题
MenuItem::dashboard(Issue::class)
    ->withBadge(fn() => 13, 'danger')

按照条件显示徽章

你也可以有条件地添加徽章,但必须满足条件。

php
use App\Nova\Issue;
use Laravel\Nova\Menu\MenuItem;

// 直接传递字符串
MenuItem::resource(Issue::class)
    ->withBadgeIf('New!', 'info', fn() => Issue::newModel()->count() > 0)

// 直接传递 Laravel\Nova\Badge 实例
MenuItem::resource(Issue::class)
    ->withBadgeIf(Badge::make('New!', 'info'), fn() => Issue::newModel()->count() > 0)

// 使用闭包解决值问题
MenuItem::resource(Issue::class)
    ->withBadgeIf(fn() => 'New!', 'info', fn() => Issue::newModel()->count() > 0)

授权菜单项目

你可以使用 canSee 方法来确定是否应向当前已通过身份验证的用户显示菜单项:

php
MenuItem::link('Cashier', '/cashier')
    ->canSee(function (NovaRequest $request) {
        return $request->user()->can('manageCashier');
    })