PHP项目Laravel Nova指标与过滤器

wen PHP项目 3

Laravel Nova 指标(Metrics)与过滤器(Filters)

指标(Metrics)

指标用于展示数据统计信息,有三种类型:数值指标趋势指标分区指标

PHP项目Laravel Nova指标与过滤器

创建指标

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() 方法设置过滤器默认值
  • 响应式设计:指标和过滤器在移动端也会自动适配

抱歉,评论功能暂时关闭!