Recently submitted an idea to the Laravel framework - add detection of a custom paginated information method in PaginatedResourceResponse
so that it can be used Resource
When the class outputs information, it is very convenient to customize the paging information.
Why you need it
I basically develop APIs. In the early days, I always returned directly, but this method sometimes caused some problems and was inconvenient to maintain. In addition, it was often necessary to add custom fields and provide different data for different ends. I have been using it since thenResource
to define the returned data. [Recommended: laravel video tutorial]
Using Resource
is very convenient and can make the logic clear. But it has a disadvantage, that is, there is too much paginated information. For API projects, in most cases, many fields in the default output paging information are not needed, and because they are often connected to some old projects, the old data format needs to be used or made compatible. The fields of the paging information are quite different. , there is no way to directly use the paging information returned by default.
I don’t know how everyone handles paging information in similar situations, but before that, in order to achieve the goal, I usually have two methods, one is to customize Response
, The data information is redefined here, and the second is to customize all the related classes of Resource
.
I don’t know much about the bottom layer of Laravel, and I’m not good at abstract framework development, but after going through this, I found that things can become much simpler. As I explained in the PR, if you can When building pagination information in src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php
, you can use its component pagination information corresponding to the Resource
class, so you don’t need to do it every time Have you gone to a lot of trouble to customize many categories? So I submitted this idea to the Laravel framework. This commit was not accepted directly at first, but was merged after Taylor's adjustments and released in v8.73.2.
This is the first time I have contributed code to Laravel, and it is also the first time I have submitted a merge request to such a large code base. Although it has not been directly adopted, the results are exciting enough.
Usage Example
So, let me give a simple example of how to use it.
Default output
{ "data": [], "links": { "first": "http://cooman.cootab-v4.test/api/favicons?page=1", "last": "http://cooman.cootab-v4.test/api/favicons?page=1", "prev": null, "next": null }, "meta": { "current_page": 1, "from": 1, "last_page": 1, "links": [ { "url": null, "label": "« 上一页", "active": false }, { "url": "http://cooman.cootab-v4.test/api/favicons?page=1", "label": "1", "active": true }, { "url": null, "label": "下一页 »", "active": false } ], "path": "http://cooman.cootab-v4.test/api/favicons", "per_page": 15, "to": 5, "total": 5 }}
This is the paging information output by Laravel by default. There are many fields. Of course, this is enough to cope with many scenarios. But sometimes we get into trouble because of it. We need a little flexibility.
When using the ResourceCollection
class
Let’s take a look at the underlying logic first!
When a ResourceCollection
is returned from the controller, its toResponse
method will eventually be called to respond. Then you can directly find this method and take a look:
/** * Create an HTTP response that represents the object. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ public function toResponse($request) { if ($this->resource instanceof AbstractPaginator || $this->resource instanceof AbstractCursorPaginator) { return $this->preparePaginatedResponse($request); } return parent::toResponse($request); }
Do you see that if the current resource is a paging object, it will shift the task to processing the paging response. Next look:
/** * Create a paginate-aware HTTP response. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\JsonResponse */ protected function preparePaginatedResponse($request) { if ($this->preserveAllQueryParameters) { $this->resource->appends($request->query()); } elseif (! is_null($this->queryParameters)) { $this->resource->appends($this->queryParameters); } return (new PaginatedResourceResponse($this))->toResponse($request); }
Oh, it is transferred to PaginatedResourceResponse
again. This is the class we ultimately need to modify. Since the content of toResponse
is too long, it is not here. Posting, anyway, the response data is started here. Of course, the paging information is also processed here, but it has an independent method. This method is paginationInformation
, which is the logic before submitting the PR:
/** * Add the pagination information to the response. * * @param \Illuminate\Http\Request $request * @return array */ protected function paginationInformation($request) { $paginated = $this->resource->resource->toArray(); return [ 'links' => $this->paginationLinks($paginated), 'meta' => $this->meta($paginated), ]; }
If you are careful, you should be able to think of $this->resource
In fact, it is an instance of the ResourceCollection
above, then its resource
is our list data, which is the paging information instance. That being the case, why can't we process paging information in ResourceCollection
? Sure, but we needed to add something, and that's the idea I submitted.
After merging PR, its logic is as follows:
/** * Add the pagination information to the response. * * @param \Illuminate\Http\Request $request * @return array */ protected function paginationInformation($request) { $paginated = $this->resource->resource->toArray(); $default = [ 'links' => $this->paginationLinks($paginated), 'meta' => $this->meta($paginated), ]; if (method_exists($this->resource, 'paginationInformation')) { return $this->resource->paginationInformation($request, $paginated, $default); } return $default; }
Very simple processing method. If there is a custom paging information construction method in the corresponding resource class, then use its own , for now, this is indeed a good idea.
At this point, it should be clear how to customize the paging information. That is to add the paginationInformation
method to your corresponding ResourceCollection
class, for example:
public function paginationInformation($request, $paginated, $default): array { return [ 'page' => $paginated['current_page'], 'per_page' => $paginated['per_page'], 'total' => $paginated['total'], 'total_page' => $paginated['last_page'], ]; }
这是自定义后的数据输出情况:
{ "data": [], "page": 1, "per_page": 15, "total": 5, "total_page": 1}
结果如我所愿。
使用 Resource
类时
我通常只喜欢定义一个 Resource
类来应对单个对象和列表的情况,这里主要关注如何处理列表数据的分页自定义。
在控制器中,我一般都是这样使用:
public function Index(){ // .... return SomeResource::collection($paginatedData);}
再来看看 collection
方法里做了什么:
/** * Create a new anonymous resource collection. * * @param mixed $resource * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection */ public static function collection($resource) { return tap(new AnonymousResourceCollection($resource, static::class), function ($collection) { if (property_exists(static::class, 'preserveKeys')) { $collection->preserveKeys = (new static([]))->preserveKeys === true; } }); }
原来它把数据转给了 ResourceCollection
,那么只需要将这个 AnonymousResourceCollection
做个自定义不就可以了。
总结
这是一个很小优化,但是很有用。
在此之前,如果想要随着 Resource
返回自定义分页信息,会比较麻烦,需要自定义很多东西,这样的方式,对老用户而言小菜一碟,但是对新手就可能是件棘手的问题。那么自此之后,无论是老用户还是新手这件事将变得易如反掌。只需要在对应的 ResourceCollection
类中添加 paginationInformation
方法,类似下面这样:
public function paginationInformation($request, $paginated, $default): array { return [ 'page' => $paginated['current_page'], 'per_page' => $paginated['per_page'], 'total' => $paginated['total'], 'total_page' => $paginated['last_page'], ]; }
不过,如果你使用的是 Resource::collection($pageData)
方式,那么还需要额外自定义一个 ResourceCollection
类,并重写对应 Resource
类的 collection
方法。
我通常会定义一个对应的基类,然后其它的都继承它。也可以做个 trait
,然后共用。
最后
其实,这个想法我很早就想提交的,但是我一直比较犹豫,这到底是不是一个很大众的需求。不过我最后想明白了,这样做既然能为我节省大量重复且危险的工作,有那么多的开发者,总会有人需要的,所以我提交了,同时也是验证下我的想法到底是否可行,我的做法是否最优,结果当然是我学到了很多,比如写稍微复杂的测试用例。
另外,我想知道大家有没其它方法,或你们是怎么对待不同情况的分页信息的。
最后的最后,你如果也有好的想法,那么尽快提交吧!
The above is the detailed content of Laravel implements returning custom paging information with Resource!. For more information, please follow other related articles on the PHP Chinese website!

本篇文章给大家带来了关于laravel的相关知识,其中主要介绍了关于单点登录的相关问题,单点登录是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于laravel的相关知识,其中主要介绍了关于Laravel的生命周期相关问题,Laravel 的生命周期从public\index.php开始,从public\index.php结束,希望对大家有帮助。

在laravel中,guard是一个用于用户认证的插件;guard的作用就是处理认证判断每一个请求,从数据库中读取数据和用户输入的对比,调用是否登录过或者允许通过的,并且Guard能非常灵活的构建一套自己的认证体系。

laravel中asset()方法的用法:1、用于引入静态文件,语法为“src="{{asset(‘需要引入的文件路径’)}}"”;2、用于给当前请求的scheme前端资源生成一个url,语法为“$url = asset('前端资源')”。

本篇文章给大家带来了关于laravel的相关知识,其中主要介绍了关于使用中间件记录用户请求日志的相关问题,包括了创建中间件、注册中间件、记录用户访问等等内容,下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于laravel的相关知识,其中主要介绍了关于中间件的相关问题,包括了什么是中间件、自定义中间件等等,中间件为过滤进入应用的 HTTP 请求提供了一套便利的机制,下面一起来看一下,希望对大家有帮助。

在laravel中,fill方法是一个给Eloquent实例赋值属性的方法,该方法可以理解为用于过滤前端传输过来的与模型中对应的多余字段;当调用该方法时,会先去检测当前Model的状态,根据fillable数组的设置,Model会处于不同的状态。

laravel路由文件在“routes”目录里。Laravel中所有的路由文件定义在routes目录下,它里面的内容会自动被框架加载;该目录下默认有四个路由文件用于给不同的入口使用:web.php、api.php、console.php等。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),
