AliReza
AliReza

Reputation: 55

How to change result of laravel relationship

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

Answers (4)

Blue Water
Blue Water

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

Foued MOUSSI
Foued MOUSSI

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

AH.Pooladvand
AH.Pooladvand

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

apokryfos
apokryfos

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

Related Questions