【问题标题】:Accessing multiple Laravel model's data through a query and displaying通过查询访问多个 Laravel 模型的数据并显示
【发布时间】:2014-04-24 19:43:16
【问题描述】:

逻辑

一家公司有很多用户。每个用户都有许多警报。每个警报 属于一个位置。

我想在表格中显示每个用户的警报以及警报各自的位置。最好在每个警报的旁边加上用户名。

公司和用户通过数据透视表(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. 获取属于该公司的每个用户,以及他们可能拥有的任何警报及其各自的位置。

转到视图,已执行的 MYSQL 查询似乎是正确的,但是,我终生无法打印出数据,例如,在每个警报中。

我想象的查询将类似于(基于模型):

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

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

对于如何显示每个用户的警报及其各自位置的任何帮助,我们将不胜感激。

【问题讨论】:

  • 你能给我们展示一个查询正在检索的模型吗?
  • 您的问题是您无法区分哪个关系/查询返回集合以及哪个返回单个模型。因此,您尝试获取相关警报或一组用户/警报(集合)的位置,这显然是不可能的。
  • 您会建议 Deczo 怎样缓解这个问题?因为我不确定你在说什么对不起!
  • @seblaze 模型已添加。
  • 我希望我给出的答案能让您清楚为什么会出现这些错误以及如何正确处理。

标签: php laravel foreach laravel-4 eloquent


【解决方案1】:

正如我在评论中所说的,您可能在之前的问题中看到:您必须了解查询返回的内容(模型或模型的集合)以及动态属性(加载关系)如何工作。 为了让您非常清楚,首先提供一些指导:

// 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

【讨论】:

  • Deczo,非常感谢。你比 Laravel 文档本身解释得更好。我欠你一个人情。非常感谢。
  • 就像另一个快速询问一样,抱歉,如果我想检索完全相同的信息,但是这次删除的alerts(软删除),这个查询必须完全改变,对吗?
  • 你就像一本 Laravel 百科全书。严重地。再次感谢德克佐。我敢肯定这不会是你最后一次收到我的消息……;)
  • 嗨,Deczo,很抱歉让您感到痛苦,代码没有出现错误,但它返回的实时警报与上面的原始代码相同。我检查了应该只有两个被删除的,但所有的活的仍然显示?
  • 我可以看到正在执行的MYSQL查询是select * from alerts,其中alerts.deleted_at不为空,alerts.user_id in ('2', '7', ' 17', '18', '1', '21') 如果有帮助的话。
【解决方案2】:

由于您的模型具有正确的关系方法,我认为您在查询中缺少的所有内容(以及因此的对象错误)都是 first()。像这样:

@foreach($alerts as $alert)

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

@endforeach

【讨论】:

  • 我已经添加了我的模型。上面的代码也返回这个错误:ErrorException Undefined property: Illuminate\Database\Eloquent\Collection::$alerts
  • 请在我添加括号时尝试使用更新的回声线。谢谢
【解决方案3】:

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

@foreach($alerts 作为 $alert) @foreach($alert->users->alerts as $alert1) {{ $alert1->位置->地址_1 }} @endforeach @endforeach

实际上,$alert-&gt;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();

现在您有一组Company 模型和users (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

【讨论】:

  • 感谢您的回复,不幸的是它返回此错误ErrorException Undefined property: Illuminate\Database\Eloquent\Collection::$alerts
  • 我后来用过$alert1,你注意到了吗?
  • 我完全复制了你的代码。 $alerts 的错误看起来是指上面的行。 -&gt;users-&gt;alerts 部分。
  • 抱歉 WereWolf,我最终遵循了 Deczos 的回答。非常感谢您的帮助。
【解决方案4】:

说实话,您不希望控制器中的数据库调用,而是模型中的数据库调用保持对 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 或更多)?因此,您必须在一个 &lt;td&gt; 中执行此操作。希望你能完成它!让我们知道它是否成功或取得了进展!

【讨论】:

  • 完全同意控制器中的数据库调用。理解您的逻辑意味着,每个用户都有一个位置,该位置与警报相关。每个警报都有一个位置。我已附加我的模型。
  • 这是一个繁重的设置! ;)
  • 逻辑上,这一切对我来说都有意义!但它显示的所有信息都令人头疼!
  • 你能具体说明你想要做什么吗?因为很难从模型关系中看出。也许写出一些伪代码。就像把你的第 2 步分成更多的步骤。 :)
  • 对不起 sidneydobber,我最终遵循了 Deczos 的回答。非常感谢您的帮助。
猜你喜欢
  • 2019-08-27
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 2016-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多