logo

定义透镜

虽然与过滤器类似,但 Nova 透镜允许您完全自定义底层资源 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
{
    /**
     * Get the query builder / paginator for the 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'));
    }

    /**
     * Get the columns that should be selected.
     *
     * @return array
     */
    protected static function columns()
    {
        return [
            'users.id',
            'users.name',
            DB::raw('sum(licenses.price) as revenue'),
        ];
    }

    /**
     * Get the fields available to the lens.
     *
     * @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);
            }),
        ];
    }

    /**
     * Get the cards available for the lens.
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function cards(NovaRequest $request)
    {
        return [];
    }

    /**
     * Get the filters available for the lens.
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return array
     */
    public function filters(NovaRequest $request)
    {
        return [];
    }

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

    /**
     * Get the URI key for the lens.
     *
     * @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
/**
 * Indicates whether the lens should automatically poll for new records.
 *
 * @var bool
 */
public static $polling = true;

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

php
/**
 * The interval (in seconds) at which Nova should poll for new lens.
 *
 * @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 镜头还包含一个 filters 方法。此方法允许您将任何现有的 过滤器 附加到镜头

php
use App\Nova\Filters\UserType;

/**
 * Get the filters available for the lens.
 *
 * @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;

/**
 * Get the actions available for the lens.
 *
 * @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;

/**
 * Get the cards available for the lens.
 *
 * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
 * @return array
 */
public function cards(NovaRequest $request)
{
    return [new NewUsers];
}