Skip to content

Commit a8a0573

Browse files
committed
refactor: Allow for lazy injections
1 parent 6360da5 commit a8a0573

File tree

2 files changed

+51
-31
lines changed

2 files changed

+51
-31
lines changed

src/Concise.php

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Articulate\Concise\Contracts\EntityMapper;
77
use Articulate\Concise\Contracts\Mapper;
88
use Articulate\Concise\Contracts\Repository;
9+
use Closure;
910
use Illuminate\Database\RecordsNotFoundException;
1011
use Illuminate\Foundation\Application;
1112
use Illuminate\Support\Str;
@@ -153,50 +154,49 @@ public function repository(string $class): Repository
153154
*
154155
* @template EntityObject of object
155156
*
156-
* @param class-string<EntityObject> $class
157-
* @param string|int $identity
158-
* @param array<string, mixed> $data
157+
* @param class-string<EntityObject> $class
158+
* @param string|int $identity
159+
* @param array<string, mixed> $data
160+
* @param (\Closure():EntityObject)|null $factory
159161
*
160-
* @return object|null
162+
* @return object
161163
*
162-
* @phpstan-return EntityObject|null
164+
* @phpstan-return EntityObject
163165
*
164166
* @throws \Illuminate\Contracts\Container\BindingResolutionException
165167
*/
166-
public function lazy(string $class, string|int $identity, array $data = []): ?object
168+
public function lazy(string $class, string|int $identity, array $data = [], ?Closure $factory = null): object
167169
{
168170
/** @var \Articulate\Concise\Contracts\EntityMapper<EntityObject>|null $mapper */
169171
$mapper = $this->entity($class);
170172

171173
if ($mapper === null) {
172-
return null;
174+
throw new RuntimeException('No entity mapper registered for class [' . $class . ']');
173175
}
174176

175177
$repository = $this->repository($class);
176178

177179
try {
178180
$reflector = new ReflectionClass($class);
179-
$lazy = $reflector->newLazyProxy(
180-
/**
181-
* @phpstan-param EntityObject $proxy
182-
*/
183-
function (object $proxy) use ($repository, $identity, $mapper) {
184-
/** @var EntityObject|null $entity */
185-
$entity = $repository->getOne(Criterion::forIdentifier($identity));
186-
187-
if ($entity === null) {
188-
throw new RecordsNotFoundException('No results for entity [' . $mapper->class() . ']');
189-
}
190-
191-
return $entity;
181+
182+
$factory ??= static function (object $proxy) use ($repository, $identity, $mapper) {
183+
/** @var EntityObject|null $entity */
184+
$entity = $repository->getOne(Criterion::forIdentifier($identity));
185+
186+
if ($entity === null) {
187+
throw new RecordsNotFoundException('No results for entity [' . $mapper->class() . ']');
192188
}
193-
);
189+
190+
return $entity;
191+
};
192+
193+
$lazy = $reflector->newLazyProxy($factory);
194194

195195
$reflector->getProperty($mapper->identity())->setRawValueWithoutLazyInitialization($lazy, $identity);
196196
} catch (Throwable $e) {
197197
report($e);
198198

199-
return null;
199+
throw new RuntimeException('Unable to create lazy proxy for entity [' . $class . ']');
200200
}
201201

202202
foreach ($data as $property => $value) {

src/Support/ImplicitBindingSubstitution.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@
1919
*/
2020
final class ImplicitBindingSubstitution
2121
{
22+
private static bool $lazyInjection = false;
23+
24+
public static function lazilyInject(): void
25+
{
26+
self::$lazyInjection = true;
27+
}
28+
29+
public static function eagerlyInject(): void
30+
{
31+
self::$lazyInjection = false;
32+
}
33+
2234
/**
2335
* @var \Articulate\Concise\Concise
2436
*/
@@ -131,18 +143,26 @@ private function resolveEntity(EntityMapper $mapper, string $value, ?string $bin
131143
/** @var \Articulate\Concise\Contracts\Repository<EntityObject> $repository */
132144
$repository = $this->concise->repository($mapper->class());
133145

134-
if ($repository instanceof RoutableRepository) {
135-
$entity = $repository->getOneForRouting($value, $bindingField);
136-
} else {
137-
$entity = $repository->getOne(Criterion::forIdentifier($value));
138-
}
146+
$resolver = static function () use ($repository, $value, $bindingField, $mapper) {
147+
if ($repository instanceof RoutableRepository) {
148+
$entity = $repository->getOneForRouting($value, $bindingField);
149+
} else {
150+
$entity = $repository->getOne(Criterion::forIdentifier($value));
151+
}
152+
153+
/** @var EntityObject|null $entity */
154+
155+
if ($entity === null) {
156+
throw new RecordsNotFoundException('No results for entity [' . $mapper->class() . ']');
157+
}
139158

140-
/** @var EntityObject|null $entity */
159+
return $entity;
160+
};
141161

142-
if ($entity === null) {
143-
throw new RecordsNotFoundException('No results for entity [' . $mapper->class() . ']');
162+
if (self::$lazyInjection === true) {
163+
return $this->concise->lazy($mapper->class(), $value, factory: $resolver);
144164
}
145165

146-
return $entity;
166+
return $resolver();
147167
}
148168
}

0 commit comments

Comments
 (0)