Unclosure
Closure unwrapper especially suited for Laravel PDO.
Package
Version
Mandatory
PHP
^8.2
✅
PHPStan
>=2.0
Note
Older versions have outdated dependency requirements. If you cannot prepare the latest environment, please refer to past releases.
composer require mpyw/unclosure
Call PDO::setAttribute() after database connection has been established
<?php
use Mpyw \Unclosure \Value ;
use PDO ;
function withEmulation (PDO $ pdo , bool $ enabled ): PDO
{
$ pdo ->setAttribute (PDO ::ATTR_EMULATE_PREPARES , $ enabled );
return $ pdo ;
}
$ connector = function (string $ dsn ) {
return new PDO ($ dsn );
};
// Eager Evaluation
$ pdo = Value::withCallback ($ connector ('sqlite::memory: ' ), 'withEmulation ' , true );
// Lazy Evaluation
$ pdo = Value::withCallback ($ connector , 'withEmulation ' , true );
$ pdo = $ pdo ('sqlite::memory: ' );
Temporarily change PDO attributes
<?php
use Mpyw \Unclosure \Value ;
use PDO ;
function switchingEmulationTo (bool $ enabled , &$ pdo , callable $ callback , ...$ args )
{
return Value::withEffect (
$ pdo ,
function (PDO $ pdo ) use ($ enabled ) {
$ original = $ pdo ->getAttribute (PDO ::ATTR_EMULATE_PREPARES );
$ pdo ->setAttribute (PDO ::ATTR_EMULATE_PREPARES , $ enabled );
return function (PDO $ pdo ) use ($ original ) {
$ pdo ->setAttribute (PDO ::ATTR_EMULATE_PREPARES , $ original );
};
},
$ callback ,
...$ args
);
}
$ connector = function (string $ dsn ) {
return new PDO ($ dsn );
};
// Eager Evaluation
$ pdo = $ connector ('sqlite::memory: ' );
switchingEmulationTo (true , $ pdo , function () use ($ pdo ) {
// Run queries that require prepared statement emulation
});
// Lazy Evaluation
$ pdo = $ connector ;
switchingEmulationTo (true , $ pdo , function () use (&$ pdo ) {
$ pdo = $ pdo ('sqlite::memory: ' );
// Run queries that require prepared statement emulation
});
static mixed|Closure withCallback (mixed|Closure $ value , callable $ callback , mixed .. .$ args )
Call $callback($value, ...$args) or wrap its call into Closure.
When you pass $value as Closure:
Return wrapped Closure which returns $callback($value(), ...$args) .
When you pass $value as a raw value:
Return $callback($value, ...$args) .
Arguments and Return Value
Name
Type
Description
$value
mixed (A) Closure
First argument for $callback which is unwrappable
$callback
(B) callable
A callback which takes unwrapped $value as the first argument
...$args
mixed
Second, third, ... arguments for $callback
<Return Value>
mixed (C) Closure
Decorated Closure or an unwrapped value
$ value (mixed .. .$ initialArgs ): mixed
Name
Type
Description
...$initialArgs
mixed
Arguments for unwrapping Closure
<Return Value>
mixed
An unwrapped value
$ callback (mixed $ value , ...$ args ): mixed
Name
Type
Description
$value
mixed
An unwrapped value
...$args
mixed
Arguments from Value::withCallback()
<Return Value>
mixed
A decorated unwrapped value
*(mixed .. .$ initialArgs ): mixed
Name
Type
Description
...$initialArgs
mixed
Arguments for unwrapping $value
<Return Value>
mixed
An unwrapped value which is propagated from $value(...$initialArgs)
Value::withEffect()Value::withEffectForEach()
public static withEffect (mixed|Closure &$ value , callable $ configurator , callable $ callback , mixed .. .$ args ): mixed
public static withEffectForEach ((mixed|Closure)[] &$ values , callable $ configurator , callable $ callback , mixed .. .$ args ): mixed
Call $callback(...$args), watching new assignment on &$value. You can conditionally unwrap $value in your $callback by yourself.
When you pass $value as Closure:
If $value has been unwrapped, configurations via $configurator are applied.
If $value still remains as Closure, all configurations are canceled.
When you pass $value as a raw value:
Configurations via $conigurator are immediately applied.
Arguments and Return Value
Name
Type
Description
&$value
mixed (A) Closure
An argument for $configurator which is unwrappable
$configurator
(B) callable
A configurator callback which takes unwrapped $value as the first argument
$callback
(D) callable
Any callback function
...$args
mixed
Arguments for $callback
<Return Value>
mixed
Return value from $callback(...$args)
Name
Type
Description
<Return Value>
mixed
An unwrapped value
$ configurator (mixed $ value ): ?callable
Name
Type
Description
mixed
mixed
An unwrapped value
<Return Value>
null (C) callable
An optional disposer function corresponding to the configurator
(C) $configurator Return Value
Name
Type
Description
mixed
mixed
An unwrapped value
$ callback (...$ args ): mixed
Name
Type
Description
...$args
mixed
Arguments from Value::withEffect()
<Return Value>
mixed