【问题标题】:eager load model ids only仅急切加载模型 ID
【发布时间】:2018-10-08 20:51:33
【问题描述】:

使用 Laravel 5.1,我为我的 HTML5 游戏建立了深度连接和嵌套模型。当玩家登录时,它会加载他们的个人资料。

每个个人资料都有m:m 完成的任务、m:m 完成的任务、m:m 完成的小游戏等。

任务/任务/小游戏是belongsTo关系,即任务belongsTo任务,小游戏belongsTo任务等

急于将这些加载到用户->个人资料上然后需要大量时间。

然后我需要做的是只急切地加载配置文件的tasksminigames 等 ID。我通过$appends尝试了这个:

class Profile extends BaseModel
{
    protected $with = ['game', 'quests'];

    protected $appends = ['task_ids'];

    public function getTaskIdsAttribute()
    {
        return $this->tasks->pluck('id');
    }

不过,这仍会加载模型和一组任务 ID 值(加载的 task 模型也急切地加载其相关子代。)。 tasks 是一个包含两个急切加载 Task 模型的数组:

我需要加快登录速度,那么如何在没有其他属性的情况下仅加载 ID?


$start = microtime(true);
$user = User::find(Authorizer::getResourceOwnerId(), // how can I add callback here?);
$time = microtime(true) - $start;

【问题讨论】:

  • 网络传输或查询时间是性能瓶颈吗?
  • @Rafael 是的,我坚信如此
  • 为了确定,请提供网络传输和查询时间指标

标签: php laravel laravel-5.1 eager-loading


【解决方案1】:

要隐藏任务,请将其设置为hidden

protected $hidden = ['tasks'];

要仅获取查询中的 task_id,请在返回模型之前使用 select 函数调用急切/延迟加载:

public function loaded()
{
    return $this->load(['tasks' => function($q) {
        $q->select('task_id', 'foreign_key');
    }]);
}

【讨论】:

  • 使用$hidden 是否仍然对急切关系运行任务查询(以获得完整的任务模型)?意思是,我是否只是隐藏了任务模型的返回,但实际上仍在运行查询?
  • 要运行更短的查询,请在返回模型之前在我的答案中调用loaded 函数
  • loaded() 函数是否替换了getTaskIdsAttribute()
  • 好的,但是这里到底发生了什么?如果没有loaded(),并且将模型名称放在$hidden 数组中,profile 查询已经有了很大的改进。 loaded() 函数除了 getTaskIdsAttribute 并使用 $hidden 不加载完整模型之外还有什么额外的好处?
  • 还有tasksm:mprofiles 的关系,所以task_id 仍然是foreign_key
【解决方案2】:

在 Laravel 5.5+ 中,你可以使用$with = ['tasks:id'];

在此之前,使用这个:

$profiles = Profile::with(['tasks' => function($query) {
    $query->select('id');
}])->get();

【讨论】:

  • 即时从模型内部加载
  • $appends 不会触发急切加载。它分别为每个Profile 加载tasks 关系。您的控制器是返回单个配置文件还是多个配置文件?
  • 它为多个配置文件设置,但为此目的只有一个配置文件
  • 对于单个配置文件,您只需使用return $this->tasks()->pluck('id');
猜你喜欢
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 2013-06-10
  • 2014-04-22
相关资源
最近更新 更多