【问题标题】:Emulating eager loading with query使用查询模拟急切加载
【发布时间】:2023-03-25 18:18:01
【问题描述】:

假设我们有表 dogbreed 以及相应的模型:

class Dog extends Model {
    protected $table = 'dogs';
    protected $fillable = [
        'name', 'breed_id'
    ];
    protected $hidden = [ 'breed_id' ];

    public function breed() {
        return $this->belongsTo(Breed::class, 'breed_id');
    }
}

class Breed extends Model {
    protected $table = 'breeds';
    protected $fillable = [
        'name'
    ];
}

我们可以像这样急切地加载和访问品种:

$dogs = Dog::with('breed')->all();

如果我们有一个 API 函数返回这个狗的集合,默认情况下它会将它们格式化为 JSON,并且每个狗对象都有一个“品种”对象:

{"dogs":[
    {
      "id": 1,
      "name": "Rover",
      "breed": {
                 "id": 1,
                 "name": "Golden Retriever"
               }
    }
    //etc

现在假设我们需要使用原始查询加载狗(这是一个简单的示例,请假装我们使用原始查询是有充分理由的)。我们可以使用 JOIN 来获取品种名称:

$query = "SELECT dogs.*, breeds.name AS breed_name
          FROM dogs
          JOIN breeds ON dogs.breed_id = breeds.id";
$dogs = DB::select(DB::raw($query));

但是,如果我们将其作为 JSON 返回,它将具有不同的结构:

{"dogs":[
    {
      "id": 1,
      "name": "Rover",
      "breed_id": 1,
      "breed_name": "Golden Retriever"
    }

有没有办法让我们的原始查询结果与我们的 Eloquent 模型结果具有相同的格式,而不必这样做?

foreach ($dogs as $dog) {
    $dog['breed'] = array(
        'id' = $dog['breed_id'], 
        'name' => $dog['breed_name']
    );
    unset($dog['breed_id']);
    unset($dog['breed_name']);
}
return $dogs;

我之所以这么问是因为我不希望客户端应用程序必须以两种不同的方式解析结果,具体取决于特定 API 函数是使用 Eloquent 进行预加载还是使用原始查询。

【问题讨论】:

  • 我认为您需要创建类似于第一个数组以按预期方式转换和返回 json。先getdog再getbreed,把数组结构和第一个一样,把结果做成json。
  • @ShaileshSingh 在问题的最底部,我举了一个你所描述的例子。我不想走这条路,因为这意味着我们必须遍历集合中的每个项目并重新格式化它,这是一个缓慢的过程

标签: php laravel laravel-5


【解决方案1】:

即使数据库具有非常好的 JSON 支持,准确返回您想要的内容也不是那么可行。

AFAIK MySQL 不支持数组,但在 Postgres 中,您可以选择数组中的品种信息,但即便如此,您也无法键入数组的元素。

您可以选择所有内容为 JSON:

-- Postgres Example
SELECT row_to_json(row(dogs.*, ARRAY[breeds.name, breeds.id])) FROM ...

但同样,键入值比仅在代码中而不是 SQL 中实现所需功能要付出更多努力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-21
    • 2016-09-06
    • 1970-01-01
    • 2013-06-18
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    相关资源
    最近更新 更多