3

Supposed I have an API response of a Product

{
    data: [
    {
        id: 3,
        name: "Test Product",
        price: "158.21",
        quantity: 4,
        income: 569.56
    },
    {
        id: 4,
        name: "Test Product",
        price: "58.21",
        quantity: 3,
        income: 157.17
    },
    ]
}

is there a way where i can add a total of all the income of a product just like this?

{
 data: [
    {
        id: 3,
        name: "Test Product",
        price: "158.21",
        quantity: 4,
        income: 569.56
    },
    {
        id: 4,
        name: "Test Product",
        price: "58.21",
        quantity: 3,
        income: 157.17
    },
    ],
    total: 726.73
}

this is my class OrderProductResource that extends JsonResource

public function toArray($request)
    {
        $quantity = 0;
        $overAllTotal = 0;
        foreach($this->orders as $order){
            $quantity += $order->pivot->quantity; 
        }
        $sub_total = round($this->price * $quantity,2);
        $discount = round((10 / 100) * $sub_total, 2);
        $totalIncome = round(($sub_total - $discount), 2);
        return [
            'id' => $this->id,
            'name' => $this->name,
            'price' => $this->price,
            'quantity' => $quantity,
            'income' => $totalIncome,
        ];
    }

i tried to use the with method in laravel but the API response is still the same.

this is my controller

public function index(){
        $errorFound = false;
        $error = ['error' => 'No Results Found'];
        $products = Product::with('orders');
        if (request()->has('q')) {
            $keyword = '%'.request()->get('q').'%';
            $builder = $products->where('name', 'like', $keyword);
            $builder->count() ? $products = $builder : $errorFound = true;
        }
        return $errorFound === false ? OrderProductResourceCollection::collection($products->latest()->paginate()) : $error;
    }
Beginner
  • 1,700
  • 4
  • 22
  • 42

2 Answers2

7

You need to define 2 Accessor for total quantity and income in Product Model

public function getQuantityAttribute() 
{ 
    $quantity = 0; 

    foreach($this->orders as $order){ 
       $quantity += $order->pivot->quantity; 
    } 

    return $quantity;
}

public function getIncomeAttribute()
{
    $sub_total = $this->price * $this->quantity;

    $discount = round((10 / 100) * $sub_total, 2); 

    return round(($sub_total - $discount), 2); 
}

Change OrderProductResource class like this

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'price' => $this->price,
        'quantity' => $this->quantity,
        'income' => $this->income,
    ];
}

Create a Resource collection class OrderProductResourceCollection for OrderProductResource like this

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class OrderProductResourceCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'total' => $this->collection->sum('income')
        ];
    }
}

Now in controller use it like this

$products = Product::with('orders')->get();
return response()->json(new OrderProductResourceCollection($products));

You can check the documents for resource collection here https://laravel.com/docs/5.6/eloquent-resources#concept-overview

rkj
  • 8,067
  • 2
  • 27
  • 33
  • Method Illuminate\Database\Query\Builder::mapInto does not exist. – Beginner Aug 08 '18 at 09:38
  • return $errorFound === false ? response()->json(OrderProductResourceCollection::collection($products->latest()->paginate())) : $error; – Beginner Aug 08 '18 at 09:42
  • but when i tried it on a typical resource class that extends JsonResource it just work fine – Beginner Aug 08 '18 at 09:46
  • still the same sir – Beginner Aug 08 '18 at 09:46
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177624/discussion-between-rkj-and-beginner). – rkj Aug 08 '18 at 09:46
  • sir https://stackoverflow.com/questions/51758398/laravel-image-validation-image-intervention – Beginner Aug 09 '18 at 03:30
  • check this link sir disregard the other one https://stackoverflow.com/questions/51759114/accessing-the-accessor-from-different-model-with-many-to-many-relationship-larav – Beginner Aug 09 '18 at 05:04
  • https://stackoverflow.com/questions/56164895/appending-current-url-with-the-new-one sir – Beginner May 16 '19 at 09:12
0

Try this:

public function toArray($request)
{
    $quantity = 0;
    $overAllTotal = 0;
    foreach($this->orders as $order){
        $quantity += $order->pivot->quantity; 
    }
    $sub_total = round($this->price * $quantity,2);
    $discount = round((10 / 100) * $sub_total, 2);
    $totalIncome = round(($sub_total - $discount), 2);
    return [
        'id' => $this->id,
        'name' => $this->name,
        'price' => $this->price,
        'quantity' => $quantity,
        'income' => $totalIncome,

        //your relation
        'realtion_name' => $this->relation_name
    ];
}
J. Doe
  • 1,682
  • 11
  • 22