user12263949
user12263949

Reputation:

How to display a parameter from two related Eloquent models?

I have two related Eloquent table models:

# app/Order.php

protected $fillable = [
  'id',  'status', 'client_email', 'partner_id',
];

public function partner()
{
    return $this->belongsTo('App\Partner');
}
# app/Partner.php

protected $fillable = ['id', 'email', 'name'];

public function order()
{
    return $this->hasOne('App\Order');
}

Then if I try add $partner to the array in my Order resource , I get a server error:

# app/Http/Resources/Order.php

public function toArray($request)
{
   // $partner = Order::find(1)->partner;

    return parent::toArray($request);

    return [
      'id' => $this->id,
      'status' => $this->status,
      'client_email' => $this->client_email,
      'partner_id' => $this->partner->id,
      'partner_name' => $this->partner->name,
     ];
}

created additional, but I don't know if I need it or not app/Http/Resources/Partner.php

<?php

namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;

class Partner extends JsonResource
{
    public function toArray($request)
    {
        return parent::toArray($request);

        return [
          'id' => $this->id,
          'name' => $this->name,
       ];
    }
}

How do I return 'partner_name' to OrderController for later use in Vue?

# OrderController.php

use App\Http\Resources\Order as OrderResource;

class OrderController extends Controller
{

    public function index()
    {
        $orders = Order::with('partner')->get();

        return OrderResource::collection($orders);
    }
}

Table partners columns:

id, email, name

Table orders columns:

id, status, client_email, partner_id

Is it correct to pass 'partner_name' to the Resources/Order array.php or does it need to be done in the controller?

Please show me how to do this correctly

Upvotes: 0

Views: 66

Answers (2)

Kenny Horna
Kenny Horna

Reputation: 14251

It seems that your relationships are a little bit off.

From your $fillable values in the Order model, I can see the partner_id, so -correct me if I'm wrong but- that is the foreign key.. making this model the child one.

Try updating your relations like so:

# Order.php

public function partner()
{
    return $this->belongsTo('App\Partner');
}   //            ^^^^^^^^^

And:

# Partner.php

public function order()
{
    return $this->hasOne('App\Order');
}   //            ^^^^^^^

So, now you could make your relationship work like so in your Order resource:

<?php

namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;

class Order extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id'           => $this->id,
            'status'       => $this->status,
            'client_email' => $this->client_email,
            'partner_id'   => $this->partner_id,
            'partner_name' => $this->partner->name,   // <---
        ];

    }
}

As a sidenote, given the fact that you want to use this Resource to return several models, when the resource will try to access the relationship value it will make an additional query.. the famous N+1 problem. To avoid it, just eager load the relationship in your controller:

use App\Http\Resources\Order as OrderResource;

public function index()
{
    $orders = Order::with('partner')->get();
    //               ^^^^^^^^^^^^^^^^^^^^^^^
    return OrderResource::collection($orders);
}

Upvotes: 1

Erich
Erich

Reputation: 2616

Access partner attributes using the relationship from your model in the resource:

return [
    'id' => $this->id,
    'status' => $this->status,
    'client_email' => $this->client_email,
    'partner_id' => $this->partner->id,       // <-- here
    'partner_name' => $this->partner->name,   // <-- here
];

EDIT:

In your controller, pass in exactly the data you want to use/transform. In your case, you're passing in a collection of User. You also need to pass in any relationships you are relying on.

return App\OrderResource::collection(Order::with('partner')->get());

Upvotes: 0

Related Questions