Home > Net >  How to properly decode response paginated resource from an API in laravel 8?
How to properly decode response paginated resource from an API in laravel 8?

Time:12-22

I'm trying to develop a laravel application that must have an internal API to get always the data and the frontend controllers to consume this API to rendering views. This API will be consumed by mobile apps, so all requests will be handled by the API.

This is my API index action, which is working fine:

public function index(Request $request)
    {
        $filters = $request->all();

        $query = Place::query()->with('user');

        if(!isset($filters['filterType']) || !in_array(Str::lower($filters['filterType']), ['and', 'or']) ){
            $filters['filterType'] = 'or';
        }

        //apply filters
        foreach($filters as $filter => $value){
            if(Place::hasProperty($filter, app(Place::class)->getTable())){
                if($filters['filterType'] == 'and'){
                    $query->where($filter, $value); 
                }
                else{
                    $query->orWhere($filter, $value);                    
                }
            }
        }

        //sorting
        if(!isset($filters['sortOrder']) || !in_array($filters['sortOrder'], ['asc', 'desc'])){
            $sortOrder = 'desc';
        }
        else{
            $sortOrder = $filters['sortOrder'];
        }

        if(isset($filters['sortBy'])){
            $sortBy = $filters['sortBy'];
            foreach(explode(',', $sortBy) as $sortField){
                if(Place::hasProperty($sortField, app(Place::class)->getTable())){
                    $query->orderBy($sortField, $sortOrder);
                }
            }
        }
        
        //default pagination
        if(!isset($filters['maxResults'])){
            $filters['maxResults'] = 5;
        }
        if(!isset($filters['page'])){
            $filters['page'] = 1;
        }

        //apply pagination
        $results = $query->paginate($filters['maxResults'], ['*'], 'page', $filters['page']);
        $resultsCollectionResource = PlaceResource::collection($results);

        return $resultsCollectionResource;
    }

If I do this request by postman https://img.codepudding.com/202112/246c1b1a780547fdaa587942f6a2cdeb.png

Decoded object in frontend: https://img.codepudding.com/202112/fc7f06bec33a476c8a8cb79be7c00d53.png

What I'm doing wrong? Thanks you all.

EDIT

Based on @matiaslauriti response, I changed my API calling to guzzle:

public function index(Request $request)
    {
        //$places =  redirect()->route('api.places.index', ['request' => $request ])->content();

        $response = Http::get(env('API_URL').'/places');
        $places = $response->object();

        return view('places.index', ['places' => $places]);
    }

But I still having exactly the same problem. I tested other methods than $response->object(), like collection. But I never get an object that can use $places->links() method in the view.

CodePudding user response:

$places->links()

This function that you tend to call is a member of Laravel paginator class and $places should be instance of this class to support this function

if you want to continue with this implementation that you have, and support Laravel pagination features you should make an instance of Laravel lengthawarepaginator and manually create paginator instance.

According to its parameters this might looks something like this:

in your front controller add:

$paginatedPlaces = new LengthAwarePaginator($places->data, $places->meta->total, $places->meta->per_page)

then pass $paginatedPlaces to your view

the second option that i suggest is that instead of using ->links() function just simply print out the links property from the response.

  • Related