kunstmaan/utilities-bundle
A small Symfony utility bundle from Kunstmaan providing shared helper classes for slug generation, string and class manipulation, and common file/URL tasks. Useful across Kunstmaan bundles and handy for everyday backend work in Symfony projects.
First, the reality check: this is a Symfony bundle from 2014, with 12 stars and 0 dependents. It contains roughly two small classes — a Cipher and a ShellHelper — wrapped in a Symfony Bundle subclass and a DI extension. It does not ship a Laravel service provider, config, or facade. You will spend more time wiring it than rewriting it.
Minimal steps
composer require kunstmaan/utilities-bundle --dry-run
If it fails on symfony/symfony ~2.x constraints (likely on any PHP 8 / Laravel 9+ project), do not fight it — copy the two service classes into app/Support/ and move on. You lose nothing; the bundle adds no behaviour beyond those classes.vendor/kunstmaan/utilities-bundle/. Look at the cipher class and the shell helper class — that's the whole API surface.// app/Providers/UtilitiesServiceProvider.php
public function register(): void
{
$this->app->singleton(Cipher::class, fn () => new Cipher(
config('services.kunstmaan_utilities.cipher_key')
));
$this->app->singleton(ShellHelper::class, fn () => new ShellHelper());
}
.env (UTILITIES_CIPHER_KEY=...) and expose it via config/services.php. Never hardcode it; the class needs the exact key length.First use case: encode an opaque token — an invite token, an unsubscribe link parameter, a stored third-party credential — into a string you can put in a URL, and decode it back on the way in. That is the one thing this package genuinely simplifies, and it's a five-minute integration.
Always wrap the cipher behind your own service. The class returns raw binary from encode(), which will corrupt the moment it hits a URL, a cookie, a JSON column, or a log line. Encode at the boundary, once:
class TokenCipher
{
public function __construct(private Cipher $cipher) {}
public function encrypt(string $value): string
{
return rtrim(strtr(base64_encode($this->cipher->encode($value)), '+/', '-_'), '=');
}
public function decrypt(string $token): ?string
{
$raw = base64_decode(strtr($token, '-_', '+/'), true);
return $raw === false ? null : $this->cipher->decode($raw);
}
}
Use it for reversible data only. Passwords → Hash::make(). Anything that has to resist tampering → Laravel's built-in Crypt (AES-256-CBC with an HMAC) or encrypt()/decrypt(). The Kunstmaan cipher is unauthenticated, so treat it as obfuscation plus confidentiality, never integrity.
Shell helper: fire-and-forget work without a queue worker. The useful pattern is launching a long-running Artisan command out of band and tracking its PID:
$pid = $shell->runInBackground(sprintf(
'php %s artisan reports:build %d > /dev/null 2>&1 &',
escapeshellarg(base_path()),
$report->id
));
$report->update(['pid' => $pid, 'started_at' => now()]);
Then a scheduled command polls isRunning($pid) and calls killProcess($pid) after a timeout, updating the row state. This is a legitimate escape hatch on hosts where you can't run queue:work persistently — but it is strictly worse than a real queue: no retries, no backoff, no failure visibility, no serialization safety.
Escape everything, structurally. The shell helper takes a command string. There is no argument array. Every interpolated value goes through escapeshellarg(), and any command name through escapeshellcmd(). If a value originates from a request, and you skip this, you've written a remote code execution vulnerability.
Keep PID bookkeeping in your own table. Add pid, started_at, finished_at, status. Don't rely on the helper to remember anything — it doesn't.
Testing: fake your own TokenCipher and a ProcessRunner interface in tests. Don't try to fake the vendor classes; they'll be gone after the first refactor.
mcrypt_*, removed from PHP in 7.2. On any modern runtime it's a fatal error, not a deprecation. PECL mcrypt exists but is unmaintained and a poor bet on PHP 8.openssl_decrypt will not reproduce these ciphertexts. If you have live data, migrate with phpseclib's Rijndael implementation (which supports arbitrary block sizes) in a one-off script: decrypt, then re-encrypt with Crypt::encryptString(). Do not attempt a byte-compatible reimplementation by hand..env will "work" and produce data you can't decrypt after you fix the key to 32 characters. Validate the length at boot.isRunning() and PID reuse. These helpers typically shell out to ps -p <pid>. After a reboot, PIDs get recycled and a stale row will report "running" for an unrelated process — and killProcess() will kill it. Store the process start time alongside the PID, or write a lock/status file from the child process instead.ps, kill, & and > /dev/null don't exist on Windows. Anyone developing on Windows will get confusing failures that don't reproduce in production..env guarantees, no cwd, different user under FPM, no PATH to your PHP binary. Always use absolute paths and cd into the app root.exec/shell_exec are commonly in disable_functions on shared hosting — check php -i | grep disable_functions before designing around this.kunstmaan_utilities.cipher.key in a Symfony YAML config and a compiled container. Laravel has neither, so you'd be pulling symfony/http-kernel into a Laravel app just to satisfy autoloading. Not worth it.app/Support, add types, drop mcrypt, add a proper IV and HMAC, and you'll have something better in an afternoon. Treat this package as a reference implementation, not a dependency.How can I help you explore Laravel packages today?