Laravel 4热切加载多张桌子,轻松访问视图


Laravel 4 Eager Loading Multiple Table and Easy Access To The View

大家好,我是Laravel 4 PHP框架的新手,我只知道一点。我只想问一下如何急切地加载3个表(或更多),并以一种干净的方式访问变量(我有一个表用户、配置文件和状态)

**Users Table**
id (int) ai
code (varchar)
email_id (int) ref to email table
username (varchar)
password (varchar)
softdeletes, timestamps, remember token laravel defaults
**Profile Table**
id (int) ai
user_id (int) index ref to users table
lastname (varchar)
firstname (varchar)
middlename (varchar)
birthdate (date)
and more...
laravel defaults...
**Statuses Table**
id (int) ai
user_id (int) index ref to users table
message (text)
laravel defaults...

laravel提供的用户模型我只是添加了一个公共功能配置文件和状态

<?php
class User extends 'Eloquent {
    ......
public function profile()
{
    return $this->hasOne('Profile');
}
public function statuses()
{
    return $this->hasMany('Status');
}
}

配置文件和状态模型

class Profile extends 'Eloquent {
public function user()
{
    return $this->belongsTo('User');
}
}
class Status extends 'Eloquent {
public function user()
{
    return $this->belongsTo('User');
}
}

在我的HomeController索引方法中,我声明了一个变量$user,如下所示。

$user = User::with('profile', 'statuses')->whereId( Auth::id() )->first();
$statuses = $user->statuses;

然后我将状态压缩到我的视图中,然后运行

@foreach($statuses as $status)
    {{ $status->user->profile->firstname; }}
    {{ $status->message; }}
@endforeach

但我犯了一个错误。

感谢:)

您需要知道,Eloquent关系不是双向的

也就是说,在users上加载statuses并不在每个status:上加载user

$user = User::with('statuses')->first();
// query users table once and statuses table once
// now you can use statuses:
$user->statuses; // collection
$user->statuses->first(); // single status

但这是完全不同的故事

$user->statuses->first()->user; 
// query users table for the user of this status
// despite you already loaded that user and stored in $user variable
// in your case you did that in your loop:
@foreach($statuses as $status)
  {{ $status->user->profile->firstname; }}
  // here you query users table AND profiles table again

因此,如果您在foreach循环中这样做,那么您最终会得到与集合中的状态一样多的查询。


现在,最简单、最具表现力的方法是:

// controller
$user = Auth::user()->load('statuses', 'profile');
// the same as User::with('statuses', 'profile')->where('id', Auth::id())->first();
return View::make('some.view', compact('user'));

那么在你看来:

@foreach ($user->statuses as $status)
  // you can access the user, not affected by the loop
  $user->username
  // you can access the profile, not affected by the loop
  $user->profile->firstname
  // and of course each status in the loop
  $status->message
@endforeach

如果我理解在Blade视图中,您应该使用:

{{ $user->profile->firstname }} {{ $user->profile->lastname }}  
@foreach ($user->statuses as $status)
  {{ $status->message }}  {{ $status->id}}
@endforeach

以获取所选用户的所有状态消息和id。

编辑

在添加更多代码时,应该为视图分配$user$statuses变量。

现在你可以做:

@foreach ($statuses as $status)
    {{ $user->profile->firstname }} {{ $user->profile->lastname }}
    {{ $status->message }}
@endforeach

因为每个用户对于这些消息都是相同的(您从具有选定id的数据库用户处获得)

但是您只能将$user分配给您的视图,并且以下代码应该可以工作:

@foreach ($user->statuses as $status)
    {{ $user->profile->firstname }} {{ $user->profile->lastname }}
    {{ $status->message }}
@endforeach

如何获取具有状态的用户的名字关联到那里的ids

然后你可以试试这个(注意User::has('statuses'),它只会得到拥有statuses的用户):

$user = User::has('statuses')
            ->with('profile', 'statuses')
            ->whereId(Auth::id())
            ->first();

如果没有has('statuses'),您将获得所有用户,即使他们没有相关的状态。然后在您的view:中

{{ $user->profile->firstname }}
{{ $user->profile->lastname }}