event-engine/php-engine-utils
Utilities for Event Engine in PHP: helper classes and shared tooling to simplify building and running Event Engine-based applications. Includes common infrastructure utilities and convenience functions to reduce boilerplate in your event-driven domain code.
Installation:
composer require event-engine/php-engine-utils
Add to composer.json under require or require-dev if needed.
First Use Case:
The package primarily provides utility classes like MapIterator and Callback for common PHP operations. Start with:
use EventEngine\Utils\MapIterator;
$array = ['a' => 1, 'b' => 2, 'c' => 3];
$iterator = new MapIterator($array, fn($key, $value) => "Key: $key, Value: $value");
foreach ($iterator as $item) {
echo $item . "\n";
}
Where to Look First:
src/: Core utility classes (e.g., MapIterator, Callback)./tests/ for usage examples and edge cases.MapIterator improvements).Transforming Traversable Objects:
Use MapIterator to apply callbacks to arrays, Traversable, or generators without manual loops:
$users = collect([['name' => 'Alice'], ['name' => 'Bob']]);
$names = new MapIterator($users, fn($user) => $user['name']);
Callback Utilities:
Leverage Callback for reusable logic (e.g., validation, transformations):
use EventEngine\Utils\Callback;
$validateName = Callback::create(fn($name) => strlen($name) > 3);
$validateName('Alice'); // Returns true
Integration with Laravel:
$this->app->singleton(MapIterator::class, fn() => new MapIterator([]));
Collection:
$collection->map(fn($item) => $item)->all(); // Replace with MapIterator for custom logic.
Generators and Lazy Loading:
Use MapIterator with generators to avoid loading large datasets:
$generator = (function() {
yield 1;
yield 2;
})();
$iterator = new MapIterator($generator, fn($item) => $item * 2);
MapIterator Traversable Quirks:
0.1.1–0.1.2 changed MapIterator from \Iterator to \Traversable and back. Ensure your code handles both:
if (!$iterator instanceof \Iterator) {
$iterator = new \ArrayIterator(iterator_to_array($iterator));
}
0.1.3, callbacks fired twice. Test with:
$calls = 0;
$iterator = new MapIterator([1, 2], fn() => $calls++);
iterator_to_array($iterator); // $calls should be 2 (pre-0.1.3) or 1 (post).
PHP 8+ Compatibility:
PHP 8.0+ (package supports it, but edge cases may exist). Use strict types if needed:
/** @var \Traversable $traversable */
$iterator = new MapIterator($traversable);
Performance:
MapIterator with generators is lazy but may cause memory issues with deep recursion. Limit generator depth or use iterator_to_array() for finite datasets.try-catch to avoid silent failures:
$iterator = new MapIterator($data, function($item) {
try {
return process($item);
} catch (\Throwable $e) {
report($e);
return null;
}
});
valid() method before rewinding:
if (method_exists($iterator, 'valid')) {
$iterator->rewind();
}
Custom Iterators:
Extend MapIterator for domain-specific logic:
class UserMapIterator extends MapIterator {
public function __construct(array $users) {
parent::__construct($users, [$this, 'transformUser']);
}
public function transformUser($user) {
return (object) $user; // Auto-convert to object.
}
}
Callback Composition: Combine callbacks for complex pipelines:
$pipeline = Callback::create(fn($data) => $data)
->then(fn($data) => strtolower($data))
->then(fn($data) => ucfirst($data));
$pipeline('HELLO'); // Returns "Hello".
Testing:
Mock MapIterator in tests to isolate logic:
$this->partialMock(MapIterator::class, ['__invoke'])
->shouldReceive('__invoke')
->andReturn('mocked');
How can I help you explore Laravel packages today?