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

Laravel 10滚动分页分类场景返回错误数据及代码冗余问题

问题修复方案

问题根源

  1. 分类参数丢失:滚动加载的fetch请求未携带当前页面的type参数,且paginated方法默认使用new作为type值,导致分页请求无法识别分类。
  2. 代码冗余:index和paginated方法重复编写了大量查询构建逻辑,维护成本高。

修复步骤及代码修改

1. 提取公共查询构建方法

在PromptController中新增私有方法,统一处理查询逻辑,消除冗余:

private function buildPromptQuery(string $type, ?string $search)
{
    $query = Prompt::query();
    $date = Carbon::now()->subHours(96);

    switch ($type) {
        case 'hot':
            $query->where('created_at', '>=', $date)
                  ->orderBy(DB::raw('views'), 'desc');
            break;
        case 'top':
            $query->where('created_at', '>=', $date)
                  ->orderBy(DB::raw('views + upvotes'), 'desc');
            break;
        case 'new':
            $query->orderBy('created_at', 'desc');
            break;
        default:
            $query->whereJsonContains('categories', $type);
    }

    if (!empty(trim($search))) {
        $query->whereFullText('prompt', $search);
    }

    return $query->where('deleted', 0)
                 ->whereNotNull('prompt')
                 ->where('prompt', '!=', '');
}

2. 简化index方法

调用公共方法重构index,保留缓存逻辑:

public function index(Request $request, $type = 'new')
{
    $perPage = 60;
    $search = $request->get('search');
    $cacheKey = 'prompts-' . $type . '-' . ($search ?? '');
    
    $prompts = Cache::remember($cacheKey, 60, function () use ($search, $perPage, $type) {
        $query = $this->buildPromptQuery($type, $search);
        $this->logSQLQuery($type, $query, $search);
        return $query->paginate($perPage);
    });
    
    $randomImageUrl = $this->getRandomImage();
    return view('index', compact('prompts', 'randomImageUrl'));
}

3. 修复paginated方法

修改为从查询参数获取type,确保分页请求能接收分类信息:

public function paginated(Request $request)
{
    $perPage = 60;
    $search = $request->get('search');
    $type = $request->get('type', 'new');

    $query = $this->buildPromptQuery($type, $search);
    $prompts = $query->paginate($perPage);
    
    $prompts->appends(['search' => $search, 'type' => $type]);
    return view('partials.prompts', compact('prompts'));
}

4. 更新前端JS,传递分类参数

修改滚动加载逻辑,从当前URL提取type并携带到分页请求:

<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js"></script>

<script>
    const loadMorePlaceholder = document.querySelector('#load-more-placeholder');
    let currentPage = {{ $prompts->currentPage() }};
    let lastPage = {{ $prompts->lastPage() }};
    let isLoading = false;

    const searchForm = document.querySelector('.search-box');
    const searchButton = document.querySelector('#search-button');
    const loadingSpinner = document.querySelector('#loading-spinner');

    // 从URL路径提取当前分类type
    const pathParts = window.location.pathname.split('/').filter(part => part.trim() !== '');
    const currentType = pathParts.length > 0 ? pathParts[0] : 'new';

    searchForm.addEventListener('submit', () => {
        document.querySelector('#search-button-text').style.display = "none";
        document.querySelector('#loading-spinner').style.display = 'inline-block';
    });

    function loadMoreImages() {
        if (isLoading || currentPage >= lastPage) return;
        isLoading = true;
        currentPage++;

        const search = new URLSearchParams(window.location.search).get('search');
        const searchParam = search ? `&search=${encodeURIComponent(search)}` : '';
        const typeParam = currentType ? `&type=${encodeURIComponent(currentType)}` : '';

        fetch(`/prompts?page=${currentPage}${searchParam}${typeParam}`)
            .then(response => response.text())
            .then(html => {
                document.querySelector('#image-container').insertAdjacentHTML('beforeend', html);
                isLoading = false;
                document.querySelector('#loading-spinner').style.display = 'none';
                document.querySelector('#search-button-text').style.display = 'inline';
            });
    }

    function onScroll() {
        const rect = loadMorePlaceholder.getBoundingClientRect();
        if (rect.top <= window.innerHeight) {
            loadMoreImages();
        }
    }

    window.addEventListener('scroll', onScroll);
</script>

5. 路由保持原有配置

无需修改web.php路由,当前配置已满足需求:

// 分页请求路由
Route::get('/prompts', [PromptController::class, 'paginated']);
// 首页/分类路由
Route::get('/{type?}', [PromptController::class, 'index']);

内容的提问来源于stack exchange,提问作者Carol.Kar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:55:55