Search code examples
laravelapiresourceslaravel-resource

How to properly send a sorted model from my controller to the Laravel API Resource collection?


This is my controller:

    public function branchesNearby($lat, $lng)
{

    $branches = Branch::all();

    //Calculate distance between each branch and client
    //Radius of earth is 6371 KM so multiply the result with radius of earth 6371*pi/180
    foreach ($branches as $branch){
    $branch['distance'] = sqrt(pow(($branch->lat - $lat), 2) + pow(($branch->lng - $lng), 2)) * 108;
    }

    //Sort by nearest first
    $sortedBranches = $branches->sortBy('distance');

    return BranchResource::collection($sortedBranches);

}

You can see i created an extra attribute to calculate distance between user location and the branch location. Then, I sort the branch model by distance. However, The api response that i get is: API response

You can see it is an object. I don't need the keys "2", "0" and "1". I need to remove this extra wrapping and i need it to be an array of objects like this: Correct API but without sorting Surely, It is sorting which causes it to become an object? I tried many other ways, one of them being:

$sortedBranches = $collection->sortBy('distance');
$final = $sortedBranches->values()->toJson(); 

and sending this $final to the resource collection. That gives me the error: " call to a member function first() on string in file api resources". This must be something small but i really need help.

Updating: I did not post my Resource before, this is how it is:

    public function toArray($request)
    {

        return [
            'id' => $this->id,
            'shop' => $this->shop->name,
            'shop_image' => asset('api/images/' . $this->shop->image_file),
            'lat' => $this->lat,
            'lng' => $this->lng,
            'shop_logo' => asset('api/images/' . $this->shop->logo_file),
            'distance' => $this->distance . " KM"

        ];

The error that i get if i use:

$sortedBranches = $branches->sortBy('distance')->values()->all();
   return BranchResource::collection($sortedBranches);

is: The error

Update 3:

If i don't call the resource collection and simply output the $sortedBranches like this:

return response()->json($sortedBranches, 200);

Here, the format of the api response is correct but the data is not correct. This is how it looks: $sortedBranches

Is there a way i can manipulate $sortedBranches and show the output like with the BranchResource?


Solution

  • Based on our troubleshoot, the resulting solution should be:

    return BranchResource::collection($sortedBranches)->values()->all();
    

    When you pass a collection into the collect method of the BranchResource class, it re-creates the collection. Laravel sees you are returning an (collection)object directly from your controller, and intervenes by casting it to json( i believe this is default). If the resulting json is not converted the way you want, you need to modify this collection. Therfor we needed to modify the BranchResource::collection() collection, not the $sortedBranches collection.

    Edit:

    • Modified collect method into collection;