logo

基础知识

简介

Laravel Nova 是一个适用于 Laravel 应用程序的漂亮管理仪表盘。当然,Nova 的主要功能是使用 Eloquent 管理底层数据库记录。Nova 通过允许您定义与应用程序中每个 Eloquent 模型相对应的 Nova “资源”来实现此目的。

定义资源

默认情况下,Nova 资源存储在应用程序的 app/Nova 目录中。您可以使用 nova:resource Artisan 命令生成新资源

bash
php artisan nova:resource Post

资源最基本和最根本的属性是其 model 属性。此属性告诉 Nova 该资源对应哪个 Eloquent 模型

php
/**
 * The model the resource corresponds to.
 *
 * @var string
 */
public static $model = 'App\Models\Post';

新创建的 Nova 资源仅包含一个 ID 字段定义。别担心,我们很快就会为我们的资源添加更多字段。

保留的资源名称

Nova 包含一些保留字,不能用于资源名称

  • 卡片
  • 仪表盘
  • 字段
  • 模拟
  • 指标
  • 资源
  • 搜索
  • 脚本
  • 样式
  • 工具

注册资源

自动注册

默认情况下,app/Nova 目录中的所有资源都将自动注册到 Nova。您无需手动注册它们。

在资源在 Nova 仪表盘中可用之前,它们必须首先在 Nova 中注册。资源通常在应用程序的 app/Providers/NovaServiceProvider.php 文件中注册。此文件包含与 Nova 安装相关的各种配置和引导代码。

如上所述,您无需手动注册资源;但是,如果您选择这样做,可以通过覆盖 NovaServiceProviderresources 方法来实现.

手动注册资源有两种方法。您可以使用 resourcesIn 方法指示 Nova 注册给定目录中的所有 Nova 资源。或者,您可以使用 resources 方法手动注册各个资源

php
use App\Nova\User;
use App\Nova\Post;

/**
 * Register the application's Nova resources.
 *
 * @return void
 */
protected function resources()
{
    Nova::resourcesIn(app_path('Nova'));

    Nova::resources([
        User::class,
        Post::class,
    ]);
}

一旦您的资源在 Nova 中注册,它们将出现在 Nova 侧边栏中

Nova Dashboard

如果您不希望资源出现在侧边栏中,您可以覆盖资源类的 displayInNavigation 属性

php
/**
 * Indicates if the resource should be displayed in the sidebar.
 *
 * @var bool
 */
public static $displayInNavigation = false;

自定义资源菜单

您可以通过在资源类中定义 menu 方法来自定义资源的菜单

php
use Illuminate\Http\Request;

/**
 * Get the menu that should represent the resource.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Laravel\Nova\Menu\MenuItem
 */
public function menu(Request $request)
{
    return parent::menu($request)->withBadge(function () {
        return static::$model::count();
    });
}

有关更多信息,请参阅 菜单自定义 文档。

分组资源

如果您想将资源分成不同的侧边栏组,您可以覆盖资源类的 group 属性

php
/**
 * The logical group associated with the resource.
 *
 * @var string
 */
public static $group = 'Admin';

资源表样式自定义

Nova 支持对你的资源进行一些可视化自定义选项。

表格样式

有时在你的资源索引表中显示更多数据会很方便。为了实现这一点,你可以使用“紧凑”表格样式选项,它旨在增加表格行的可视化密度。要实现这一点,请覆盖你资源类中的静态 $tableStyle 属性或静态 tableStyle 方法

php
/**
 * The visual style used for the table. Available options are 'tight' and 'default'.
 *
 * @var string
 */
public static $tableStyle = 'tight';

这将以更少的可视化高度显示你的表格行,从而能够显示更多数据

Tight Table Style

列边框

你可以指示 Nova 显示列边框,方法是覆盖你资源类中的静态 $showColumnBorders 属性或静态 showColumnBorders 方法

php
/**
 * Whether to show borders for each column on the X-axis.
 *
 * @var bool
 */
public static $showColumnBorders = true;

将此属性设置为 true 将指示 Nova 在每个表格项上显示带边框的表格

Table Column Borders

资源表点击操作

默认情况下,当点击资源表行时,Nova 将导航到该资源的详细信息视图。但是,你可能希望 Nova 转而导航到编辑表单。你可以通过更改资源类上的 clickAction 属性来自定义此行为

php
/**
 * The click action to use when clicking on the resource in the table.
 *
 * Can be one of: 'detail' (default), 'edit', 'select', 'preview', or 'ignore'.
 *
 * @var string
 */
public static $clickAction = 'edit';

选择 select 选项将选中资源行的复选框。ignore 选项指示 Nova 完全忽略点击事件。

急切加载

如果你需要在你的字段、资源标题资源副标题中例行访问资源的关系,那么将该关系添加到你的资源的 with 属性中可能是一个好主意。此属性指示 Nova 在检索资源时始终急切加载列出的关系。

例如,如果你在 Post 资源的 subtitle 方法中访问了 Post 资源的 user 关系,则应将 user 关系添加到 Post 资源的 with 属性中

php
/**
 * The relationships that should be eager loaded on index queries.
 *
 * @var array
 */
public static $with = ['user'];

资源复制

有时,您可能希望在使用现有资源中的所有数据作为起点时创建一个新资源。Nova 的资源复制功能就是这样做的。在单击复制按钮后,您将被带到一个资源创建表单,其中所有复制资源的数据都已注入到表单中并准备进行调整

Resource Replication

要自定义复制模型,您可以在资源类上覆盖 replicate 方法

php
/**
 * Return a replicated resource.
 *
 * @return static
 *
 * @throws \InvalidArgumentException
 */
public function replicate()
{
    return tap(parent::replicate(), function ($resource) {
        $model = $resource->model();

        $model->name = 'Duplicate of '.$model->name;
    });
}

附件可能无法复制

使用 withFiles 方法的 MarkdownTrix 字段可能无法复制。

如果您需要存储对原始资源 ID 的引用,则可以访问复制请求中的 fromResourceId 值。通常,此值将从侦听模型的 creating 事件的事件侦听器或观察器中访问

php
namespace App\Observers;

use App\Models\Post;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Nova;

class PostObserver
{
    /**
     * Handle the creation of a new Post.
     *
     * @param  \App\Models\Post  $model
     * @return void
     */
    public function creating(Post $model): void
    {
        Nova::whenServing(function (NovaRequest $request) use ($model) {
            $model->parent_id = $request->input('fromResourceId');
        });
    }
}

资源事件

所有 Nova 操作都使用您熟悉的典型 savedeleteforceDeleterestore Eloquent 方法。因此,很容易侦听 Nova 触发的模型事件并对它们做出反应。最简单的方法是简单地将 Laravel 模型观察器附加到模型

php
namespace App\Providers;

use App\Models\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        User::observe(UserObserver::class);
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

如果您想附加一个仅在 Nova 相关的 HTTP 请求期间调用其方法的观察器,则可以使用 Laravel\Nova\Observable 类提供的 make 方法注册观察器。通常,这应该在应用程序的 NovaServiceProvider 中完成

php
use App\Models\User;
use Laravel\Nova\Observable;
use App\Observers\UserObserver;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    Observable::make(User::class, UserObserver::class);
}

或者,您可以在 Observer 本身中使用 Nova 的 whenServing 方法确定当前 HTTP 请求是否正在提供与 Nova 相关的请求

php
namespace App\Observers;

use App\Models\User;
use Illuminate\Http\Request;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Nova;

class UserObserver
{
    /**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */
    public function created(User $user)
    {
        Nova::whenServing(function (NovaRequest $request) use ($user) {
            // Only invoked during Nova requests...
        }, function (Request $request) use ($user) {
            // Invoked for non-Nova requests...
        });

        // Always invoked...
    }
}

资源挂钩

Nova 还允许您在资源上定义以下静态方法,作为仅在从 Laravel Nova 中执行相应资源操作时调用的挂钩

  • afterCreate
  • afterUpdate
  • afterDelete
  • afterForceDelete
  • afterRestore

例如,您可能希望在 Nova 中创建用户后发送电子邮件验证通知

php
use App\Models\User;
use App\Nova\Resource;
use Illuminate\Database\Eloquent\Model;
use Laravel\Nova\Http\Requests\NovaRequest;

class User extends Resource
{
    /**
     * Register a callback to be called after the resource is created.
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public static function afterCreate(NovaRequest $request, Model $model)
    {
        $model->sendEmailVerificationNotification();
    }
}

防止冲突

如果某个模型在 Nova 上次检索后已更新,Nova 将自动响应一个 409 冲突 HTTP 状态代码并显示错误消息,以防止意外的模型更改。如果在您在资源上打开“编辑”页面后,另一位用户更新了该模型,则可能会发生这种情况。此功能也称为 Nova “交通警察”。

禁用交通警察

如果您不关心防止冲突,可以通过在给定的资源类上将 trafficCop 属性设置为 false 来禁用交通警察功能

php
/**
 * Indicates whether Nova should check for modifications between viewing and updating a resource.
 *
 * @var bool
 */
public static $trafficCop = false;

如果您有更严格的自定义需求,还可以覆盖资源上的 trafficCop 方法,以确定是否应启用此功能

php
/**
 * Indicates whether Nova should check for modifications between viewing and updating a resource.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return  bool
*/
public static function trafficCop(Request $request)
{
    return static::$trafficCop;
}

时间同步

如果您在使用交通警察时遇到问题,您应该确保您的系统时间使用 NTP 正确同步。

资源轮询

Nova 可以自动在指定的时间间隔内获取资源的最新记录。要启用轮询,请覆盖资源类的 polling 属性

php
/**
 * Indicates whether the resource should automatically poll for new resources.
 *
 * @var bool
 */
public static $polling = true;

要自定义轮询间隔,您可以在资源类上覆盖 pollingInterval 属性,其中包含 Nova 在获取新资源记录之前应等待的秒数

php
/**
 * The interval at which Nova should poll for new resources.
 *
 * @var int
 */
public static $pollingInterval = 5;

切换资源轮询

默认情况下,当启用资源轮询时,一旦页面加载,就无法禁用它。您可以通过在资源类上将 showPollingToggle 属性设置为 true 来指示 Nova 为资源轮询显示一个开始/停止切换按钮

php
/**
 * Indicates whether to show the polling toggle button inside Nova.
 *
 * @var bool
 */
public static $showPollingToggle = true;

然后,Nova 将显示一个可单击按钮,您可以使用该按钮为资源启用/禁用轮询

Nova Resource Polling Toggle Button

重定向

Nova 允许您轻松自定义在执行资源操作(例如创建或更新资源)后将用户重定向到何处

在幕后,Nova 的重定向功能使用 Inertia.js 的 visit 方法。因此,重定向仅限于 Laravel Nova 中的路径。您可以调用 URL::remote 方法重定向到外部 URL

php
use Laravel\Nova\URL;

return URL::remote('https://nova.laravel.net.cn');

创建后重定向

你可以通过覆盖资源的 redirectAfterCreate 方法来定制用户在创建资源后被重定向到的位置

php
/**
 * Return the location to redirect the user after creation.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @param  \Laravel\Nova\Resource  $resource
 * @return \Laravel\Nova\URL|string
 */
public static function redirectAfterCreate(NovaRequest $request, $resource)
{
    return '/resources/'.static::uriKey().'/'.$resource->getKey();
}

更新后重定向

你可以通过覆盖资源的 redirectAfterUpdate 方法来定制用户在更新资源后被重定向到的位置

php
/**
 * Return the location to redirect the user after update.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @param  \Laravel\Nova\Resource  $resource
 * @return \Laravel\Nova\URL|string
 */
public static function redirectAfterUpdate(NovaRequest $request, $resource)
{
    return '/resources/'.static::uriKey().'/'.$resource->getKey();
}

删除后重定向

你可以通过覆盖资源的 redirectAfterDelete 方法来定制用户在删除资源后被重定向到的位置

php
/**
 * Return the location to redirect the user after deletion.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return \Laravel\Nova\URL|string|null
 */
public static function redirectAfterDelete(NovaRequest $request)
{
    return null;
}

分页

Nova 能够为你的资源列表显示分页链接。你可以根据应用程序的需求在三种不同的样式之间进行选择:“simple”、“load-more”和“links”

Simple Pagination

Load-more Pagination

Links Pagination

默认情况下,Nova 资源使用“simple”样式显示。但是,你可以通过更改应用程序的 config/nova.php 配置文件中的 pagination 配置选项的值,将其自定义为使用 load-morelinks 样式

php
'pagination' => 'links',

自定义分页

如果你想自定义每个资源的“每页”过滤器菜单中显示的可选择最大结果数,可以通过自定义资源的 perPageOptions 属性来实现

php
/**
 * The pagination per-page options configured for this resource.
 *
 * @return array
 */
public static $perPageOptions = [50, 100, 150];

或者,你可以在安装 Nova 时创建的应用程序的基本 Resource 类中覆盖 perPageOptions 方法

php
/**
 * The pagination per-page options configured for this resource.
 *
 * @return array
 */
public static function perPageOptions()
{
    return [50, 100, 150];
}

自定义 perPageOptions 和资源获取

在你的 Resource 中更改 perPageOptions 的值将导致 Nova 获取等于 perPageOptions 数组中第一个值的数量的资源。

使用 $perPageViaRelationship 属性,你还可以自定义当某个特定资源在另一个资源的详细信息视图中作为关系显示时显示的资源数

php
/**
 * The number of resources to show per page via relationships.
 *
 * @var int
 */
public static $perPageViaRelationship = 10;

CSV 导出

有时你可能需要将一组资源记录导出为 CSV 文件,以便你可以在电子表格应用程序中与数据交互或将数据导入另一个系统。值得庆幸的是,Nova 包含了导出资源数据的内置支持。

要开始,将 Laravel\Nova\Actions\ExportAsCsv 操作 添加到您的 Nova 资源中

php
use Laravel\Nova\Actions\ExportAsCsv;
use Laravel\Nova\Http\Requests\NovaRequest;

/**
 * Get the actions available for the resource.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function actions(NovaRequest $request)
{
    return [
        ExportAsCsv::make(),
    ];
}

如果您希望允许用户对下载的 CSV 文件命名,您可以在注册操作时调用 nameable 方法

php
return [
    ExportAsCsv::make()->nameable(),
];

如果您希望自定义和设置在生成的 CSV 中包含的字段的格式,您可以在注册操作时调用 withFormat 方法

php
return [
    ExportAsCsv::make()->withFormat(function ($model) {
        return [
            'ID' => $model->getKey(),
            'Name' => $model->name,
            'Email Address' => $model->email,
        ];
    }),
];

资源索引搜索去抖

您可能希望自定义单个资源的索引列表的搜索去抖时间。例如,执行以检索某些资源的查询可能比其他查询花费更长的时间。您可以通过设置资源类上的 debounce 属性来自定义单个资源的搜索去抖

php
/**
 * The debounce amount (in seconds) to use when searching this resource.
 *
 * @var float
 */
public static $debounce = 0.5; // 0.5 seconds

键盘快捷键

您可以在资源索引上按 C 键导航到“创建资源”页面。在资源详情页面上,E 键可用于导航到“更新资源”页面。