Reputation:
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
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
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
];
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