Replies: 2 comments
-
@Montaire please share an example of your controller or something where you use that method. And would be good to see what you expect and what you get. In general, the more context you can give the better |
Beta Was this translation helpful? Give feedback.
-
Here is how the new function works: namespace App\Support\ApiHelpers;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
class PaginatedResourceCollection extends AnonymousResourceCollection //I used here anonymous to get a generic helper but this is used mostly with ResourceCollection
{
public function paginationInformation($request, $paginated, $default){
return [
'total' => $paginated['total'],
];
}
} I can use this class from all my other collections, and my response would look like this for all my lists: {
"data": [
{
"title": "string"
}
],
"total": 0
} This is great because I store the scheme for all paginated list at a same place, which makes changing it later much easier. Here is my current workaround, and all the classes, but it would be much nicer to get the data from that function directly.Controller class HolidayController extends Controller
{
/**
* List
*/
public function index(Request $request)
{
//....
$query = Holiday::paginate($request->input('limit',10));
//...
return HolidayResource::paginableCollection($query);
}
} Resource class HolidayResource extends JsonResource
{
use HasPaginableCollection;
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'title' => $this->title,
];
}
} So I added this new function into the resource to have template parameter in the infering process. trait HasPaginableCollection {
/**
* Create a new paginable resource collection.
*
* @param mixed $resource
* @return PaginatedResourceCollection
*/
public static function paginableCollection($resource): PaginatedResourceCollection
{
return tap(new PaginatedResourceCollection($resource, static::class), function ($collection) {
if (property_exists(static::class, 'preserveKeys')) {
$collection->preserveKeys = (new static([]))->preserveKeys === true;
}
});
}
} And now comes the infering part as I could not get the second parameter in the class PaginableResourceCreationInfer implements ExpressionTypeInferExtension
{
public function getType(Expr $node, Scope $scope): ?Type
{
if ($node instanceof Node\Expr\StaticCall) {
if ($node->name->toString() === 'paginableCollection') {
return new Generic(
PaginatedResourceCollection::class . '-schema',
[
$this->setResourceType(new Generic($node->class->toString()), $scope, $node->args),
],
);
}
}
return null;
}
/**
* @param Node\Arg[] $args
*/
private function setResourceType(Generic $obj, Scope $scope, array $args)
{
$obj->templateTypes[0] = TypeHelper::getArgType($scope, $args, ['resource', 0]);
return $obj;
}
} And finally my custom PaginatorResource as you see I used again the class PaginatedResourceCollectionTypeToSchema extends TypeToSchemaExtension
{
public function shouldHandle(Type $type)
{
return $type instanceof Generic
&& $type->name === PaginatedResourceCollection::class . '-schema'
&& count($type->templateTypes) === 1
&& $type->templateTypes[0] instanceof ObjectType;
}
/**
* @param Generic $type
*/
public function toResponse(Type $type)
{
$collectingClassType = $type->templateTypes[0];
if (! $collectingClassType->isInstanceOf(JsonResource::class) && ! $collectingClassType->isInstanceOf(Model::class)) {
return null;
}
if (! ($collectingType = $this->openApiTransformer->transform($collectingClassType))) {
return null;
}
$type = new OpenApiObjectType;
$type->addProperty('data', (new ArrayType())->setItems($collectingType));
$type->addProperty('total', (new IntegerType)->setDescription('Total number of items being paginated.'));
return Response::make(200)
->description('Paginated set of `'.$this->components->uniqueSchemaName($collectingClassType->name).'`')
->setContent('application/json', Schema::fromType($type));
}
} Thank you for the awesome documentator, and you time, and please feel free to ask if its not clear! |
Beta Was this translation helpful? Give feedback.
-
In Laravel 10 we have a new function paginationInformation for defining meta data.
Can we have typing for pagination from that function?
I tried to make a plugin myself, but it seems the built in plugins are overtiring the user defined ones if they are extending the same class.
I it possible to run the user defined plugins after the built-in ones? It would be a desired behavior to be able to override the built in ones for me.
Beta Was this translation helpful? Give feedback.
All reactions