mpyw / unclosure
Closure unwrapper especially suited for Laravel PDO
Installs: 77 660
Dependents: 2
Suggesters: 0
Security: 0
Stars: 0
Watchers: 3
Forks: 1
Open Issues: 0
Requires
- php: ^8.2
Requires (Dev)
- phpstan/phpstan: >=2.0
- phpunit/phpunit: >=11.0
This package is auto-updated.
Last update: 2025-03-04 06:46:25 UTC
README
Closure unwrapper especially suited for Laravel PDO.
Requirements
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.
Installing
composer require mpyw/unclosure
Examples
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 });
API
Value::withCallback()
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
asClosure
:- Return wrapped
Closure
which returns$callback($value(), ...$args)
.
- Return wrapped
- When you pass
$value
as a raw value:- Return
$callback($value, ...$args)
.
- Return
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 |
(A) $value
$value(mixed ...$initialArgs): mixed
Name | Type | Description |
---|---|---|
...$initialArgs |
mixed | Arguments for unwrapping Closure |
<Return Value> | mixed | An unwrapped value |
(B) $callback
$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 |
(C) Return 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
asClosure
:- If
$value
has been unwrapped, configurations via$configurator
are applied. - If
$value
still remains asClosure
, all configurations are canceled.
- If
- When you pass
$value
as a raw value:- Configurations via
$conigurator
are immediately applied.
- Configurations via
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) |
(A) &$value
*(): mixed
Name | Type | Description |
---|---|---|
<Return Value> | mixed | An unwrapped value |
(B) $configurator
$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
*(mixed $value): void
Name | Type | Description |
---|---|---|
mixed |
mixed | An unwrapped value |
(D) $callback
$callback(...$args): mixed
Name | Type | Description |
---|---|---|
...$args |
mixed | Arguments from Value::withEffect() |
<Return Value> | mixed |