Laravel Nova 指标(Metrics)与过滤器(Filters)
指标(Metrics)
指标用于展示数据统计信息,有三种类型:数值指标、趋势指标和分区指标。

创建指标
php artisan nova:metric TotalUsers php artisan nova:metric UsersPerDay php artisan nova:metric UserBreakdown
数值指标(Value Metrics)
// app/Nova/Metrics/TotalUsers.php
<?php
namespace App\Nova\Metrics;
use App\Models\User;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Metrics\Value;
class TotalUsers extends Value
{
public $name = '用户总数';
public function calculate(NovaRequest $request)
{
return $this->count($request, User::class);
}
public function ranges()
{
return [
30 => '30天',
60 => '60天',
365 => '365天',
'TODAY' => '#39;,
'MTD' => '本月至今',
'QTD' => '本季度至今',
'YTD' => '今年至今',
];
}
public function cacheFor()
{
return now()->addMinutes(5);
}
}
自定义查询指标
public function calculate(NovaRequest $request)
{
return $this->count($request, User::class, function ($query) {
return $query->where('status', 'active');
});
}
// 或者使用 aggregate
return $this->average($request, Order::class, 'total_amount');
return $this->sum($request, Order::class, 'total_amount');
return $this->max($request, Order::class, 'total_amount');
return $this->min($request, Order::class, 'total_amount');
趋势指标(Trend Metrics)
// app/Nova/Metrics/UsersPerDay.php
<?php
namespace App\Nova\Metrics;
use App\Models\User;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Metrics\Trend;
class UsersPerDay extends Trend
{
public $name = '每日用户注册';
public function calculate(NovaRequest $request)
{
return $this->countByDays($request, User::class)->showLatestValue();
}
public function ranges()
{
return [
30 => '30天',
60 => '60天',
90 => '90天',
];
}
}
其他趋势方法
// 按小时统计
return $this->countByHours($request, User::class);
// 按周统计
return $this->countByWeeks($request, User::class);
// 按月统计
return $this->countByMonths($request, User::class);
// 自定义日期字段
return $this->countByDays($request, User::class, 'created_at');
// 带条件的趋势查询
return $this->countByDays($request, User::class)
->where('role_id', 1);
// 叠加多条线
return $this->countByDays($request, User::class)
->showLatestValue()
->sum([
'active' => User::where('status', 'active'),
'inactive' => User::where('status', 'inactive'),
]);
分区指标(Partition Metrics)
// app/Nova/Metrics/UserBreakdown.php
<?php
namespace App\Nova\Metrics;
use App\Models\User;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Metrics\Partition;
class UserBreakdown extends Partition
{
public $name = '用户角色分布';
public function calculate(NovaRequest $request)
{
return $this->count($request, User::class, 'role_id')
->label(function ($value) {
return \App\Models\Role::find($value)?->name ?? '未知';
})
->colors([
'admin' => '#f5365c',
'user' => '#11cdef',
'guest' => '#5e72e4',
]);
}
}
注册指标
// app/Nova/User.php
public function cards(NovaRequest $request)
{
return [
new \App\Nova\Metrics\TotalUsers,
new \App\Nova\Metrics\UsersPerDay,
(new \App\Nova\Metrics\UserBreakdown)->onlyOnDetail(), // 仅显示在详情页
];
}
过滤器(Filters)
过滤器允许用户按特定条件筛选资源列表。
创建过滤器
php artisan nova:filter UserActiveFilter php artisan nova:filter DateRangeFilter
基础过滤器
// app/Nova/Filters/UserRoleFilter.php
<?php
namespace App\Nova\Filters;
use Illuminate\Http\Request;
use Laravel\Nova\Filters\Filter;
class UserRoleFilter extends Filter
{
public $name = '用户角色';
public function apply(Request $request, $query, $value)
{
return $query->where('role_id', $value);
}
public function options(Request $request)
{
return [
'管理员' => 'admin',
'用户' => 'user',
'访客' => 'guest',
];
}
}
布尔过滤器
// app/Nova/Filters/UserActiveFilter.php
<?php
namespace App\Nova\Filters;
use Illuminate\Http\Request;
use Laravel\Nova\Filters\BooleanFilter;
class UserActiveFilter extends BooleanFilter
{
public $name = '用户状态';
public function apply(Request $request, $query, $value)
{
return $query->where('active', $value['active'] ?? true);
}
public function options(Request $request)
{
return [
'active' => '活跃用户',
];
}
}
日期范围过滤器
// app/Nova/Filters/DateRangeFilter.php
<?php
namespace App\Nova\Filters;
use Illuminate\Http\Request;
use Laravel\Nova\Filters\DateFilter;
use Carbon\Carbon;
class DateRangeFilter extends DateFilter
{
public $name = '注册日期';
public function apply(Request $request, $query, $value)
{
return $query->whereDate('created_at', '=', $value);
}
}
选择字段过滤器
// app/Nova/Filters/StatusFilter.php
<?php
namespace App\Nova\Filters;
use Illuminate\Http\Request;
use Laravel\Nova\Filters\SelectFilter;
class StatusFilter extends SelectFilter
{
public $name = '状态';
public function apply(Request $request, $query, $value)
{
return $query->where('status', $value);
}
public function options(Request $request)
{
return [
'active' => '活跃',
'inactive' => '非活跃',
'pending' => '待处理',
];
}
}
自定义过滤器组件
// 使用可输入的选择器
use Laravel\Nova\Filters\SelectFilter;
use Illuminate\Support\Facades\Log;
class CustomStatusFilter extends SelectFilter
{
public $name = '自定义状态';
public function apply(Request $request, $query, $value)
{
Log::info('Filter applied', ['value' => $value]);
return $query->where('status', $value);
}
public function options(Request $request)
{
return [
'active' => '活跃',
'inactive' => '非活跃',
];
}
public function default()
{
return 'active';
}
}
注册过滤器
// app/Nova/User.php
public function filters(NovaRequest $request)
{
return [
new \App\Nova\Filters\UserRoleFilter,
(new \App\Nova\Filters\UserActiveFilter)->canSee(function ($request) {
return $request->user()->can('view_users');
}),
new \App\Nova\Filters\DateRangeFilter,
];
}
高级用法
动态选项过滤器
class UserDepartmentFilter extends SelectFilter
{
public function apply(Request $request, $query, $value)
{
return $query->whereHas('department', function ($q) use ($value) {
$q->where('id', $value);
});
}
public function options(Request $request)
{
return \App\Models\Department::all()
->pluck('name', 'id')
->toArray();
}
}
多项选择过滤器
use Laravel\Nova\Filters\MultiSelectFilter;
class MultipleRolesFilter extends MultiSelectFilter
{
public function apply(Request $request, $query, $value)
{
return $query->whereIn('role_id', $value);
}
public function options(Request $request)
{
return [
'admin' => '管理员',
'user' => '用户',
'mod' => '版主',
];
}
}
使用自定义查询
class PriceRangeFilter extends Filter
{
public function apply(Request $request, $query, $value)
{
return $query->whereBetween('price', [$value['min'], $value['max']]);
}
public function options(Request $request)
{
return [
'min' => '最低价格',
'max' => '最高价格',
];
}
}
完整示例
// app/Nova/Metrics/RevenueBreakdown.php
<?php
namespace App\Nova\Metrics;
use App\Models\Order;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Metrics\Partition;
class RevenueBreakdown extends Partition
{
public $name = '收入分布';
public function calculate(NovaRequest $request)
{
return $this->sum($request, Order::class, 'total', 'status')
->label(function ($value) {
return ucfirst($value);
})
->colors([
'paid' => '#2dce89',
'pending' => '#f5365c',
'refunded' => '#5e72e4',
]);
}
}
// app/Nova/Order.php
public function cards(NovaRequest $request)
{
return [
new \App\Nova\Metrics\TotalRevenue,
new \App\Nova\Metrics\RevenueBreakdown,
(new \App\Nova\Metrics\OrdersPerDay)->onlyOnDetail(),
];
}
public function filters(NovaRequest $request)
{
return [
new \App\Nova\Filters\OrderStatusFilter,
(new \App\Nova\Filters\DateRangeFilter)->canSee(function ($request) {
return $request->user()->isAdmin();
}),
];
}
注意事项
- 性能优化:对复杂查询使用
cacheFor()方法缓存结果 - 权限控制:使用
canSee()方法控制指标和过滤器的显示 - 自定义字段:可以添加
$name属性自定义显示名称 - 默认值:使用
default()方法设置过滤器默认值 - 响应式设计:指标和过滤器在移动端也会自动适配