Reputation: 55
I have an one to one relationship in laravel same as following:
public function Category()
{
return $this->belongsTo(Categories::class);
}
and run this eloquent query:
Product::with('category')->first();
this query return:
{
"name": "Green Book",
"category": {
"id": 1,
"name": "Book"
}
}
but I went this data:
{
"name": "Green Book",
"category": "Book"
}
Is it possible to do this without using a loop?
Upvotes: 3
Views: 10870
Reputation: 190
I get same result so, i tried but didn't get right result. how to change the result of laravel eloquent relation. I found one way and used transformer. we can change the result in transformer.
$result = Event::with(['eventType'])
->where('id', $id)
->where('user_id', auth()->user()->id)
->first();
return $this->trans->transform($result);
this is the result and i used transformer as follow.
public function transform(Event $Event)
{
return [
'id' => $Event->id,
'company_id' => $Event->company_id,
'calendar_id' => $Event->calendar_id,
'case_id' => $Event->case_id,
'user_id' => $Event->user_id,
'title' => $Event->title,
'description' => $Event->description,
'duration' => $Event->duration,
'alert_at' => $Event->alert_at,
'alert_email' => $Event->alert_email,
'email_sent' => $Event->email_sent,
'alert_popup' => $Event->alert_popup,
'popup_triggered' => $Event->popup_triggered,
'created_by' => $Event->created_by,
'completed' => $Event->completed,
'alert_offset' => $Event->alert_offset,
'icon' => $Event->icon,
'color' => $Event->color,
'snoozed' => $Event->snoozed,
'type_id' => $Event->type_id,
'datetime' => $Event->at,
'endtime' => $Event->end_time,
'event_type_name'=>$Event->eventType->name,
];
}
then, we can get right result. Focuse on 'event_type_name'=>$Event->eventType->name,
But i have one problem yet.
now, the result is only 1 row. it is just first()
.
but if i use get()
, i can't use transformer.
of course, i can loop the result using foreach()
.
but i think it is not right way.
what is better way?
Please answer.
Upvotes: 1
Reputation: 4813
According to Laravel Doc Eager Loading Specific Columns
You may use the following
Product::with('category:id,name')->first();
Or you may do it yourself :
$product = Product::with('category')->first();
$product->category = $product->category->name;
Upvotes: 0
Reputation: 2059
You can use leftJoin
return \App\Product::leftJoin('categories', 'products.category_id', '=', 'categories.id')
->select('products.*', 'categories.title as category')->get();
Upvotes: 0
Reputation: 40663
First of all it seems like you have a 1-X relationship which you are mistakenly using as a many to one. Your belongsTo
should be hasOne
since the your items have one category not the other way around.
You can use the $appends
property to append a custom field and make it behave as though it's part of your model:
Rename your relationship and add a mutator and accessor:
public function categoryRelationship()
{
return $this->hasOne(Categories::class);
}
public function getCategoryAttribute() {
return $this->categoryRelationship->name;
}
public function setCategoryAttribute($value) {
$this->categoryRelationship->name = $value;
}
You can also choose to add an event to automatically save your relationship when the model is being saved to ensure it works transparently:
protected static function booted()
{
static::saving(function ($myModel) {
$myModel->categoryRelationship->save();
});
}
}
Finally you add the $appends
property to ensure your new attribute is alwasy included in the model as though it's a native one.
protected $appends = [ 'category' ];
// This is so you don't end up also showing the relationship
protected $hidden = [ 'categoryRelationship' ];
Upvotes: 3