Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mstnorris's avatar

Laravel 5: How do I pass all related items to the view?

I have the default User model along with models such as Article, Task, and Module etc. What I would like to do, is within my ProfilesController is to send all the related models through to the view?

  1. Is this possible?
  2. Is this a good idea?
0 likes
46 replies
bestmomo's avatar

Yes it's possible, and it's a good idea if view need them ;)

mstnorris's avatar

@bestmomo you sure you're not British with that wit? :P

I've set up the relationships in the models. Does this make the related models available automatically when I pass the User to the view?

thepsion5's avatar

@mstnorris @bestmomo Technically yes, but they'll be loaded lazily, which means you could end up with a TON of queries on that page. To prevent that, you want to use Eager Loading, which will only use 1 extra query for relationship.

For a query:

$user = User::with('article', 'task', 'module')->where('id', $userId)->first();

For an existing instance:

$user->load('article', 'task', 'module');

Now you'll be able to access those relationships without worrying about extra queries.

1 like
michaeldyrynda's avatar

@mstnorris when you pass the User to the view, you'll be able to access the relationships via User->relationship.

It's tidier imo to pass relationship as a separate variable within your controller. It also means that anybody looking or working with the view knows what is there, rather than having to dive into the model to identify any relationships.

Using eager loading will cut down on surplus queries, too (running a single WHERE user_id IN for all Users rather than one WHERE user_id = for each User).

1 like
mstnorris's avatar

I have just installed Clockwork and I'm logging what queries are being called.

There isn't a difference in the number of queries being executed when I change:

Auth::user();

to

Auth::user()->with('article', 'module', 'note', 'reminder', 'task');

Where would it make a difference?

michaeldyrynda's avatar

Yes @mstnorris! And as @bestmomo stated, the query won't actually run without the ->get() call as with() returns an instance of the query builder, not a collection :)

mstnorris's avatar

@bestmomo thank you, but I am now getting an error saying.

Undefined property: Illuminate\Database\Eloquent\Collection::$modules
mstnorris's avatar

@bestmomo I have the following models Article, Task, and Module.

In my navigation.blade.php file

@if ( Auth::check() )
<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-cube"></i> <span class="hidden-xs">My Modules <span class="caret"></span></span></a>
    <ul class="dropdown-menu" role="menu">
        @foreach ( $user->modules as $module )
            <li><a href="#">{{ $module->module_code }} - {{ str_limit($module->name, 30) }}</a></li>
        @endforeach
        <li class="divider"></li>
        <li><a href="#">View Last Years Modules</a></li>
    </ul>
</li>
@endif

User.php

public function articles()
{
    return $this->hasMany('App\Article');
}
public function modules()
{
    return $this->belongsToMany('App\Module');
}
public function tasks()
{
    return $this->hasMany('App\Task');
}

Do you need any other information?

bestmomo's avatar

And you use that ?

Auth::user()->with('articles', 'modules', 'tasks')->get();
mstnorris's avatar

@bestmomo that works... However, and this is a big however. In my ProfilesController I have the following method:

public function dashboard()
{
    if ( Auth::check() )
    {
        $user = Auth::user()->with('articles', 'modules', 'notes', 'reminders', 'tasks')->first();

        return view('users.dashboard', compact('user'));
    }

    abbort(403);
}

This executes 9 sql queries

But when I remove the ->with(...); part, it only executes 4 queries.

public function dashboard()
{
    if ( Auth::check() )
    {
        $user = Auth::user();

        return view('users.dashboard', compact('user'));
    }

    abbort(403);
}

Why is that?

mstnorris's avatar

@bestmomo, I thought that eager loading would reduce the number of queries.

Also, how to I reference the models in my navigation?

Do I still need to use

@foreach ( Auth::user()->modules as $module )
...

because if I just use

@foreach ( $user->modules as $module )
...

I get Undefined variable: user in my navigation.blade.php file.

bestmomo's avatar

@mstnorris

Eager loading will reduce the number of queries in loops in your view.

But you send $user in your view and you dont get it ???

mstnorris's avatar

@bestmomo no I don't.

I have a layouts directory which houses a master.blade.php file which includes my partials/navigation.blade.php file. As such I have another directory partials which is on the same document level as the layouts directory which has the navigation.blade.php file within.

Could it be that my dashboard.blade.php that extends layouts.master and doesn't have access to the User model?

mstnorris's avatar

@xroot and @bestmomo here is my ProfilesController

public function dashboard()
    {
        if ( Auth::check() )
        {
            $user = Auth::user()->with('articles', 'modules', 'notes', 'reminders', 'tasks')->first();

            dd($user);

            return view('users.dashboard', compact('user'));
        }

        abbort(403);
    }

Auth::user()-> ... -> first(); always returns the first user in the database, not the actual authenticated user.

Also, the format for the output from dd($user); is:

User {#294 ▼
  #table: "users"
  #fillable: array:3 [▼
    0 => "name"
    1 => "email"
    2 => "password"
  ]
  #hidden: array:2 [▼
    0 => "password"
    1 => "remember_token"
  ]
  #connection: null
  #primaryKey: "id"
  #perPage: 15
  +incrementing: true
  +timestamps: true
  #attributes: array:7 [▼
    "id" => 1
    "name" => "Faker User"
    "email" => "fake@example.com"
    "password" => "$2y$10$fk0Ricz3lc7FBQOGW8CWEu7.Tl7QJW6Jfd5aOiaaWrDBiA/vjXIha"
    "remember_token" => "SjrYKNs18XoidM4NwfVmRr1KROWnG79o38mZl5W7qwdbvXBkRCtqfBXpPs0E"
    "created_at" => "2015-02-10 21:08:28"
    "updated_at" => "2015-02-11 11:09:51"
  ]
  #original: array:7 [▼
    "id" => 1
    "name" => "Faker User"
    "email" => "fake@example.com"
    "password" => "$2y$10$fk0Ricz3lc7FBQOGW8CWEu7.Tl7QJW6Jfd5aOiaaWrDBiA/vjXIha"
    "remember_token" => "SjrYKNs18XoidM4NwfVmRr1KROWnG79o38mZl5W7qwdbvXBkRCtqfBXpPs0E"
    "created_at" => "2015-02-10 21:08:28"
    "updated_at" => "2015-02-11 11:09:51"
  ]
  #relations: array:5 [▼
    "articles" => Collection {#304 ▶}
    "modules" => Collection {#318 ▶}
    "notes" => Collection {#322 ▶}
    "reminders" => Collection {#319 ▶}
    "tasks" => Collection {#339 ▶}
  ]
  #visible: []
  #appends: []
  #guarded: array:1 [▼
    0 => "*"
  ]
  #dates: []
  #casts: []
  #touches: []
  #observables: []
  #with: []
  #morphClass: null
  +exists: true
}
mstnorris's avatar
mstnorris
OP
Best Answer
Level 55

This is the actual answer:

ProfilesController

public function dashboard()
{
    if ( Auth::check() )
    {
        $user = Auth::user();

        $user->load('articles', 'modules', 'notes', 'reminders', 'tasks')->get();

        return view('users.dashboard', compact('user'));
    }

    abbort(403);
}

And then for example in my navigation.blade.php I can use the following (a snippet):

<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-inbox"></i> <span class="hidden-xs">Reminders</span> <span class="label label-danger">{{ $user->reminders()->count() }}</span></a>
    <ul class="dropdown-menu" role="menu">
        @foreach ( $user->reminders as $reminder )
            <li><a href="#">{{ $reminder->text }}</a></li>
        @endforeach
        <li class="divider"></li>
        <li><a href="#"><i class="fa fa-sign-out"></i> Clear All</a></li>
    </ul>
</li>
1 like
bestmomo's avatar

This will work :

 $user = \App\User::with('articles', 'modules', 'notes', 'reminders', 'tasks')->find(Auth::id());
mstnorris's avatar

@bestmomo I still don't understand that when I remove the with( ... ) part I execute fewer queries. I thought by eager loading them, that would run fewer.

bestmomo's avatar

@mstnorris You have fewer queries in controller without the with but you'll have many ones in your loops in views.

mstnorris's avatar

@bestmomo how should my navigation view look like with my drop down lists?

How do I reference the Tasks, Articles etc?

bestmomo's avatar

You should make a new post for each issue with clear context.

pmall's avatar

This is a nonsense :

$user = Auth::user()->with('articles', 'modules', 'notes', 'reminders', 'tasks')->first();

Auth::user() returns the logged in user, not a query builder. Good way of doing this would be either :

$user = Auth::user();

$user->load('articles', 'modules', 'notes', 'reminders', 'tasks');

Or use the $with attribute of the user model :

class User extends Model{

  protected $with = ['articles', 'modules', 'notes', 'reminders', 'tasks'];

}

But remember with the second method all these relationship will be loaded every time a user is retrieved.

About eager loading, it will issue one query per relationship. If you have more queries than expected you must have made a mistake somewhere.

Next

Please or to participate in this conversation.