Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Dynamic Helpers Laravel Package

l0n3ly/laravel-dynamic-helpers

Laravel package for managing custom helper classes dynamically. Generate helpers with php artisan make:helper, organize them in nested folders, and call them as global functions like moneyHelper() with auto-registration and singleton caching.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

The package is a conventional Laravel package (auto-discovered service provider + one Artisan command) but the mechanism is unconventional for production Laravel. v2.0.0 resolves helpers by scanning app/Helpers at service-provider boot, then:

  1. Defining real global PHP functions via eval()
  2. Writing .phpstorm.meta.php and _ide_helper.php to the project root on every boot
  3. Appending those files to .gitignore on first boot

That is three boot-time side effects (code generation, filesystem mutation, VCS mutation) sitting on the framework's hottest initialization path. For a TPM the architectural question is not "does it work" — it clearly does in a developer's local checkout — but "does this belong in a request lifecycle that must be deterministic, read-only, and horizontally scalable?"

It solves a real, small problem: Laravel's app/Helpers convention has no autoloading story, so teams either cram functions into a single helpers.php (no namespace, no DI, no testability) or manually register class aliases. Replacing function soup with injectable classes extending Helper is a defensible design position. The delivery mechanism is the liability, not the goal.

Integration feasibility

Installation is a one-liner and make:helper is a nice ergonomic win with sensible name normalization (money-helper / money_helper → MoneyHelper) and nested paths (Store/Product/UpdateHelper → storeProductUpdateHelper()). A single developer can be productive in under an hour.

The problem is verification. Because the API is generated at runtime, the codebase is opaque to the tools we rely on for confidence:

  • PHPStan/Psalm cannot see moneyHelper(), MoneyHelper::format(), or helpers()->moneyHelper() — the base class uses __call/__callStatic magic, so there are no real signatures to analyze.
  • The published "IDE autocomplete" story depends on generated stub files that are gitignored, meaning a fresh clone has no static type information until the app boots at least once.
  • _ide_helper.php is the exact filename used by barryvdh/laravel-ide-helper. Two packages writing the same artifact to the project root is a concrete, predictable collision.
  • Documentation is internally inconsistent: the README states auto-discovery needs no setup, while the v2.0.0 release notes instruct php artisan vendor:publish --tag=dynamic-helpers. For an ops runbook, that ambiguity matters.

Technical risk

Risk Severity Notes
eval() in a boot path High Executes generated strings in the global scope on every cold boot. Any escape bug or malicious file dropped into app/Helpers becomes code execution. This is a supply-chain and code-review problem, not a style preference.
Boot-time filesystem writes High Fails or throws on read-only filesystems (Lambda, distroless/immutable container images, Heroku-style ephemeral FS), on restricted open_basedir, and on CI runners with a dirty-check gate.
Global function namespace High moneyHelper() and helpers() are unprefixed and live in the root namespace. A second package or a legacy helpers.php defining the same name is a fatal redeclare error at boot.
Static analysis blind spot Medium No types, no refactor safety, no dead-code detection. Every helper call is effectively an untyped dynamic dispatch.
Laravel Octane / Swoole Medium Discovery happens at worker boot; helpers created after boot require a worker restart. Singletons cached across requests mean mutable helper state leaks between users.
Maintainer/bus factor Medium One maintainer, 1 star, 0 dependents, rapid breaking churn (v1.0 → v2.0 within a short window, helpers:ide removed in a major bump). MIT gives us fork rights, but we would own the fork.
Version claims Low Laravel 13 support asserted with a CI matrix, but 13 is ahead of most enterprise adoption; the constraint floor (Laravel 11) is fine.

Key questions

  1. What is the measured cold-boot delta with 5, 25, and 100 helpers? Is the filesystem scan and stub regeneration gated to local/testing only, or does it run in production?
  2. Are eval() and the stub writers wrapped in function_exists() / is_writable() guards, and do they degrade gracefully to a no-op when the FS is read-only?
  3. Is there a php artisan optimize-style cache so discovery happens once at deploy rather than per worker?
  4. Does it respect APP_ENV=production to suppress IDE artifact generation?
  5. How are duplicate flattened names handled — Store/Tenant and StoreTenant both map to storeTenantHelper(); is that a silent overwrite or a hard failure?
  6. Why does the singleton pattern apply to helpers that may hold request state under Octane?
  7. What is the actual delta versus "files": ["app/Helpers/helpers.php"] in composer.json plus PSR-4 autoloaded classes? The honest answer may be "ergonomics," which is a legitimate but not load-bearing justification.

Integration Approach

Stack fit

Good fit: Laravel 11–13 monolith or modular monolith, PHP 8.1+, deployed to a long-lived VM or a container with a writable working directory, team already comfortable with service providers and Artisan. Small teams with a single helpers.php and no static-analysis discipline will get real value fast.

Poor fit: serverless (Bref/Lambda), immutable distroless images, Kubernetes with readOnlyRootFilesystem: true, Octane-heavy deployments, or any codebase with a strict PHPStan level ≥ 6 gate.

Migration path

If adopted, migrate in this order:

  1. Introduce the package alongside the existing helpers.php — do not remove it immediately. Guard against fatal redeclares by confirming every legacy function name is unique against the new flattened camelCase names.
  2. Create classes one domain at a time (Money, Permission, then nested Store/*). Move the function body into a method; keep the old global function as a thin delegator (function money_format($a){ return moneyHelper()->format($a); }) so call sites don't change in the same PR.
  3. Only after the delegators are the sole remaining entries, delete helpers.php and remove it from composer.json's files array.
  4. Do not attempt an in-place 1.x → 2.x upgrade. helpers:ide was removed and the service provider changed shape; treat it as a greenfield install or skip it entirely.

Compatibility

  • Collides with barryvdh/laravel-ide-helper (shared _ide_helper.php filename) and any package shipping a global helpers() function.
  • Conflicts with CI dirty-tree checks and git diff --exit-code gates because the provider mutates .gitignore and writes root-level files.
  • Blind to PHPStan, Psalm, Rector, and IDE refactor tooling.
  • Untested against Octane, Horizon worker recycling, and multi-tenant setups where helper state must not persist.

Sequencing

A defensible 4-week evaluation, not a rollout:

  • Week 1: spike in a disposable branch. Time cold boot before/after with 5 and 50 helpers. Confirm behavior with APP_ENV=production and with the working directory chmod'd read-only.
  • Week 1: run PHPStan at the project's current level with and without the package; quantify the baseline suppression you'd need.
  • Week 2: verify Octane compatibility and singleton state leakage with a two-request test hitting a stateful helper.
  • Week 3: decide keep/fork/drop. If "fork," scope the work to strip eval, move discovery to a deploy-time artisan dynamic-helpers:cache, and namespace the generated functions.
  • Week 4: if kept, write an ADR, pin the exact version, and add a CI job that boots the app in a read-only container to catch regressions.

My recommendation: do not adopt as a dependency; treat it as a design reference. The underlying idea — helpers as first-class, injectable classes with a scaffold command — can be reproduced in ~80 lines of application code (a Helper base class, a make:helper stub, and explicit PSR-4 autoloading) without eval, without boot-time writes, and without global namespace risk. You get 90% of the ergonomics and 0% of the operational surface.

Operational Impact

Maintenance

The maintenance burden inverts the usual open-source calculus: the code is small and MIT-licensed, so fixing it is cheap — but the fixes required to make it production-safe (removing eval, adding a discovery cache, prefixing global functions, gating stub generation by environment) amount to a rewrite of its core value proposition. At 1 star and 0 dependents, we are the only meaningful consumer; there is no community to absorb the maintenance. Expect to vendor or fork on first incident. Version churn is a live concern: a breaking major already landed between v1.x and v2.0.0 with a removed Artisan command, which signals the API is still being discovered rather than stabilized.

Support

Effectively self-support. MIT provides no warranty, no SLA, no security response process. An eval-based package with a single maintainer and no dependents is a supply-chain item that belongs on an internal security review, not just an engineering checklist. Escalation path is "read the source and patch it."

Scaling

Boot-time discovery is a per-worker cost. In a fleet of N containers each running M PHP-FPM workers or Octane workers, that is N×M filesystem scans plus N×M stub writes — the writes being the expensive part and the one most likely to hit contention. Under Octane, discovery is once per worker lifetime, which is better, but helpers added at runtime (which is the package's whole premise) are invisible until restart, so the "dynamic" promise degrades to "static with extra steps."

The scaling story is fine at 1–10 helpers and a couple of containers. It does not have a good story for autoscaled ephemeral compute, which is where most teams are heading.

Failure modes

Ranked by likelihood × blast radius:

  1. Fatal on read-only FS — container fails to boot because the provider cannot write stubs. Blast radius: total outage on deploy.
  2. Global function redeclare — a second package or leftover helpers.php defines helpers(). Blast radius: total outage, and the stack trace points at the framework, not the cause.
  3. eval escape / malicious helper file — arbitrary code execution under the app's privileges. Blast radius: full compromise. Low likelihood, unacceptable severity.
  4. Octane state bleed — a helper cached as a singleton holds per-request data. Blast radius: cross-user data leakage. Silent, which makes it worse than a crash.
  5. Silent name collision on nested flattening — Store/Tenant and StoreTenant resolve to the same function; one wins non-deterministically by scan order. Blast radius: wrong behavior in production, no error.
  6. Dirty working tree in CI — .gitignore mutated, stub files appear, git diff --exit-code fails. Blast radius: pipeline red, developer confusion, slow diagnosis.
  7. Stale IDE stubs — autocomplete suggests methods that no longer exist because the last boot predates a deletion. Blast radius: developer friction only.

Ramp-up

For application developers: near zero — make:helper and a global function is the lowest-friction API possible, which is precisely the package's appeal. For platform/SRE/DX: high. Someone must own the read-only-filesystem question, the CI dirty-tree exception, the .gitignore policy, and the security sign-off on eval. That is a disproportionate amount of cross-team coordination for a helper-scaffolding convenience, and it is the single strongest argument against adoption. The asymmetry — five minutes to adopt, two weeks of platform review to operate safely — is the whole assessment in one sentence.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera