其实有更优解针对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
类就行
Laravel分页自带了
$models = YourModel::paginate(); // 对象
$models->items() // 结果数组
// 遍历查询结果的每一项
$models->each(function($model){
// 修改可以影响 $models
$model->status_label = $model->status===0 ? '启用' : '禁用' ;
})
那我给个完整版的
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
}
}
如果是要对分页后的数据进行整理输出的话,可以使用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;
});
transform是集合的一个遍历方法,foreach是迭代语法结构, 这2个有什么关系呢?
分页数据处理,laravel不是有很多方法吗?你的目标是遍历处理数据,方法只是实现工具,因为每个业务数据处理是不同的,没必要过度封装,我个人一般都是ResourceCollection处理数据就行了,transform/map等等都可以,如果用JsonResource,每次遍历都会实例化一个JsonResource对象,如果不在乎实例开销,也可以只用JsonResource,我一般倾向于单独用ResourceCollection实现。
推荐文章: