通过查询和显示访问多个Laravel模型的数据

时间:2014-04-24 19:43:16

标签: php laravel foreach laravel-4 eloquent

逻辑

  

一家公司有很多用户。每个用户都有很多提醒。每个警报   属于一个地方。

我想在表格中显示每个用户的提醒以及提醒的相应位置。最好在每个警报一侧使用用户名。

公司和用户通过pivotTable链接,即belongsToMany关系。 警报属​​于一个位置。 该位置有很多警报。

警报模型:

public function location()

    {
        return $this->belongsTo('Location');
    }

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

用户模型:

public function companies()
    {
        return $this->belongsToMany('Company')->withTimestamps();
    }

    public function alerts()
    {
        return $this->hasMany('Alert');
    }

公司型号:

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

位置模型:

public function alerts()
{
    return $this->hasMany('Alert');
}

到目前为止,我在控制器中有这个:

public function getAdminIndex()
{   
    $company_id = User::find(Auth::user()->id)
        ->companies()
        ->first()
        ->id;
    $alerts = Company::with('users.alerts.location')
        ->where('id', '=', $company_id)
        ->get();
    $this->layout->content = View::make('agents.admin.index',
         array('alerts' => $alerts));
}

我如何解释查询

  1. 获取经过身份验证的用户的公司ID。
  2. 获取属于该公司的每个用户,以及他们可能拥有的任何提醒及其各自的位置。
  3. 转到视图,已经执行的MYSQL查询似乎是正确的,但是,我不能在我的生活中打印出数据,例如,在每个警报中。

    我对查询进行成像将基于(基于模型):

    @foreach($alerts as $alert)
        <td>{{$alert->users->alerts->location->address_1}}</td>
    @endforeach
    

    但每次我遇到一个或另一个错误时 - 最常见的错误是Trying to get property of non-object

    如何显示每个用户的提醒及其各自的位置,我们将非常感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

正如我在您之前的问题中所述的评论中所述:您必须了解从查询(模型集或模型集)返回的内容以及动态属性(加载关系)的工作原理。 为了让你完全清楚,先做一点指导:

// Company model
public function users()
{
    return $this->belongsToMany('User')->withTimestamps();
}

// now you can do this:
$company = Company::find($someId);

$company->users;
// which does behind the scenes:
$company->users()->get();
// thus returned Collection

// Alert model
public function location()
{
  return $this->hasOne('Location');
}

// calling relation:
$alert = Alert::find($id);

$alert->location; // single model because it does the same as:
$alert->location()->first();

话虽这么说,你可以访问这样的相关模型:

$company->users->first()->alerts->first()->location->address_1;

// and for your needs use of course loops:

// don't call it $alerts as it returns company with some relations
$company = Company::with('users.alerts.location')
    ->where('id', '=', $company_id)
    ->first(); // use first not get for the reason I mentioned above

  @foreach ($company->users as $user)
    @foreach ($user->alerts as $alert)
      {{ $alert->location->address_1 }}
      ...
    @endforeach
  @endforeach

破坏警报:

// User model
// additional relation for ease of use
public function deletedAlerts()
{
   return $this->hasMany('Alert')->onlyTrashed();
}

// only change in the call is replacing alerts with deletedAlerts:
$company = Company::with('users.deletedAlerts.location')
    ->where('id', '=', $company_id)
    ->first();

@foreach ($company->users as $user)
  @foreach ($user->deletedAlerts as $alert)
    {{ $alert->location->address_1 }}
     ...
  @endforeach
@endforeach

答案 1 :(得分:0)

作为日志,因为您的模型具有正确的关系方法,我认为您的查询中缺少的所有内容(因此对象错误)都是第一个()。像这样:

@foreach($alerts as $alert)

    <td>{{$alert->users->alerts->first()->location()->address_1}}</td>

@endforeach

答案 2 :(得分:0)

老实说,您不希望控制器中的数据库调用,但在模型中保持对MVC范例的忠诚。我试图绕过这个。我认为你可以将这个重构为关系,并在foreach循环中调用所有内容。

@foreach($user->company()->users as $company_user)
<tr>
   <td>
   {{ $company_user->username }}
   </td>
   <td>
   @foreach($company_user->alerts() as $alert)
      {{ $alert->message }} - {{ $alert->location()->name }}
   @endforeach
   </td>
</tr>
@endforeach

通过这种设置和正确的关系,这应该可行。这是一个复杂的结构。缺陷是警报的数量可能是可变的(可以是0或更多)?所以你必须在一个<td>中完成这项工作。希望你能完成它!如果它成功或进展,请告诉我们!

答案 3 :(得分:0)

它不起作用,因为$alert->users是一个集合,而每个$user都有$alerts,这也是另一个集合,并且您正在尝试使用该集合中的属性,在这种情况下,您需要循环所有警报:

<击>     @foreach($ alert as $ alert)                      @foreach($ alert-&gt; users-&gt;提醒为$ alert1)                 {{$ alert1-&gt; location-&gt; address_1}}             @endforeach              @endforeach

实际上,$alert->users是一个集合所以:

@foreach($alerts as $alert)
    @foreach($alert->users as $user)
        @foreach($user->alerts as $anAlert)
            {{ $anAlert->location->address_1 }}
        @endforeach               
    @endforeach       
@endforeach

好吧,让我们重写整个事情:

$companies = Company::with('users.alerts.location')
                    ->where('id', '=', $company_id)
                    ->get();

现在,您拥有Companyusers (collection)模型集合,每个users都有另一个Alert集合,因此有多个用户和多个警报,然后每个Alert有一个Location,所以:

@foreach($companies as $company)
    // Each User belongs to multiple company, so multiple users here
    @foreach($company->users as $user)
        // Each User has multiple alerts
        @foreach($user->alerts as $anAlert)
            // Each location belongs to one alert
            {{ $anAlert->location->address_1 }}
        @endforeach
    @endforeach
@endforeach