Skip to content

Commit 36601d2

Browse files
committed
Add lazy and proxy helpers
1 parent b4d8576 commit 36601d2

File tree

3 files changed

+653
-0
lines changed

3 files changed

+653
-0
lines changed

src/Illuminate/Support/helpers.php

Lines changed: 82 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,54 @@ 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;
215+
216+
$closureReflector ??= new class
217+
{
218+
use ReflectsClosures;
219+
220+
public function typeFromParameter($callback)
221+
{
222+
return $this->firstClosureParameterType($callback);
223+
}
224+
};
225+
226+
[$class, $callback, $options] = is_string($class)
227+
? [$class, $callback, $options]
228+
: [$closureReflector->typeFromParameter($class), $class, $callback ?: $options];
229+
230+
$reflectionClass = new ReflectionClass($class);
231+
232+
$instance = $reflectionClass->newLazyGhost(function ($instance) use ($callback) {
233+
$result = $callback($instance);
234+
235+
if (is_array($result)) {
236+
$instance->__construct(...$result);
237+
}
238+
}, $options);
239+
240+
foreach ($eager as $property => $value) {
241+
$reflectionClass->getProperty($property)->setRawValueWithoutLazyInitialization($instance, $value);
242+
}
243+
244+
return $instance;
245+
}
246+
}
247+
199248
if (! function_exists('object_get')) {
200249
/**
201250
* Get an item from an object using "dot" notation.
@@ -295,6 +344,39 @@ function preg_replace_array($pattern, array $replacements, $subject): string
295344
}
296345
}
297346

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

0 commit comments

Comments
 (0)