mpyw/unclosure
Unclosure

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
$valueasClosure:- Return wrapped
Closurewhich returns$callback($value(), ...$args).
- Return wrapped
- When you pass
$valueas 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
$valueasClosure:- If
$valuehas been unwrapped, configurations via$configuratorare applied. - If
$valuestill remains asClosure, all configurations are canceled.
- If
- When you pass
$valueas a raw value:- Configurations via
$coniguratorare 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 |
Related Packages
mpyw/laravel-pdo-emulation-control
Temporarily enable/disable PDO prepared statement emulation
81,180
2
mpyw/laravel-mysql-system-variable-manager
A tiny extension of MySqlConnection that manages session system variables
6,229
11
detain/session-samurai
🥷 Universal high-speed asynchronous (non-blocking) SessionHandlerInterface impl...
2,345
8
shiftonelabs/laravel-sqs-fifo-queue
Adds a Laravel queue driver for Amazon SQS FIFO queues.
6,877,453
154