최근 Laravel 프레임워크에 아이디어를 제출했습니다. PaginatedResourceResponse
에 사용자 정의 페이지 매김 정보 메소드 감지를 추가하여 Resource
클래스를 사용하여 정보를 출력할 때, 페이징 정보를 사용자 정의하는 것이 매우 편리합니다. PaginatedResourceResponse
中添加一个自定义分页信息方法的检测,以便在使用 Resource
类输出信息时,能够非常方便地自定义分页信息。
为什么需要它
我基本上都是在开发 API。早期时候我都是直接返回,但是这种方式有时候会出现一些问题,也不方便维护,加上经常需要添加自定义字段和针对不同端给出不同数据的情况,我后来就一直在使用 Resource
来定义返回的数据。【推荐:laravel视频教程】
使用 Resource
很方便也能够让逻辑清晰。但它有个不好的地方,那就是分页信息太多了。针对 API 项目而言,大多数情况下,默认输出的分页信息里很多字段并不需要,并且由于经常对接的是一些老项目,需要沿用老的数据格式或者做兼容,分页信息的字段大不相同,没办法直接使用默认返回的分页信息。
我不知道大家是怎么处理类似情况时的分页信息的,但在此之前,为了能够达到目的,我通常有两种做法,一是自定义 Response
,在这里面把数据信息进行重新定义,二是将 Resource
相关的类全部自定义一遍。
我对 Laravel 底层并不是很了解,我也不擅长做抽象的框架开发,但是在经历这些之后,我发现事情能够变得简单很多,正如我在 PR 阐述的那样,如果可以在 src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php
中组建分页信息时,能够使用其对应 Resource
类的组件分页信息,那不就不需要每次大费周章的进行自定义很多类了吗。于是我就提交了这个想法给 Laravel 框架。这个提交在一开始并没有被直接接受,而是在经过 Taylor 调整后被合并,并发布在 v8.73.2。
这是我第一次向 Laravel 贡献代码,也是第一次向这么大的代码库提交合并请求,虽然没有被直接采用,但结果足以振奋人心。
使用示例
那么,我来简单的示例一下如何使用吧。
默认输出
{ "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 }}
这是 Laravel 默认输出的分页信息,是不是很多字段,当然这足够应对很多场景的使用。但有时候也会因此犯难。我们需要一点灵活。
使用 ResourceCollection
类时
我们先来看看底层逻辑吧!
当在控制器返回一个 ResourceCollection
时,最终会调用其 toResponse
方法以响应。那么可以直接找到该方法看看:
/** * 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); }
看到没,如果当前资源是个分页对象时,它就把任务转向处理分页响应了。接着看:
/** * 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); }
噢,它又转给了 PaginatedResourceResponse
,这是我们最终需要修改的类,由于 toResponse
的内容太长,就不在这里贴出,反正就是在这里开始组建响应的数据,分页信息当然也是在这里面做的处理,不过它有个独立的方法。该方法就是 paginationInformation
, 这是在提交 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), ]; }
如果你细心的话,你应该能够想到,这里的 $this->resource
其实就是上面的 ResourceCollection
的实例,那么它的 resource
就是我们的列表数据,也就是分页信息实例。既然如此,那我们为何不能在 ResourceCollection
中进行分页信息的处理呢?当然可以,但我们需要加点东西,这就是我提交的想法。
合并 PR 之后,它的逻辑是这样的:
/** * 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; }
很简单的处理方式,如果对应资源类中有自定义的分页信息组建方法,那就使用它自己的,目前而言,这确实是个好想法。
于此,如何自定义分页信息应该很清晰了。那就是在自己相应的 ResourceCollection
类中添加 paginationInformation
필요한 이유
저는 기본적으로 API를 개발합니다. 초기에는 항상 직접 리턴을 했었는데 이 방법은 가끔 문제가 발생하고 유지관리가 불편한 경우가 많았습니다. 또한, 사용자 정의 필드를 추가하고 엔드별로 다른 데이터를 제공해야 하는 경우가 많았습니다. 를 사용하여 반환된 데이터를 정의합니다. [권장: laravel 동영상 튜토리얼]🎜🎜리소스
사용 > 매우 편리하며 논리를 명확하게 만들 수 있습니다. 하지만 페이지에 매겨진 정보가 너무 많다는 단점이 있습니다. API 프로젝트의 경우 대부분의 경우 기본 출력 페이징 정보의 많은 필드가 필요하지 않으며 일부 이전 프로젝트와 연결되는 경우가 많기 때문에 이전 데이터 형식을 사용하거나 호환되도록 해야 합니다. 매우 다릅니다. 기본적으로 반환되는 페이징 정보를 직접 사용할 수 있는 방법은 없습니다. 🎜🎜비슷한 상황에서 다들 어떻게 페이징 정보를 처리하는지 모르겠지만, 그 전에 목표를 달성하기 위해 보통 두 가지 방법을 사용합니다. 하나는 Response
를 사용자 정의하는 것입니다. 데이터 정보, 둘째, 모든 리소스
관련 클래스를 사용자 정의합니다. 🎜🎜저는 Laravel의 하위 레이어에 대해 잘 모르고 추상 프레임워크 개발도 잘 못하는데, 이 과정을 겪어보니 PR에서 설명한 것처럼 하면 훨씬 더 간단해질 수 있다는 것을 알게 되었습니다. src/Illuminate/Http/Resources/Json/PaginatedResourceResponse.php에서 페이징 정보를 구성할 때 Resource
클래스의 해당 구성 요소 페이징 정보를 사용할 수 있습니다. 그래서 매번 많은 돈을 쓸 필요가 없습니다. Zhou Zhang이 많은 카테고리를 맞춤화했습니까? 그래서 저는 이 아이디어를 Laravel 프레임워크에 제출했습니다. 이 커밋은 처음에는 직접 승인되지 않았지만 Taylor의 조정 후에 병합되어 v8.73.2에 출시되었습니다. 🎜🎜Laravel에 코드를 기여한 것은 이번이 처음이고, 이렇게 큰 코드 베이스에 병합 요청을 제출한 것도 처음입니다. 비록 직접 채택되지는 않았지만 결과는 충분히 흥미롭습니다. 🎜사용예
🎜 그럼 간단한 사용예를 들어보겠습니다. 🎜기본 출력
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'], ]; }🎜Laravel에서 기본적으로 출력하는 페이징 정보입니다. 물론 필드가 많죠? , 이는 다양한 사용 시나리오를 처리하기에 충분합니다. 그러나 때때로 우리는 이것 때문에 어려움을 겪습니다. 약간의 유연성이 필요합니다. 🎜
ResourceCollection
클래스 사용 시
🎜먼저 기본 로직을 살펴보겠습니다! 🎜🎜 ResourceCollection
이 컨트롤러에서 반환되면 해당 toResponse
메서드가 결국 호출되어 응답하게 됩니다. 그런 다음 이 메서드를 직접 찾아서 살펴볼 수 있습니다. 🎜{ "data": [], "page": 1, "per_page": 15, "total": 5, "total_page": 1}🎜 현재 리소스가 페이징 개체인 경우 작업이 페이징 응답 처리로 전환된다는 것을 보셨나요? 다음 보기: 🎜
public function Index(){ // .... return SomeResource::collection($paginatedData);}🎜아, 다시
PaginatedResourceResponse
로 전송되었습니다. 이것은 우리가 마지막으로 수정해야 할 클래스입니다. toResponse
의 내용이 너무 길기 때문에. 여기에 게시하지 마십시오. 어쨌든 응답 데이터가 형성되기 시작하는 곳입니다. 물론 페이징 정보도 여기에서 처리되지만 독립적인 방법이 있습니다. 이 메소드는 PR을 제출하기 전 로직인 paginationInformation
입니다: 🎜/** * 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; } }); }🎜조심하시면
$this->resource
여기에 실제로 위의 ResourceCollection
인스턴스가 있고 해당 resource
는 페이징 정보 인스턴스인 목록 데이터입니다. 그렇다면 ResourceCollection
에서 페이징 정보를 처리할 수 없는 이유는 무엇입니까? 물론이죠. 하지만 뭔가 추가할 것이 필요했고, 그것이 제가 제출한 아이디어였습니다. 🎜🎜PR 병합 후 논리는 다음과 같습니다. 🎜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'], ]; }🎜 처리하는 매우 간단한 방법 해당 리소스 클래스에 사용자 정의 페이지 매김 정보 구성 방법이 있는 경우 지금은 자체적으로 사용합니다. 좋은 생각이에요. 🎜🎜이 시점에서는 페이징 정보를 사용자 정의하는 방법이 명확해졌습니다. 이는 다음과 같이 해당
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'], ]; }
这是自定义后的数据输出情况:
{ "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
,然后共用。
最后
其实,这个想法我很早就想提交的,但是我一直比较犹豫,这到底是不是一个很大众的需求。不过我最后想明白了,这样做既然能为我节省大量重复且危险的工作,有那么多的开发者,总会有人需要的,所以我提交了,同时也是验证下我的想法到底是否可行,我的做法是否最优,结果当然是我学到了很多,比如写稍微复杂的测试用例。
另外,我想知道大家有没其它方法,或你们是怎么对待不同情况的分页信息的。
最后的最后,你如果也有好的想法,那么尽快提交吧!
위 내용은 Laravel은 Resource를 사용하여 사용자 정의 페이징 정보 반환을 구현합니다!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

개발 환경과 생태계에서 Laravel과 Python의 비교는 다음과 같습니다. 1. Laravel의 개발 환경은 간단하며 PHP와 작곡가 만 필요합니다. Laravelforge와 같은 풍부한 확장 패키지를 제공하지만 확장 패키지 유지 보수는시기 적절하지 않을 수 있습니다. 2. 파이썬의 개발 환경도 간단하며 파이썬과 PIP 만 필요합니다. 생태계는 거대하고 여러 분야를 다루지 만 버전 및 종속성 관리는 복잡 할 수 있습니다.

Laravel은 백엔드 논리에서 어떻게 중요한 역할을합니까? 라우팅 시스템, eloquentorm, 인증 및 승인, 이벤트 및 청취자, 성능 최적화를 통해 백엔드 개발을 단순화하고 향상시킵니다. 1. 라우팅 시스템은 URL 구조의 정의 및 요청 처리 로직을 정의 할 수 있습니다. 2. eloquentorm은 데이터베이스 상호 작용을 단순화합니다. 3. 인증 및 인증 시스템은 사용자 관리에 편리합니다. 4. 이벤트와 리스너는 느슨하게 결합 된 코드 구조를 구현합니다. 5. 성능 최적화는 캐싱 및 대기열을 통한 응용 프로그램 효율성을 향상시킵니다.

Laravel의 인기에는 단순화 된 개발 프로세스, 쾌적한 개발 환경 및 풍부한 기능이 포함됩니다. 1) PHP의 유연성을 결합하여 Rubyonrails의 설계 철학을 흡수합니다. 2) 개발 효율성을 향상시키기 위해 Eloquentorm, Blade Template Engine 등과 같은 도구를 제공하십시오. 3) MVC 아키텍처 및 종속성 주입 메커니즘은 코드를보다 모듈화적이고 테스트 가능하게 만듭니다. 4) 캐싱 시스템 및 모범 사례와 같은 강력한 디버깅 도구 및 성능 최적화 방법을 제공합니다.

Django와 Laravel은 모두 풀 스택 프레임 워크입니다. Django는 Python 개발자 및 복잡한 비즈니스 논리에 적합한 반면 Laravel은 PHP 개발자 및 우아한 구문에 적합합니다. 1. Django는 파이썬을 기반으로하며 빠른 개발 및 높은 동시성에 적합한 "배터리 완성"철학을 따릅니다. 2. Laravel은 PHP를 기반으로하며 개발자 경험을 강조하며 중소형 프로젝트에 적합합니다.

Laravel은 PHP 기반 프레임 워크이기 때문에 PHP와 Laravel은 직접 비교할 수 없습니다. 1.PHP는 소규모 프로젝트 또는 빠른 프로토 타이핑에 적합하고 간단하고 직접적이기 때문에 적합합니다. 2. Laravel은 대규모 프로젝트 또는 효율적인 개발에 적합하지만 풍부한 기능과 도구를 제공하지만 가파른 학습 곡선을 가지고 있으며 순수한 PHP만큼 좋지 않을 수 있습니다.

laravelisabackendframeworkbuiltonphp, 디자인 된 forwebapplicationdevelopment.itfocusesonserver-sidelogic, databasemanagement, andapplicationtructure, and canbeintegratedwithfrontendechnologies likevue.jsorreactforfull-stackdevelopment.

이 기사는 Laravel에서 사용자 정의 블레이드 지시문을 만들고 사용하여 템플릿을 향상시키는 것에 대해 설명합니다. 지침 정의, 템플릿에서이를 사용하고 대규모 프로젝트에서 관리하고 개선 된 코드 재사용 성 및 R과 같은 이점을 강조합니다.

이 기사는 구성 요소를 사용하여 Laravel에서 재사용 가능한 UI 요소를 작성하고 사용자 정의하여 조직을위한 모범 사례를 제공하고 패키지 강화를 제안합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

Eclipse용 SAP NetWeaver 서버 어댑터
Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

Dreamweaver Mac版
시각적 웹 개발 도구

SublimeText3 Linux 새 버전
SublimeText3 Linux 최신 버전
