首页 > 解决方案 > Laravel 分页追加属性

问题描述

我正在从 php 重建我的搜索功能到 vue。

在 php 中,我曾经为我的模型类添加属性,例如 html 标签、缩略图等。我可以抓住它$model->HtmlThumb并加载属性。现在,由于我收到了 json 响应,因此标签不存在。我知道我可以简单地使用$appends模型类的属性。

问题是属性总是被附加,这是我绝对不想要的。

我知道我可以使用 hideAttributes 或类似的东西手动隐藏这些属性,但在现有应用程序中这样做并不方便。

这样它应该可以工作,但现在它返回一个项目数组而不是分页器集合。

$results = $db_query->paginate($num_of_results)->appends($result)->each(function($project){
    $result->setAppends([
        'ProjectDescription',
        'FileCountLabel',
    ]);
});

我正在寻找一种方法来正确地做到这一点。

标签: laraveleloquentpagination

解决方案


OP 接受的答案是正确且有效的,但我想提出一个具有两个优点的替代答案:

  1. 它不必为每种模型类型和附加属性的每种组合创建一个新的 ResourceCollection。

  2. 来自分页器的响应的格式将与来自响应的格式相同$db_query->paginate($num_of_results)(默认情况下,ResourceCollection 将分页元数据移动到响应中的两个子对象中,links并且meta,这意味着需要重构使用 API 的代码)。

我们的想法是创建一个通用的 ResourceCollection,它允许我们动态控制附加的属性:

app/Resources/AppendablePaginator.php

<?php

namespace App\Http\Resources;

use Illuminate\Support\Arr;
use Illuminate\Http\Resources\Json\PaginatedResourceResponse;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Pagination\AbstractPaginator;

class AppendablePaginator extends ResourceCollection
{
    private $appends = [];

    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'data' => $this->collection->each->append($this->appends)
        ];
    }

    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function toResponse($request)
    {
        return $this->resource instanceof AbstractPaginator
                    ? (new FlattenedPaginatedResourceResponse($this))->toResponse($request)
                    : parent::toResponse($request);
    }

    /**
     * Append to the underlying models
     * @param  array|string|null  $key
     */
    public function modelAppend($key) {
        if (is_null($key)) {
            return $this;
        }

        if (is_array($key)) {
            $this->appends = array_merge($this->appends, $key);
        } else {
            $this->appends[] = $key;
        }
        
        return $this;
    }
}

class FlattenedPaginatedResourceResponse extends PaginatedResourceResponse {
    /**
     * Add the pagination information to the response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function paginationInformation($request)
    {
        $paginated = $this->resource->resource->toArray();
        return Arr::except($paginated, ['data']);
    }
}

现在我们可以动态追加:

$results = (new AppendablePaginator($db_query->paginate($num_of_results))->modelAppend([
    'ProjectDescription',
    'FileCountLabel'
]);

这意味着我们可以轻松地更改附加属性,并且由于此代码适用于任何模型类型,我们不必担心生成新集合。


推荐阅读