Skip to content

Commit 8dba754

Browse files
committed
Add lazy and proxy helpers
1 parent b4d8576 commit 8dba754

File tree

3 files changed

+649
-0
lines changed

3 files changed

+649
-0
lines changed

src/Illuminate/Support/helpers.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Illuminate\Support\Sleep;
1414
use Illuminate\Support\Str;
1515
use Illuminate\Support\Stringable as SupportStringable;
16+
use Illuminate\Support\Traits\ReflectsClosures;
1617

1718
if (! function_exists('append_config')) {
1819
/**
@@ -196,6 +197,52 @@ function literal(...$arguments)
196197
}
197198
}
198199

200+
if (! function_exists('lazy') && version_compare(phpversion(), '8.4.0', '>=')) {
201+
/**
202+
* Create a lazy instance.
203+
*
204+
* @template TValue of object
205+
*
206+
* @param class-string<TValue>|(\Closure(TValue): mixed) $class
207+
* @param (\Closure(TValue): mixed)|int $callback
208+
* @param int $options
209+
* @param array<string, mixed> $eager
210+
* @return TValue
211+
*/
212+
function lazy($class, $callback = 0, $options = 0, $eager = [])
213+
{
214+
static $closureReflector = new class
215+
{
216+
use ReflectsClosures;
217+
218+
public function typeFromParameter($callback)
219+
{
220+
return $this->firstClosureParameterType($callback);
221+
}
222+
};
223+
224+
[$class, $callback, $options] = is_string($class)
225+
? [$class, $callback, $options]
226+
: [$closureReflector->typeFromParameter($class), $class, $callback ?: $options];
227+
228+
$reflectionClass = new ReflectionClass($class);
229+
230+
$instance = $reflectionClass->newLazyGhost(function ($instance) use ($callback) {
231+
$result = $callback($instance);
232+
233+
if (is_array($result)) {
234+
$instance->__construct(...$result);
235+
}
236+
}, $options);
237+
238+
foreach ($eager as $property => $value) {
239+
$reflectionClass->getProperty($property)->setRawValueWithoutLazyInitialization($instance, $value);
240+
}
241+
242+
return $instance;
243+
}
244+
}
245+
199246
if (! function_exists('object_get')) {
200247
/**
201248
* Get an item from an object using "dot" notation.
@@ -295,6 +342,37 @@ function preg_replace_array($pattern, array $replacements, $subject): string
295342
}
296343
}
297344

345+
if (! function_exists('proxy') && version_compare(phpversion(), '8.4.0', '>=')) {
346+
/**
347+
* Create a lazy proxy instance.
348+
*
349+
* @template TValue of object
350+
*
351+
* @param class-string<TValue>|(\Closure(TValue): TValue) $class
352+
* @param (\Closure(TValue): TValue)|int $callback
353+
* @param int $options
354+
* @return TValue
355+
*/
356+
function proxy($class, $callback = 0, $options = 0)
357+
{
358+
static $closureReflector = new class
359+
{
360+
use ReflectsClosures;
361+
362+
public function typeFromParameter($callback)
363+
{
364+
return $this->firstClosureParameterType($callback);
365+
}
366+
};
367+
368+
[$class, $callback, $options] = is_string($class)
369+
? [$class, $callback, $options]
370+
: [$closureReflector->typeFromParameter($class), $class, $callback ?: $options];
371+
372+
return (new ReflectionClass($class))->newLazyProxy($callback, $options);
373+
}
374+
}
375+
298376
if (! function_exists('retry')) {
299377
/**
300378
* Retry an operation a given number of times.

0 commit comments

Comments
 (0)