healthengine/laravel-better-models
A Laravel package that enhances Eloquent models with helpful conventions and utilities for cleaner, more maintainable model code. Useful for teams standardizing model behavior and reducing boilerplate in Laravel applications.
Architecture fit. healthengine/laravel-better-models is a convention-layer package: the description ("Better model defaults for Laravel") and HealthEngine's engineering blog footprint point to an abstract base Model (or trait set) that pre-configures Eloquent behaviour — likely strict-mode defaults (preventLazyLoading, preventSilentlyDiscardingAttributes), $guarded/$fillable posture, standard casts, timestamps and key conventions. That places it at the foundation of our domain layer. The blast radius is disproportionate to its size: if the defaults are wrong, every model inherits the mistake. Architecturally it is a good idea occupying a bad delivery vehicle.
Integration feasibility. Mechanically trivial — a composer require and having models extend a new base class. Practically constrained: last release September 2020 pins it to the Laravel 7/8 era and PHP 7.3–8.0 territory. Any application on Laravel 10/11 with PHP 8.2+ will hit illuminate/* constraint conflicts and, if forced through with --ignore-platform-reqs or a fork bump, likely hit Eloquent internals that changed across majors. Adoption as a live dependency is not feasible on a modern stack.
Technical risk. High, and almost entirely supply-chain and lifecycle rather than code-quality risk:
::query() chains, factories, and test helpers that assume the defaults.$guarded and mass assignment is a security decision we would be delegating to an abandoned repo. That alone warrants a line-by-line review before anything else.Key questions for the discovery pass (half a day, one engineer):
illuminate/* and PHP constraints are declared in composer.json?Model::shouldBeStrict(), preventLazyLoading, attribute casting, HasFactory)? My prior is that most of this package's value was absorbed into Laravel core between 2020 and 2023, which would make it largely redundant.Stack fit. Determine our Laravel version first; that decides everything. On L7/L8 the package could technically run, but adopting an archived dependency to save writing ~150 lines of base-class code is a poor trade at any framework version. On L9+ it will not install cleanly and should not be forced.
Recommended path: harvest, don't depend. Read the source, extract the behaviours we agree with into App\Models\Concerns\* traits plus a thin App\Models\BaseModel, and record the MIT attribution. This converts an unmaintained third-party dependency into ~1–2 days of first-party code we own outright. It also lets us discard the parts that are now native Laravel and keep only what is genuinely ours (e.g., house conventions for key strategy, soft deletes, auditing).
Compatibility work if we insisted on the dependency. Fork → bump illuminate/support and PHP constraints → pin orchestra/testbench to a matching major → run the package's own test suite → run our application suite against the fork. That fork immediately becomes a permanent maintenance line item, which is strictly worse than the harvest path for the same end state.
Sequencing.
@deprecated any legacy base model.Maintenance. A composer dependency on an archived package is a standing liability: it silently blocks framework upgrades, and the cost lands months later on whoever does the Laravel bump. The harvest path front-loads ~2 days and then costs nothing. Ongoing cost of the fork path is roughly 0.5–1 day per Laravel major, forever, plus the cognitive load of a non-standard base class in a codebase where every new hire expects vanilla Eloquent.
Support. No upstream triage, no documented upgrade notes, no maintainer to escalate to. If a subtle default causes a data-loss bug in our application, there is no one to ask. Any adoption requires a named internal owner — a requirement I would not accept for a foundation-layer package unless the value were exceptional.
Scaling. Runtime cost is nil; this is convention code, not a hot path. The operational consideration is behavioural, not performance: enabling strict-mode defaults (preventLazyLoading, preventSilentlyDiscardingAttributes) changes application behaviour globally. The first is a feature — it surfaces N+1 queries — but if enabled in production rather than gated to non-production, it converts latent N+1s into thrown exceptions and 500s. That must be staged deliberately, environment-gated initially, and backed by query monitoring.
Failure modes.
Ramp-up. Learning the package is cheap (hours), and that is a trap: the cost is not learning it, it is un-learning it. Engineers onboarding onto a non-standard base class must reason about Eloquent semantics that differ from every tutorial, StackOverflow answer, and AI-generated snippet. That friction is permanent and compounds with team size.
Recommendation. Do not take a dependency on healthengine/laravel-better-models. Treat it as a design reference: one engineer, one day, extract the good ideas into first-party traits, verify each behaviour against current Laravel native strict-mode features, and close the ticket. The only scenario that flips this recommendation is discovering the audit reveals non-trivial logic (e.g., sophisticated auditing or key-generation behaviour) that would take more than ~5 days to reimplement — in which case, fork it under MIT, own it explicitly, and schedule the Laravel-upgrade work now rather than discovering it later.
How can I help you explore Laravel packages today?