user947668
user947668

Reputation: 2728

Laravel simplify nested relation output

I get all items owned by authenticated user.

$items=Auth::user()->with('items')->get();

In my view i can access items collection, but instead of title_id want to retrieve item_title value. Currently i'm able to get item_title value using code below:

$item->title->title

Is it possible to simplify it to retrieve title like this: $item->title ?

Here is my models and relations:

Users
    id
    username
Item
    id
    user_id
    title_id
Item_Titles
    id
    title

User model:

  public function items()
  {
      return $this->hasMany('Item', 'user_id', 'id');
  }

Item model:

public function user(){
    return $this->belongsTo('User', 'user_id', 'id');
} 

public function title()
{
  return $this->belongsTo('ItemTitle','title_id','id');
}

ItemTitle model:

public function item()
{
  return $this->hasMany('Item', 'title_id', 'id');
}

UPDATE

Excuse me probably I wasn't clear. To be precise - I just want to find Eloquent alternative to:

$items=Item::where('user_id','=',Auth::id())->leftJoin('item_titles', 'item.title_id', '=', 'item_titles.id')->get();

@foreach ($items as $item)
    {{ $item->title }}
@endforeach

Upvotes: 1

Views: 188

Answers (2)

Mike Miller
Mike Miller

Reputation: 3129

Just change your relationship function to

Item model:

public function title()
{
   return $this->belongsTo('ItemTitle','title_id','id')->first()->title;
}

You will need to call it as $item->title() unless you also do

public function getTitleAttribute(){
   return $this->title();
}

You might get some funny stuff with everything being called 'title' but with this $item->title should also work I think

Upvotes: 3

Thomas Kim
Thomas Kim

Reputation: 15951

Yes it is. It looks like you setup a many-to-many relationship with the Item model being the pivot table.

User Model

public function titles()
{
    return $this->belongsToMany('ItemTitle', 'items');
}

Note: Change ItemTitle to the correct namespace. Also, change items to the Item model's table name.

You can also define the inverse relationship like this:

ItemTitle Model

public function users()
{
    return $this->belongsToMany('User', 'items');
}

From there, you can get all the authenticated user's ItemTitles like this:

$titles = Auth::user()->titles;

Link to the documentation: https://laravel.com/docs/5.1/eloquent-relationships#many-to-many

Editing based on the comments below (thanks to @ash for helping clarify and for his suggestion):

The other answer is more along the lines of what you are trying to achieve so I would recommend taking a look at that. However, there is an error in your question. This does not return items:

$items=Auth::user()->with('items')->get();

That returns all users with their items eager loaded. To see proof of this, if you dd($items), you will most likely see every single user in the database.

That is most likely not what you want to do. To get all items for the authenticated users, you should do this:

$items = Auth::user()->items;

It's that simple to get a collection of items. This will run 2 queries - 1 to get the user and another to get all of his items.

Upvotes: 2

Related Questions