logo

定义镜头

Nova lenses 与过滤器类似,允许您完全自定义 Eloquent 的基础资源查询。例如,您可能希望按照终身总收入排序,列出应用程序的所有用户:

Lens

创建这样一个列表可能需要连接到其他表,并在查询中执行聚合函数。如果听起来很复杂,不用担心--镜头正是用来解决这种情况的。

概述

要创建镜头,可以使用 nova:lens Artisan 命令。默认情况下,Nova 会将新生成的镜头放在 app/Nova/Lenses 目录中:

bash
php artisan nova:lens MostValuableUsers

Nova 生成的每个镜头都包含多个方法。不过,我们目前关注的两个方法是 queryfields 方法。query 方法负责构建检索所需数据所需的 Eloquent 查询,而 fields 方法则返回查看镜头时应显示的字段数组。

要了解更多信息,让我们来看看显示用户及其终生收入的完整镜头定义。正如您在下面的示例中看到的,query 方法将利用 LensRequest 提供的 withFilterswithOrdering 方法,以指示 Nova 将任何选定的筛选器和排序约束也应用到查询中:

php
<?php

namespace App\Nova\Lenses;

use Illuminate\Support\Facades\DB;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Number;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\LensRequest;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Lenses\Lens;

class MostValuableUsers extends Lens
{
    /**
     * 获取镜头的查询生成器/分页器。
     *
     * @param  \Laravel\Nova\Http\Requests\LensRequest  $request
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return mixed
     */
    public static function query(LensRequest $request, $query)
    {
        return $request->withOrdering($request->withFilters(
            $query->select(self::columns())
                ->join('licenses', 'users.id', '=', 'licenses.user_id')
                ->groupBy('users.id', 'users.name')
                ->withCasts([
                    'revenue' => 'float',
                ])
        ), fn ($query) => $query->orderBy('revenue', 'desc'));
    }

    /**
     * 获取应选择的字段。
     *
     * @return array
     */
    protected static function columns()
    {
        return [
            'users.id',
            'users.name',
            DB::raw('sum(licenses.price) as revenue'),
        ];
    }

    /**
     * 获取镜头可用的字段。
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function fields(NovaRequest $request)
    {
        return [
            ID::make('ID', 'id'),
            Text::make('Name', 'name'),

            Number::make('Revenue', 'revenue', function ($value) {
                return '$'.number_format($value, 2);
            }),
        ];
    }

    /**
     * 获取可用于镜头的卡片。
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function cards(NovaRequest $request)
    {
        return [];
    }

    /**
     * 获取适用于镜头的过滤器。
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function filters(NovaRequest $request)
    {
        return [];
    }

    /**
     * 获取镜头的可用动作。
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function actions(NovaRequest $request)
    {
        return [];
    }

    /**
     * 获取镜头的 URI key。
     *
     * @return string
     */
    public function uriKey()
    {
        return 'most-profitable-users';
    }
}

如上例所示,query 方法可完全控制用于检索镜头数据的 Eloquent 查询。fields 方法可利用 Nova 的任何字段,以便适当显示查询检索到的数据。

列方法

在本例中,columns 方法是从 query 方法中提取出来的,以便于阅读。它不是 "必需 "的,也不是镜头的 "特征"。

镜头列选择

在编写镜头查询时,应尽量将资源的 ID 作为选定列。如果不包含 ID,Nova 将无法显示镜头的 「选择所有匹配」选项。此外,资源删除菜单也将不可用。

查询助手

withOrderingwithFilters 方法用于为镜头查询应用排序和过滤器,应始终在 query 方法中应用。这两种方法都接受 $query 作为第一个参数,而 withOrdering 方法则接受一个闭包作为第二个参数。传递给 withOrdering 方法的闭包应为查询应用默认排序,如果没有从 Nova 面板选择其他排序,则会应用默认排序:

php
return $request->withOrdering(
    $request->withFilters($query),
    fn ($query) => $query->latest()
);

镜头轮询

Nova 可以通过轮询以指定的时间间隔自动获取镜头的最新记录。要启用轮询,请覆盖镜头类的 polling 属性:

php
/**
 * 表示镜头是否应自动轮询新记录。
 *
 * @var bool
 */
public static $polling = true;

要自定义轮询间隔,你可以覆盖镜头类上的 pollingInterval 属性。pollingInterval 定义了 Nova 在获取新记录前应等待的秒数:

php
/**
 * Nova 轮询新镜头的时间间隔(秒)。
 *
 * @var int
 */
public static $pollingInterval = 5;

切换镜头轮询

默认情况下,当启用镜头轮询时,页面加载后无法禁用轮询。不过,你可以在镜头类中定义一个 showPollingToggle 属性为 true,指示 Nova 显示开始/停止轮询切换按钮:

php
/**
 * 表示是否在 Nova 内部显示轮询切换按钮
 *
 * @var bool
 */
public static $showPollingToggle = true;

镜头过滤器

每个 Nova 镜头还包含一个 filters 方法。该方法允许你将任何现有的 过滤器)附加到镜头上:

php
use App\Nova\Filters\UserType;

/**
 * 获取适用于镜头的过滤器。
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function filters(NovaRequest $request)
{
    return [new UserType];
}

镜头动作

每个 Nova 镜头还包含一个 actions 方法。该方法允许你将任何现有的 动作附加到镜头:

php
use App\Nova\Actions\Export;

/**
 * 获取镜头的可用动作。
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function actions(NovaRequest $request)
{
    return [new Export];
}

资源动作

默认情况下,镜头将继承其关联资源的操作。不过你可以覆盖镜头上的 actions 方法,以定义镜头可用的自定义动作集。

镜头指标

每个 Nova 镜头还包含一个 cards 方法。该方法允许你将任何现有的 指标 附加到镜头:

php
use App\Nova\Metrics\NewUsers;

/**
 * 获取可用于镜头的卡片。
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function cards(NovaRequest $request)
{
    return [new NewUsers];
}