You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中如何用calebporzio/sushi插件从其他表动态填充数据?

问题原因与解决步骤

问题出在Sushi的默认机制:直接设置$rows属性属于静态预设数据,只会在模型首次加载时生效,不会动态更新。要实现运行时从数据库拉取最新数据,必须通过重写getRows()方法来动态生成数据集,同时结合Filament Tree的需求构建树结构。


1. 修正TaskTicketReport模型的Sushi配置

移除静态$rows属性,重写getRows()方法,让模型每次查询时都动态拉取Task、Tickets、Ticket_user的关联数据并构造成树节点格式:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Sushi\Sushi;
use App\Models\Task;
use App\Models\Ticket;

class TaskTicketReport extends Model
{
    use Sushi;

    // 关闭Sushi缓存,确保每次都拉取最新数据(按需开启)
    public $cache = false;

    /**
     * 动态生成树结构所需的数据集
     */
    public function getRows()
    {
        // 1. 拉取活跃任务作为树的根节点,关联工单数量和关联用户总数
        $taskNodes = Task::where('is_active', true)
            ->withCount([
                'tickets',
                'tickets as assigned_user_total' => function ($query) {
                    $query->select(\DB::raw('COUNT(DISTINCT ticket_user.user_id)'))
                        ->join('ticket_user', 'tickets.id', '=', 'ticket_user.ticket_id');
                }
            ])
            ->get()
            ->map(function ($task) {
                return [
                    'id' => 'task_' . $task->id, // 加前缀避免与工单ID冲突
                    'name' => $task->name,
                    'parent_id' => null, // 任务作为根节点
                    'ticket_count' => $task->tickets_count,
                    'user_count' => $task->assigned_user_total,
                    'node_type' => 'task', // 标记节点类型,方便Filament区分展示
                ];
            });

        // 2. 拉取关联工单作为任务节点的子节点,关联该工单的用户数
        $ticketNodes = Ticket::whereHas('task', fn($q) => $q->where('is_active', true))
            ->withCount('users')
            ->get()
            ->map(function ($ticket) {
                return [
                    'id' => 'ticket_' . $ticket->id,
                    'name' => $ticket->title,
                    'parent_id' => 'task_' . $ticket->task_id, // 关联到对应任务节点
                    'user_count' => $ticket->users_count,
                    'node_type' => 'ticket',
                ];
            });

        // 合并任务和工单节点,返回树结构数据集
        return $taskNodes->concat($ticketNodes)->toArray();
    }
}

2. 配置Filament Tree资源

确保Filament Tree资源正确绑定模型,并根据节点类型配置展示字段:

<?php

namespace App\Filament\Resources;

use App\Models\TaskTicketReport;
use Filament\Tables;
use SolutionForest\FilamentTree\Resources\Concern\HasTree;
use Filament\Resources\Resource;

class TaskTicketReportResource extends Resource
{
    use HasTree;

    protected static ?string $model = TaskTicketReport::class;
    protected static ?string $navigationIcon = 'heroicon-o-folder-tree';

    public static function treeSchema(): array
    {
        return [
            Tables\Columns\TextColumn::make('name')
                ->label('节点名称')
                ->sortable(),
            Tables\Columns\TextColumn::make('ticket_count')
                ->label('关联工单数')
                ->visible(fn($record) => $record['node_type'] === 'task'),
            Tables\Columns\TextColumn::make('user_count')
                ->label('关联用户数'),
        ];
    }

    // 按需补充表单、权限等其他配置
}

3. 验证与调试

  • 用Artisan Tinker验证模型数据是否正确:
php artisan tinker
>>> App\Models\TaskTicketReport::all();
  • 如果仍存在缓存问题,可手动清除Sushi缓存:
TaskTicketReport::flushCache();

内容的提问来源于stack exchange,提问作者Petro Gromovo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:24:52