Laravel的Eloquent ORM vs Query Builder

时间:2015-01-17 07:27:58

标签: php mysql laravel orm eloquent

我有2个表:usersarticlesusers表有一个名为is_suspended的列,它接受yesnoarticles表有一个名为is_published的列,它接受0 1}}或1。要从数据库中提取文章数据,articles.is_published必须等于1users.is_suspended必须等于no。现在假设users.is_suspended等于yes,如果我尝试使用像这样的查询生成器获取文章的数据:

// first code:

    $articles = Article::join('users', 'articles.user_id', '=', 'users.user_id')
        ->select(['articles.*', 'users.user_name', 'users.user_email'])
        ->where('articles.article_id', '=', 9)
        ->where('articles.is_published', '=', 1)
        ->where('users.is_suspended', '=', 'no')
        ->get();

这将完美运行,不会返回任何内容(因为users.is_suspended = yes)。现在让我们尝试使用Laravel Eloquent ORM获取相同的文章:

// second code:

$articles = Article::with([
    'user' => function($query) {
        $query->select(['user_id', 'user_name', 'user_email'])
            ->where('users.is_suspended', '=', 'no');
    }])
    ->where('articles.article_id', '=', 9)
    ->where('articles.is_published', '=', 1)
    ->get();

在这种情况下,我将得到下一个结果:

[
  {
    article_id: 9,
    user_id: 1,
    article_title: "Article title here",
    article_body: "Article body here",
    is_published: 1,
    created_at: "2015-01-17 02:26:24",
    updated_at: "2015-01-17 02:26:24",
    user: null
  }
]

即使用户被暂停,它也会获取文章的数据,这是错误的。所以我的问题是如何修复第二个代码,就像第一个代码一样?

2 个答案:

答案 0 :(得分:2)

您可能希望使用with来确保延迟加载关系,但是您对其施加的任何约束仅适用于加载的关系。要限制对未暂停用户的文章的响应,您可能希望使用whereHas方法。

$articles = Article::with(['user' => function($q){
        $q->select(['user_id', 'user_name', 'user_email', 'created_at']);
    }])
    ->whereHas('user', function($q) {
        $q->where('is_suspended', '=', 'no');
    })
    ->where('articles.article_id', '=', 9)
    ->where('articles.is_published', '=', 1)
    ->get();

答案 1 :(得分:0)

你需要whereHas而不是with(或两者兼而有之,但在这种情况下不需要with),就像@DavidBarker所说的那样。

但我建议更多,请考虑此代码的可读性:

$article = Article::whereHas('user', function ($q) {
   $q->active();
})->published()->find(9);

它使用scopes

所以这就是你可以做些什么来让你的生活更轻松:

  1. is_suspended更改为bool,因为:

    $user->is_suspended; // no
    (bool) $user->is_suspended; // true    
    
  2. suspended模型上定义范围User,在published上定义Article

    // Article model - on User accordingly
    public function scopePublished($query)
    {
        $query->where('is_published', 1);
    }
    
  3. 当您想要获取单个模型时,请使用find($id)where('col', $id)->first()而不是get,因为后者将返回一个集合,即使只有一个结果。