具有未大写 Laravel 关系的重复查询

Duplicated query with uncapitalized Laravel relationships

我遇到了 Laravel 5 的奇怪行为和一个简单的关系查询: 我有一个 Issues MySQL table 和另一个 Articles table。每个 Issue 都可以有一篇或多篇文章,所以这是一个普通的 OneToMany 关系。

Issue.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Issue extends Model
{
    protected $fillable = ['status', 'volume', 'number', 'date'];

    public function articles()
    {
        return $this->hasMany('App\Article');
    }
}

Article.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    protected $fillable = ['status', 'authors', 'bibliography', 'references', 'notes', 'topic', 'issue_id'];
    protected $with = ['Articles_contents'];

    public function Articles_contents()
    {
        return $this->hasMany('App\Articles_content');
    }

    public function issue()
    {
        return $this->belongsTo('App\Issue');
    }
}

ArticlesArticles_contents有另一种关系,但我认为这与我的问题无关。

当我编辑一个问题时,我想列出其中的所有文章。 文章必须按数字字段排序为 Articles table,命名为“sort”:

public function edit($id)
{
    $issue = Issue::with(array(
        'Articles' => function ($query) {
            $query->orderBy('sort', 'asc');
        }
    ))->find($id);

    $this->data['issue'] = $issue;

    return view('admin_issues_edit', $this->data);
}

我的问题在视图中:当我这样做时,要列出文章:

        @foreach( $issue->Articles as $article )
          <li id="article_{{ $article->id }}">{!! link_to_route('admin.articles.edit', $article->Articles_contents->first()->title, array($article->id)) !!}</li>
        @endforeach

...我得到了正确的、最少的查询:

select * from issues where issues.id = '8' limit 1

select * from articles where articles.issue_id in ('8') order by sort asc

select * from articles_contents where articles_contents.article_id in ('20', '14', '5')

但是如果我用小写 ->articles 做同样的事情,就像文档中建议的那样:

        @foreach( $issue->articles as $article )
          <li id="article_{{ $article->id }}">{!! link_to_route('admin.articles.edit', $article->Articles_contents->first()->title, array($article->id)) !!}</li>
        @endforeach

我得到一个重复的查询,其中有一个 is not null 语句:

select * from issues where issues.id = '8' limit 1

select * from articles where articles.issue_id in ('8') order by sort asc

select * from articles_contents where articles_contents.article_id in ('20', '14', '5')

select * from articles where articles.issue_id = '8' and articles.issue_id is not null

select * from articles_contents where articles_contents.article_id in ('5', '14', '20')

当然,对 articles_contents 的两个查询是正常的,因为我在模型中进行了自动预先加载,但我收到了对 Articles table 的两个查询:第一个是我要求的正确排序,第二个是奇怪的 issue_id is not null part.

怎么了? :)

因为,什么时候做:

 @foreach( $issue->Articles as $article )
      <li id="article_{{ $article->id }}">{!! link_to_route('admin.articles.edit', $article->Articles_contents->first()->title, array($article->id)) !!}</li>
 @endforeach

您循环已经(已加载)可用的 Articles 因为您使用了:

array(
    'Articles' => function ($query) {
        $query->orderBy('sort', 'asc');
    }
)

所以 Articles 存在,但是当您使用 articles 时,它会立即加载文章,因为关系数组中没有可用的 articles 键。所以这是在 运行 时间执行的另一个查询,这是 Eloquent 关系的动态行为,是的 is not null 在执行查询时被 Laravel 使用。