elasticms/helpers
PHP Helpers wraps and simplifies common PHP functions into PHPStan-compliant helpers, making static analysis easier and code safer across elasticMS projects. Part of the elasticMS monorepo, with docs and issue tracking available on GitHub.
Install it as a normal dependency and confirm which PHP line you need — the releases are branched per elasticMS major (6.9.x for older PHP, 7.x for the current line), so pick the branch matching your runtime before composer require elasticms/helpers.
composer require elasticms/helpers:^7.0
composer dump-autoload # some helpers are plain namespaced functions in "files" autoload
Where to look first, in this order:
vendor/elasticms/helpers/src/ — the real API. The README is a stub; the source tree is the documentation. Namespaces are grouped by concern (Standard\Json, Standard\Type, File\..., array/text utilities), so ls -R gives you the catalogue in ten seconds.vendor/elasticms/helpers/tests/ — when published, the tests are the best usage examples: they show exactly what each wrapper returns and what it throws.ems-project.github.io/#/dev/helpers/index.md — useful for intent, but always verify signatures against the installed version.First use case, and the one that pays off fastest: a boundary. Take a controller, import command, or queue job where you currently receive mixed and immediately json_decode() it. Replace that with the package's typed decode and type coercion wrappers so PHPStan knows the shape from that point on:
use EMS\Helpers\Standard\Json;
use EMS\Helpers\Standard\Type;
$payload = Json::decode(Type::string($request->getContent())); // array, not mixed
$id = Type::integer($payload['id'] ?? null); // int, or throws
That single change usually removes a cluster of @phpstan-ignore lines and mixed-type cascade errors downstream.
Coerce at the edges, never in the core. The package's value proposition is that a wrapper returns a precise type or throws. Use them in form requests, console command option parsing, config readers, and API clients; keep domain/services fully typed and free of helpers. If you find yourself calling Type::string() on an already-typed variable, the coercion is in the wrong layer.
Treat wrappers as an alternative to the PHPStan baseline, not an addition to it. Adoption pattern that works:
phpstan analyse --error-format=json then sort by file).Each deleted baseline line is a permanent win; a growing baseline is a permanent tax.
Wrap once, expose your own façade. Because the package is low-traffic and versioned with the elasticMS monorepo, don't sprinkle EMS\Helpers\... across hundreds of files. Put a thin App\Support\Typed (or extend Laravel's Str/Arr usage) that delegates to the helpers for the handful you actually use. Swapping or forking later becomes a one-file change, and your IDE autocompletes your own vocabulary.
Integrate with Laravel's typed boundaries. Custom casts, DTO fromArray() constructors, and resource classes are natural homes:
final class Money
{
public static function fromArray(array $data): self
{
return new self(Type::integer($data['amount']), Type::string($data['currency']));
}
}
Use it in tests deliberately. Assert that malformed input throws rather than silently returns false/null — this pins the behaviour you're relying on and protects you when you bump the package.
JSON/YAML/file wrappers in importers and fixtures. Seeder and import pipelines benefit most: Json::encode() returning a guaranteed string removes the string|false branch that otherwise infects every caller.
json_decode() returns null, file_get_contents() returns false. The wrappers typically throw. That's the point — but it is a behaviour change in production. Add try/catch at the boundary, map to a 422/500, and make sure error paths have test coverage before you swap call sites in bulk.@throws and catch that specific type. A broad \Throwable catch will swallow genuine bugs and defeat the purpose.files autoload key, they won't exist until composer dump-autoload runs. This bites in Docker builds that cache an old autoloader and in preloaded/opcache setups.config/helpers.php — none exists, and nothing registers itself in Laravel."elasticms/helpers": "7.3.9"), read the changelog entries touching the helpers you use, and avoid depending on undocumented edge behaviour. Fork or vendoring is a legitimate hedge if a wrapper becomes load-bearing.Type::string($x) and then pass it into an untyped array or assign it to a mixed property — you've paid the runtime cost and thrown the analysis benefit away. Keep declare(strict_types=1) in files that use them.Str::/Arr:: helpers and don't mirror their semantics (e.g. multi-byte assumptions, null handling). Pick one idiom per concern per file; mixing both in a single class is where subtle bugs live.false, dump the raw value with var_dump(get_debug_type($value)) before the call — the exception messages describe the expected type, and the most common cause is a value arriving as int where you assumed string (form input, database driver casts, decoded JSON numbers).How can I help you explore Laravel packages today?