Laravel paginate 后遍历用 foreach 还是 transform?

有些教程是 foreach 有些是 transform ,那么到底应该用那个呢?

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 17

我一般都是把它转化为数组后再处理数据

1天前 评论
sunny123456 (楼主) 1天前
冯小胖同学 (作者) 1天前
sunny123456 (楼主) 1天前

其实有更优解针对API分页

app/Providers/AppServiceProvider.php 中:

<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        JsonResource::withoutWrapping();
        JsonResource::macro('paginationInformation', function (Request $request, array $paginated, array $default) {
            return ['meta' => Arr::only($paginated, [
                'current_page',
                'last_page',
                'per_page',
                'total',
            ])];
        });
    }
}

只要加这个就行,其他都不用变,也不需要创建 Collection 类,只要基础的 Resource 类就行

1天前 评论
sunny123456 (楼主) 1天前
唐章明

Laravel分页自带了

$models = YourModel::paginate(); // 对象

$models->items()  // 结果数组

// 遍历查询结果的每一项
$models->each(function($model){
    // 修改可以影响 $models 
    $model->status_label = $model->status===0 ? '启用' : '禁用' ;
})
1天前 评论
唐章明 (作者) 1天前
sunny123456 (楼主) 1天前

那我给个完整版的

app/Providers/AppServiceProvider.php:

<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        //
    }

    public function boot(): void
    {
        JsonResource::withoutWrapping();
        JsonResource::macro('paginationInformation', function (Request $request, array $paginated, array $default) {
            return ['meta' => Arr::only($paginated, [
                'current_page',
                'last_page',
                'per_page',
                'total',
            ])];
        });
    }
}

app/Http/Resources/Api/UserResource.php:

<?php

namespace App\Http\Resources\Api;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'avatar' => $this->avatar,
        ];
    }
}

app/Http/Controllers/Api/UsersController.php:

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\Api\UserResource;
use App\Models\User;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;

class UsersController extends Controller
{
    public function index(): AnonymousResourceCollection
    {
        return UserResource::collection(User::query()->latest()->paginate());
    }
}

routes/api.php:

<?php

use App\Http\Controllers\Api\UsersController;
use Illuminate\Support\Facades\Route;

Route::get('/users', [UsersController::class, 'index']);

访问接口 /api/users 返回的数据就是这样:

{
    "data": [
        {
            "id": 1,
            "name": "user",
            "avatar": ""
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 15,
        "total": 1
    }
}
1天前 评论
sunny123456 (楼主) 10小时前

如果是要对分页后的数据进行整理输出的话,可以使用through方法

return Product::paginate()->through(fn($p) => [
    'id' => $p->id,
    'name' => $p->name,
    'price' => Number::currency($p->price, 'CNY', 'zh')   
]);

这个返回的是一个AbstractPaginator对象,需要注意的是,这种方式不会走模型中定义的casts,当然你可以为casts数组中定义的字段定义对应的访问器,也可以用toArray方法来触发casts, 或者你也可以像下面这样处理,这种直接返回模型,同样会走casts相关的数据转换

return Product::paginate()->through(function($p) {
    $p->marked = true;
    unset($p->name);
    return $p;
});
22小时前 评论
nff93

你直接 foreach 就行,transform 是类似 array_map 的东西,用哪个取决于你的需求

18小时前 评论
sunny123456 (楼主) 10小时前

transform是集合的一个遍历方法,foreach是迭代语法结构, 这2个有什么关系呢?

分页数据处理,laravel不是有很多方法吗?你的目标是遍历处理数据,方法只是实现工具,因为每个业务数据处理是不同的,没必要过度封装,我个人一般都是ResourceCollection处理数据就行了,transform/map等等都可以,如果用JsonResource,每次遍历都会实例化一个JsonResource对象,如果不在乎实例开销,也可以只用JsonResource,我一般倾向于单独用ResourceCollection实现。

file file

9小时前 评论
sunny123456 (楼主) 4小时前

我是使用的foreach

8小时前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!