【问题标题】:Laravel query builder two tables in left joinLaravel 查询生成器左连接中的两个表
【发布时间】:2019-10-23 00:22:02
【问题描述】:

我有以下查询,我正在尝试将其转换为 Laravel 的查询构建器,以便我可以利用自动转义等功能。

SELECT subjects.name, report_comments.comment
FROM subjects
LEFT JOIN (report_comments, library_comments) ON subjects.id = library_comments.subject_id
AND report_comments.library_comment_id = library_comments.id
AND report_comments.report_id = 1

查询实际上是“获取所有主题的名称,如果它们有匹配的 report_comment(通过中间 library_comments 表),则将其与主题一起返回”(主题有 1 或 0 report_cmets 用于给定的标准)。如果我直接在 MySQL 中运行它并返回我期望的结果,则该查询有效。 report_comment.report_id = 1 目前是硬编码的,但最终将成为一个占位符,以便可以传入任何 report_id

到目前为止,我已经设法得到:

DB::table('subjects')->select(['subjects.name', 'report_comments.comment'])->leftJoin('report_comments', function ($join) {
$join->on('subjects.id', '=', 'library_comments.subject_id')
->on('report_comments.library_comment_id', '=', 'library_comments.id')
->on('report_comments.report_id', '=', '1');
})

如果我添加toSql,结果是:

select `subjects`.`name`, `report_comments`.`comment` from `subjects` left join `report_comments` on `subjects`.`id` = `library_comments`.`subject_id` and `report_comments`.`library_comment_id` = `library_comments`.`id` and `report_comments`.`report_id` = `1`

这几乎是我想要的,只是它失败了,因为根本没有提到 library_comments 表:

Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'library_comments.subject_id' in 'on clause' (SQL: select `subjects`.`name`, `report_comments`.`comment` from `subjects` left join `report_comments` on `subjects`.`id` = `library_comments`.`subject_id` and `report_comments`.`library_comment_id` = `library_comments`.`id` and `report_comments`.`report_id` = `1`)'

我需要做的是告诉leftJoin 函数关于report_comments library_comments,但似乎没有任何方法可以做到这一点。我试过了:

leftJoin(['report_comments', 'library_comments'], function($join)

猜测 Laravel 可能会将一组表名转换为 (report_comments, library_comments),但这不起作用并给了我以下警告:

PHP Notice:  Array to string conversion in /home/paul/sites/report-assistant/vendor/laravel/framework/src/Illuminate/Database/Grammar.php on line 39

有没有办法将多个表传递到leftJoin,还是我需要完全重写查询才能使用 Laravel 的查询构建器?

我使用的是 laravel/framework 版本 5.8.21,我的所有依赖项都是最新的 (composer update && npm update)。

【问题讨论】:

标签: php mysql laravel


【解决方案1】:

使用BD::raw

这样写查询就可以了

 DB::table('subjects')->select(['subjects.name, report_comments.comment'])->leftJoin(DB::raw('(report_comments, library_comments)'), function ($join) {
$join->on('subjects.id', '=', 'library_comments.subject_id')
->on('report_comments.library_comment_id', '=', 'library_comments.id')
->on('report_comments.report_id', '=', '1');
})

【讨论】:

    【解决方案2】:

    不确定这是否可行,但我认为它会按照这些思路进行,希望你能从中有所收获。

    基本上添加了一个检查关系是否存在,如果存在则加入它。

    Subject::select('subjects.name, report_comments.comment')
        ->leftJoin('library_comments', 'subjects.id, '=', library_comments.subject_id')
        ->leftJoin('report_comments', function($join){
    
              if(report->library->relationship){
                  $join->on('report_comments.library_comment_id', '=', 'library_comments.id')
                  ->where('report_comments.report_id', '=', '1');
              }
    
    })
    

    【讨论】:

      【解决方案3】:

      经过一番修改,我设法分两部分找到了答案:

      首先,我必须调整连接的这一部分:

      on('report_comments.report_id', '=', '1')
      

      并将其替换为:

      where('report_comments.report_id', '=', '1')
      

      如果我不这样做,Laravel 会用反引号引用 1,导致 MySQL 将其解释为列名。

      另一个更改是使用DB::raw,我试图避免这种情况,但我认为在这种情况下这并不算太糟糕,因为我传递的是硬编码字符串而不是用户输入(或任何受用户输入影响的东西) )。 leftJoin 现在看起来像:

      leftJoin(DB::raw('(report_comments, library_comments)')
      

      【讨论】:

        猜你喜欢
        • 2022-01-20
        • 2014-05-13
        • 2018-07-06
        • 2014-01-13
        • 2016-11-12
        • 2018-07-29
        • 2017-12-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多