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

FilamentPHP v3中Repeater内Select字段内存耗尽问题求优化方案

优化FilamentPHP v3中Repeater内Select字段内存耗尽问题

针对你遇到的2万条产品数据导致内存不足的问题,以下是具体优化方案:

1. 移除preload(),启用异步搜索

preload()会一次性把所有选项加载到内存,这是内存耗尽的核心原因。Filament的searchable()默认支持异步搜索,删掉preload()后,仅当用户输入搜索关键词时才会触发数据库查询,不会预加载全量数据。

2. 用searchUsing()实现精准异步搜索

自定义搜索逻辑,只返回匹配关键词的结果,同时限制返回条数,避免一次性加载过多数据:

Select::make('product_id')
    ->hidden(function () use ($productId) {
        return $productId !== null;
    })
    // 替换原options方法,改用searchUsing实现异步搜索
    ->searchUsing(function (Get $get, string $search) {
        $supplierId = $get('../../supplier_id');
        if (!$supplierId) {
            return ['Selecteer eerst een merk'];
        }

        return Product::select('id', DB::raw("CONCAT(item_code, ' - ', item_description) as concatenated_value"))
            ->where('supplier_id', $supplierId)
            ->where('available', true)
            // 模糊匹配搜索关键词,可根据实际字段调整
            ->where(function ($query) use ($search) {
                $query->where('item_code', 'like', "%{$search}%")
                      ->orWhere('item_description', 'like', "%{$search}%");
            })
            ->limit(50) // 限制返回最多50条结果
            ->pluck('concatenated_value', 'id')
            ->toArray();
    })
    ->label('Product')
    ->searchable()
    // 移除preload()
    ->disabled(fn(Get $get) => $get('../../sent'))
    ->columnSpan(2)
    ->required();

3. 数据库层面优化查询速度

给查询用到的字段添加索引,减少数据库查询时间和内存占用:

-- 给supplier_id、available添加复合索引
CREATE INDEX products_supplier_available ON products (supplier_id, available);

-- 给item_code和item_description添加全文索引(提升模糊搜索效率)
ALTER TABLE products ADD FULLTEXT INDEX idx_products_search (item_code, item_description);

如果使用全文索引,搜索逻辑可改为:

->whereRaw("MATCH(item_code, item_description) AGAINST(? IN BOOLEAN MODE)", [$search])

4. 缓存供应商对应的产品列表

如果同一供应商的产品不会频繁变动,用Laravel缓存缓存查询结果,避免重复查询数据库:

->searchUsing(function (Get $get, string $search) {
    $supplierId = $get('../../supplier_id');
    if (!$supplierId) {
        return ['Selecteer eerst een merk'];
    }

    // 缓存key,结合supplier_id和搜索关键词
    $cacheKey = "products_supplier_{$supplierId}_search_{$search}";
    
    return Cache::remember($cacheKey, now()->hour(), function () use ($supplierId, $search) {
        return Product::select('id', DB::raw("CONCAT(item_code, ' - ', item_description) as concatenated_value"))
            ->where('supplier_id', $supplierId)
            ->where('available', true)
            ->where(function ($query) use ($search) {
                $query->where('item_code', 'like', "%{$search}%")
                      ->orWhere('item_description', 'like', "%{$search}%");
            })
            ->limit(50)
            ->pluck('concatenated_value', 'id')
            ->toArray();
    });
})

5. 优化Repeater的加载逻辑

如果Repeater允许添加多个条目,每个条目都触发查询会成倍消耗内存。前面的异步搜索已经能大幅降低这个问题的影响,也可以额外判断:仅当当前条目未选定product_id时,才启用搜索功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:27:36