From d663d7b6e6b6c369ead5c22e3262015eac2b04eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= <715557344@qq.com> Date: Fri, 14 Apr 2023 16:13:58 +0800 Subject: [PATCH] Support deeply nested cache relations for `model-cache`. (#5641) --- CHANGELOG-3.0.md | 1 + .../src/EagerLoad/EagerLoaderBuilder.php | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-3.0.md b/CHANGELOG-3.0.md index 81b10273b1..0a70475490 100644 --- a/CHANGELOG-3.0.md +++ b/CHANGELOG-3.0.md @@ -4,6 +4,7 @@ - [#5634](https://github.com/hyperf/hyperf/pull/5634) Added `Hyperf\Stringable\str()` helper function. - [#5639](https://github.com/hyperf/hyperf/pull/5639) Added `Redis::pipeline()` and `Redis::transaction()` support. +- [#5641](https://github.com/hyperf/hyperf/pull/5641) Support deeply nested cache relations for `model-cache`. ## Optimized diff --git a/src/model-cache/src/EagerLoad/EagerLoaderBuilder.php b/src/model-cache/src/EagerLoad/EagerLoaderBuilder.php index 06823c3bce..f4db857b54 100644 --- a/src/model-cache/src/EagerLoad/EagerLoaderBuilder.php +++ b/src/model-cache/src/EagerLoad/EagerLoaderBuilder.php @@ -14,6 +14,7 @@ use Closure; use Hyperf\Collection\Arr; use Hyperf\Database\Model\Builder; +use Hyperf\Database\Model\Collection; use Hyperf\Database\Model\Relations\Relation; use Hyperf\ModelCache\CacheableInterface; @@ -47,7 +48,18 @@ protected function getEagerModels(Relation $relation) $column = sprintf('%s.%s', $model->getTable(), $model->getKeyName()); if ($model instanceof CacheableInterface && $this->couldUseEagerLoad($wheres, $column)) { - return $model::findManyFromCache($wheres[0]['values'] ?? []); + $models = $model::findManyFromCache($wheres[0]['values'] ?? []); + // If we actually found models we will also eager load any relationships that + // have been specified as needing to be eager loaded, which will solve the + // n+1 query issue for the developers to avoid running a lot of queries. + if ($models->count() > 0 && $with = $relation->getEagerLoads()) { + $first = $models->first(); + $self = (new static($this->query->newQuery())); + $builder = $first->registerGlobalScopes($self->setModel($first))->setEagerLoads($with); + $models = new Collection($builder->eagerLoadRelations($models->all())); + } + + return $models; } return $relation->getEager();