Baru-baru ini menyerahkan idea kepada rangka kerja Laravel - tambah pengesanan kaedah maklumat penomboran tersuai dalam PaginatedResourceResponse
supaya ia boleh dikeluarkan apabila menggunakan Resource
kelas Apabila melihat maklumat, adalah sangat mudah untuk menyesuaikan maklumat paging.
Pada dasarnya saya membangunkan API. Pada hari-hari awal, saya selalu kembali secara langsung, tetapi kaedah ini kadangkala menyebabkan beberapa masalah dan menyusahkan untuk diselenggara Selain itu, selalunya perlu untuk menambah medan tersuai dan menyediakan data yang berbeza untuk tujuan yang berbeza yang saya gunakan Resource
tentukan data yang dikembalikan. [Disyorkan: tutorial video laravel]
Menggunakan Resource
sangat mudah dan boleh menjelaskan logiknya. Tetapi ia mempunyai kelemahan, iaitu, terdapat terlalu banyak maklumat penomboran. Untuk projek API, dalam kebanyakan kes, banyak medan dalam maklumat paging output lalai tidak diperlukan, dan kerana ia sering disambungkan kepada beberapa projek lama, format data lama perlu digunakan atau dibuat serasi Medan maklumat paging adalah agak berbeza, tidak ada cara untuk menggunakan maklumat paging yang dikembalikan secara lalai.
Saya tidak tahu bagaimana semua orang mengendalikan maklumat paging dalam situasi yang sama, tetapi sebelum itu, untuk mencapai matlamat, saya biasanya mempunyai dua kaedah Satu ialah menyesuaikan Response
, di mana Maklumat data adalah ditakrifkan semula, dan yang kedua adalah untuk menyesuaikan semua Resource
kelas yang berkaitan.
Saya tidak tahu banyak tentang lapisan bawah Laravel, dan saya tidak mahir dalam pembangunan rangka kerja abstrak, tetapi selepas melalui ini, saya mendapati bahawa perkara boleh menjadi lebih mudah Seperti yang saya jelaskan dalam PR, jika anda boleh Apabila membina maklumat paging dalam src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php
, anda boleh menggunakan maklumat paging komponen yang sepadan dengan kelas Resource
Kemudian anda tidak perlu menghabiskan banyak masa untuk menyesuaikan banyak kelas. Jadi saya menyerahkan idea ini kepada rangka kerja Laravel. Komit ini tidak diterima secara langsung pada mulanya, tetapi telah digabungkan selepas pelarasan Taylor dan dikeluarkan dalam v8.73.2.
Ini adalah kali pertama saya menyumbang kod kepada Laravel, dan ini juga kali pertama saya menyerahkan permintaan gabungan kepada pangkalan kod yang begitu besar Walaupun ia tidak diterima pakai secara langsung, hasilnya menarik cukuplah.
Nah, izinkan saya memberikan contoh mudah tentang cara menggunakannya.
{ "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 }}
Ini ialah output maklumat paging oleh Laravel secara lalai. Sudah tentu, ini sudah cukup untuk menghadapi banyak senario . Tetapi kadang-kadang kita mendapat masalah kerananya. Kami memerlukan sedikit fleksibiliti.
ResourceCollection
Mari kita lihat logik asas dahulu!
Apabila ResourceCollection
dikembalikan daripada pengawal, kaedah toResponse
nya akhirnya akan dipanggil sebagai tindak balas. Kemudian anda boleh terus mencari kaedah ini dan lihat:
/** * 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); }
Lihat, jika sumber semasa ialah objek paging, ia akan mengalihkan tugas untuk memproses respons paging. Pandangan seterusnya:
/** * 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, ia telah dipindahkan ke PaginatedResourceResponse
sekali lagi. Ini adalah kelas yang akhirnya perlu kami ubah suai Memandangkan kandungan toResponse
terlalu panjang, saya tidak akan menyiarkannya Di sini, ia adalah Di sini kita mula membina data respons Sudah tentu, maklumat paging juga diproses di sini, tetapi ia mempunyai kaedah bebas. Kaedahnya ialah paginationInformation
, iaitu logik sebelum menyerahkan 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), ]; }
Jika anda berhati-hati, anda sepatutnya dapat berfikir bahawa $this->resource
di sini sebenarnya adalah contoh di atas ResourceCollection
. Maka resource
ialah data senarai kami, yang merupakan contoh maklumat halaman. Oleh itu, mengapa kami tidak boleh memproses maklumat halaman dalam ResourceCollection
? Sudah tentu, tetapi kami perlu menambah sesuatu, dan itulah idea yang saya serahkan.
Selepas menggabungkan PR, logiknya adalah seperti berikut:
/** * 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; }
Kaedah pemprosesan yang sangat mudah Jika terdapat kaedah pembinaan maklumat paging tersuai dalam kelas sumber yang sepadan, gunakannya Saya sendiri, buat masa ini, ini sememangnya idea yang baik.
Pada ketika ini, cara untuk menyesuaikan maklumat halaman harus jelas. Iaitu untuk menambah kaedah ResourceCollection
pada kelas paginationInformation
anda yang sepadan, contohnya:
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
,然后共用。
其实,这个想法我很早就想提交的,但是我一直比较犹豫,这到底是不是一个很大众的需求。不过我最后想明白了,这样做既然能为我节省大量重复且危险的工作,有那么多的开发者,总会有人需要的,所以我提交了,同时也是验证下我的想法到底是否可行,我的做法是否最优,结果当然是我学到了很多,比如写稍微复杂的测试用例。
另外,我想知道大家有没其它方法,或你们是怎么对待不同情况的分页信息的。
最后的最后,你如果也有好的想法,那么尽快提交吧!
Atas ialah kandungan terperinci Laravel melaksanakan pengembalian maklumat halaman tersuai dengan Sumber!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!