【问题标题】:How to convert this to a nice Eloquent query如何将其转换为漂亮的 Eloquent 查询
【发布时间】:2013-07-21 09:01:44
【问题描述】:

如何用Eloquent查询,所有没有某种证书的用户?

Laravel 4

我有 2 张桌子:

users table:
   ->id
   ->name


certificats table:
    ->id
    ->user_id
    ->certificate_type

我已经为此苦苦挣扎了好几个小时。我尝试的最后一件事是:

$users = User::with(array('certificate' => function($query)
{
    $query->where('type','!=','SL');
}))->get();

这给了我所有的用户,但我试图让所有没有证书类型“SL”的用户。

--编辑: Spencer7593 下面的原始查询有效。但我没有让雄辩的查询工作。

SELECT u.*
FROM users u
LEFT
JOIN certificates c
ON c.user_id = u.id
AND c.type = 'SL'
WHERE c.user_id IS NULL

关系:

public function certificate(){
    return $this->hasMany('Certificate');
}

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

【问题讨论】:

  • 这个有帮助吗:$query->where('certificate_type','!=','SL');
  • 不,它没有:(,我也试过'certificate.type'。
  • type 指的是证书表中的列,因此应该是正确的。您没有在其他任何可能覆盖它的地方重新定义 $users 变量吗?您的User 模型中确实有适当的函数将其与证书相关联吗?
  • 我不会在其他任何地方重新定义 $users。我认为这种关系已经建立起来了。我在第一篇文章中添加了这种关系。
  • 我认为问题在于建立你们的关系。

标签: php mysql laravel-4 relationship eloquent


【解决方案1】:

获取所需结果集的 SQL 相当简单。

SELECT u.*
  FROM users u
  LEFT
  JOIN certificates c
    ON c.user_id = u.id
   AND c.type = 'SL'
 WHERE c.user_id IS NULL

这是一种熟悉的模式,称为“反连接”。基本上,这是一个 LEFT JOIN 查找匹配的行,以及来自users 的没有匹配的行,然后过滤掉所有匹配的行,我们留下来自users 的行没有匹配项。

诀窍是让 Eloquent 为您生成该 SQL。要让 Eloquent 做到这一点,您需要告诉 eloquent 进行 LEFT JOIN,并添加 WHERE 子句,

也许这样的事情会很接近:

->left_join('certificate AS c', function($join){
      $join->on('c.user_id','=','user.id');
      $join->and_on('c.type','=','SL');
  })
->where_null('c.user_id')

跟进

(为了那些可能不会阅读 cmets 的人的利益)

Klass Terst (OP),在尝试 Eloquent 时报告语法问题(在上面的答案中):left_join 需要替换为 leftJoin,而 and_on 无法识别。 (后者可能是我的发明,基于whereand_whereor_where 中使用的约定。)

$users = DB::table('users')
  ->select('users.id','users.name')
  ->leftJoin('certificate AS c', function($join){
     $join->on('c.user_id','=','user.id');
     $join->on('c.type','=','SL'); 
  })
  ->where_null('c.user_id');

【讨论】:

  • 您的原始查询正在运行,但是当我尝试您的雄辩解决方案时,我得到了一个大对象。我没有t know how to use. Also i had to change left_join to leftJoin, and and_on didnt 工作(不存在?)。所以我得到了这个: $users = DB::table('users') ->select('users.id','users.name') ->leftJoin('certificate', function($join){ $join- >on('certificate.user_id','=','user.id'); $join->on('certificate.type','!=','SL'); }) ->where_null('certificate 。用户身份'); dd($users);
  • @Klaas Terst:我希望原始查询能够工作;这是一种熟悉的模式,称为“反连接”。在这种情况下,我们对从证书中返回任何列并不真正感兴趣;它只返回 users 表中的列。我绝对不是 Eloquent 的专家。我只是尝试了一些我认为可能会生成该 SQL 语句的东西。
  • @Klaas Terst:这应该是对“SL”的真正平等测试,而不是不平等测试。您想“标记”来自具有匹配“SL”行的用户的行。
【解决方案2】:

我相信问题出在你的人际关系上。

型号

class User extends Eloquent
{
    public function certificates()
    {
        return $this->hasMany('Certificate');
    }
}

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

控制器

$users = User::with(array('certificates' => function($query)
{
    $query->where('type','!=','SL');
}))->get();
return View::make('yourView')->with('users',$users);

查看

@foreach($users as $user)
    {{ $user->name }} // User's name
    @foreach($user->certificates as $certificate)
        {{ $certificate->certificate_type }} // Certificate type shouldn't be 'SL'
    @endforeach
@endforeach

我希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多