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

Laravel 5.5 自定义分页:将横版图片视为2页处理

解决Laravel分页中横版图片按2页计算的问题

要实现横版图片等价于2页的分页逻辑,Laravel默认的paginate()方法没法直接满足——它是按记录数分页的。我们需要自定义分页逻辑,基于图片的横竖版计算"虚拟页数权重",再筛选出当前页应该展示的图片,最后手动构建分页器实例。

核心思路与实现步骤

  • 给每张图片分配权重:竖版(width ≤ height)权重1,横版(width > height)权重2
  • 基于总权重计算虚拟总页数,而非按图片数量计算
  • 匹配当前页对应的虚拟页数范围,筛选出该范围覆盖的图片
  • 用Laravel的LengthAwarePaginator构建自定义分页器,保持原有分页接口的兼容性

修改后的完整代码

/**
 * The attributes on which the comic list can be ordered
 * @var array
 */
public static $allowedSortingOptions = [
    'sort_order desc' => 'Sort Order (descending)',
    'random' => 'Random'
];

/**
 * Lists images for the front end
 *
 * @param $query
 * @param array $options Display options
 *
 * @return \Illuminate\Pagination\LengthAwarePaginator
 */
public function scopeListFrontEnd($query, $options) {
    /*
     * Default options
     */
    extract(array_merge([
        'page' => 1,
        'perPage' => 1,
        'sort' => 'sort_order',
        'chapter' => null,
        'language' => 'en'
    ], $options));

    if($chapter) {
        $query->where('attachment_id', $chapter);
    }

    $query->where('language', $language);

    /*
     * Sorting
     */
    if (!is_array($sort)) {
        $sort = [$sort];
    }

    foreach ($sort as $_sort) {
        if (in_array($_sort, array_keys(self::$allowedSortingOptions))) {
            $parts = explode(' ', $_sort);
            if (count($parts) < 2) {
                array_push($parts, 'desc');
            }
            list($sortField, $sortDirection) = $parts;
            if ($sortField == 'random') {
                $sortField = \DB::raw('RAND()');
            }
            $query->orderBy($sortField, $sortDirection);
        }
    }

    // 1. 获取排序后的所有符合条件的图片
    $allImages = $query->get();

    // 2. 为每张图片计算权重
    $weightedImages = $allImages->map(function($image) {
        $image->weight = $image->width > $image->height ? 2 : 1;
        return $image;
    });

    // 3. 计算总虚拟页数(总权重 / 每页虚拟页数,向上取整)
    $totalWeight = $weightedImages->sum('weight');
    $totalPages = (int)ceil($totalWeight / $perPage);

    // 4. 确定当前页对应的虚拟页数范围
    $currentPageStart = ($page - 1) * $perPage + 1;
    $currentPageEnd = $page * $perPage;

    // 5. 筛选当前页需要展示的图片
    $currentImages = collect();
    $accumulatedWeight = 0;

    foreach ($weightedImages as $image) {
        $prevWeight = $accumulatedWeight;
        $accumulatedWeight += $image->weight;

        // 计算当前图片覆盖的虚拟页数区间
        $imageStartPage = $prevWeight + 1;
        $imageEndPage = $accumulatedWeight;

        // 只要图片区间和当前页区间有交集,就加入当前页列表
        if ($imageStartPage <= $currentPageEnd && $imageEndPage >= $currentPageStart) {
            $currentImages->push($image);
        }

        // 已经超过当前页范围,提前终止循环提升效率
        if ($accumulatedWeight > $currentPageEnd) {
            break;
        }
    }

    // 6. 构建自定义分页器,保持原有分页功能的兼容性
    $paginator = new \Illuminate\Pagination\LengthAwarePaginator(
        $currentImages,
        $totalWeight,
        $perPage,
        $page,
        [
            'path' => \Request::url(),
            'query' => \Request::query(),
        ]
    );

    return $paginator;
}

效果验证

当perPage设为2时:

  • 竖版图片每张占1个虚拟页,所以每页会展示2张竖版图片
  • 横版图片每张占2个虚拟页,刚好填满一个分页,因此会单独占一页,不会和竖版图片混排

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:41:04