Laravel eloquent 给出与 DB facade 不同的结果

Laravel eloquent giving different results from DB facade

我有一个 laravel eloquent 查询,它使用 DB 门面给我一个不同的结果。我不明白为什么结果会不同。结果集的长度相同 (6),但一个数据对象键 ha 对于 eloquent 查询保持不变(这是不正确的),而 DB facade returns ha 键值正确。
Eloquent:

$add = FertilAppUser::join('farms', 'fertilappuser.farm_id', '=', 'farms.id')
            ->join('farm_blocks', 'farms.id', '=', 'farm_blocks.farm_id') 
            ->crossJoin('crops', 'farm_blocks.crop_id', '=', 'crops.id')
            ->select('fertilappuser.block_id', 'fertilappuser.id', 'farm_blocks.hectares as ha')
            ->where('fertilappuser.farm_id', '=',  16)
            ->whereNotIn('fertilappuser.block_id', [6])
            ->groupBy('fertilappuser.id')
            ->get();

eloquent 查询 returns 6 个对象项的集合,但 ha 键保持不变:

                    Collection {
                        #items: array:6 [
                          0 =>  {
                            #original: array:3 [
                              "block_id" => 140
                              "id" => 7
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          1 =>  {
                            #original: array:3 [
                              "block_id" => 809
                              "id" => 66
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          2 =>  {
                            #original: array:3 [
                              "block_id" => 152
                              "id" => 67
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          3 =>  {
                            #original: array:3 [
                              "block_id" => 143
                              "id" => 68
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          4 =>  {
                            #original: array:3 [
                              "block_id" => 149
                              "id" => 69
                              "ha" => 2.5 // does not vary
                            ]
                          }
                          5 =>  {
                            #original: array:3 [
                              "block_id" => 673
                              "id" => 70
                              "ha" => 2.5 // does not vary
                            ]
                          }
                        ]
                      }

数据库门面:

$add = DB::select('SELECT fau.id id, fau.block_id, frm_b.hectares ha ' .
        ' FROM fertilappuser as fau ' .
        ' INNER JOIN farms AS f ' .
            ' ON (fau.farm_id = f.id) ' .
        ' INNER JOIN farm_blocks as frm_b CROSS JOIN crops c ' .
            ' ON (fau.block_id = frm_b.id AND frm_b.crop_id = c.id) ' .
        ' WHERE fau.farm_id = ? AND fau.block_id NOT IN (?) ' .
        ' GROUP BY fau.id ', [16, '6']);

DB 外观 returns 长度为 6 的数组和关联的对象键 ha 值不同但正确。

array:6 [
  0 => {#985
    +"id": 7
    +"block_id": 140
    +"ha": 2.5 // correct
  }
  1 => {#983
    +"id": 66
    +"block_id": 809
    +"ha": null // correct
  }
  2 => {#988
    +"id": 67
    +"block_id": 152
    +"ha": null // correct
  }
  3 => {#1021
    +"id": 68
    +"block_id": 143
    +"ha": 4.3 // correct
  }
  4 => {#1022
    +"id": 69
    +"block_id": 149
    +"ha": 3.5
  }
  5 => {#1023
    +"id": 70
    +"block_id": 673
    +"ha": 2.53 // correct
  }
]

有谁知道为什么会有不同的结果?我在 eloquent 查询上的联接可能不正确吗?

Laravel 5.6.39

您使用 eloquent 的查询已转换为以下 SQL 代码:

select
    `fertilappuser`.`block_id`,
    `fertilappuser`.`id`,
    `farm_blocks`.`hectares` as `ha`
from
    `fertilappuser`
inner join
    `farms` on `fertilappuser`.`farm_id` = `farms`.`id`
inner join
    `farm_blocks` on `farms`.`id` = `farm_blocks`.`farm_id`
cross join
    `crops` on `farm_blocks`.`crop_id` = `crops`.`id`
where
    `fertilappuser`.`farm_id` = ?
and
    `fertilappuser`.`block_id` not in (?)
group by
    `fertilappuser`.`id`

您的 SQL 在某些部分有所不同:

  1. (可能的罪魁祸首)' INNER JOIN farm_blocks as frm_b CROSS JOIN crops c ' .
  2. (可能不太重要)你传递的是 '6' 而不是 6)
  3. (一点都不重要)别名

现在,我不确定哪个查询是正确的,但基本上不同的查询意味着不同的结果。


仅使用控制台 (php artisan tinker) 我能够生成以下查询(不需要设置,因为我实际上没有访问任何数据库)

select
    `fau`.`id` as `id`,
    `fau`.`block_id`,
    `frm_b`.`hectares` as `ha`
from
    `fertilappuser` as `fau`
inner join
    `farms` as `f` on (
        `fau`.`farm_id` = `f`.`id`
    )
inner join
    `farm_blocks` as `frm_b`
cross join
    `crops` as `c` on (
        `fau`.`block_id` = `frm_b`.`id` and `frm_b`.`crop_id` = `c`.`id`
    )
where `fau`.`farm_id` = ?
and `fau`.`block_id` not in (?)
group by `fau`.`id`

通过运行这个代码:

// You should be able to replace the first line by either
// DB::table('fertilappuser', 'fau')
// or FertilAppUser::from('fertilappuser', 'fau')
// to keep the alias
DB::connection('mysql')->table('fertilappuser', 'fau')
    ->select('fau.id as id', 'fau.block_id', 'frm_b.hectares as ha')
    ->join('farms as f', function ($join) {
        return $join->on(['fau.farm_id' => 'f.id']);
    })
    ->join('farm_blocks as frm_b', function ($join) {
        return $join;
    })
    ->crossJoin('crops as c', function ($join) {
        return $join->on(['fau.block_id' => 'frm_b.id', 'frm_b.crop_id' => 'c.id']);
    })
    ->where('fau.farm_id', 16)
    ->whereNotIn('fau.block_id', ['6']) // I still think this should be just 6
    ->groupBy('fau.id')
    ->toSql(); // replace with ->get(); to get the results

这里有些奇怪的事情:

  • 在 $joins 中使用数组符号。

通常你会写

$join->on(['fau.farm_id' => 'f.id'])

$join->on(['fau.block_id' => 'frm_b.id', 'frm_b.crop_id' => 'c.id'])

作为

$join->on('fau.farm_id', 'f.id')

$join->on('fau.block_id', 'frm_b.id')->on('frm_b.crop_id', 'c.id')

但是使用数组表示法告诉 eloquent 在其周围放置一对括号。我不确定它是否真的有助于您的查询,但我希望它完全相同。

  • 没有oninner join

由于Eloquent强制你在使用join()方法时添加一个条件,我只是传递了一个闭包并使它return成为$join本身,没有添加任何东西.