虽然与过滤器类似,但 Nova 透镜允许您完全自定义底层资源 Eloquent 查询。例如,您可能希望列出所有应用程序的用户,并按其总终身收入排序
创建这样的列表可能需要您加入其他表并在查询中执行聚合函数。如果听起来很复杂,别担心 - 这正是透镜旨在解决的类型。
要创建透镜,您可以使用 nova:lens
Artisan 命令。默认情况下,Nova 会将新生成的透镜放置在 app/Nova/Lenses
目录中
php artisan nova:lens MostValuableUsers
Nova 生成的每个透镜都包含几个方法。但是,我们目前关注的两个方法是 query
和 fields
方法。query
方法负责构建检索所需数据的 Eloquent 查询,而 fields
方法返回一个应该在查看透镜时显示的字段数组。
要了解更多信息,让我们看一下显示用户及其终身收入的完整透镜定义。正如您在下面的示例中看到的,query
方法将利用 LensRequest
提供的 withFilters
和 withOrdering
方法来指示 Nova 也将任何选定的过滤器和排序约束应用于查询
<?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 将无法为透镜显示“选择所有匹配项”选项。此外,资源删除菜单将不可用。
withOrdering
和 withFilters
方法用于将排序和过滤器应用于透镜查询,并且应始终在 query
方法中应用。这两个方法都接受 $query
作为第一个参数,withOrdering
方法接受闭包作为第二个参数。传递给 withOrdering
方法的闭包应将默认排序应用于查询,该排序将在从 Nova 仪表板中未选择其他排序的情况下应用
return $request->withOrdering(
$request->withFilters($query),
fn ($query) => $query->latest()
);
Nova 可以通过轮询以指定的时间间隔自动获取镜头的最新记录。要启用轮询,请覆盖镜头类的 polling
属性
/**
* Indicates whether the lens should automatically poll for new records.
*
* @var bool
*/
public static $polling = true;
要自定义轮询间隔,您可以在镜头类上覆盖 pollingInterval
属性。pollingInterval
定义 Nova 在获取新记录之前应等待的秒数
/**
* The interval (in seconds) at which Nova should poll for new lens.
*
* @var int
*/
public static $pollingInterval = 5;
默认情况下,启用镜头轮询后,页面加载后无法禁用轮询。但是,您可以通过在镜头类上定义 showPollingToggle
属性为 true
来指示 Nova 显示开始/停止轮询切换按钮
/**
* Indicates whether to show the polling toggle button inside Nova.
*
* @var bool
*/
public static $showPollingToggle = true;
每个 Nova 镜头还包含一个 filters
方法。此方法允许您将任何现有的 过滤器 附加到镜头
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
方法。此方法允许您将任何现有的 操作 附加到镜头
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
方法。此方法允许您将任何现有的 指标 附加到镜头
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];
}