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 Strict Stubs Laravel Package

mll-lab/laravel-strict-stubs

Laravel Strict Stubs replaces Laravel’s default scaffolding stubs with stricter versions, so generated models, controllers, and other classes include declare(strict_types=1) and opinionated defaults. A small package for teams that want consistent, stricter code from the first Artisan make command.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Scope correction first. The prior TPM assessment in the evidence pack frames this as a migration-stub formatter and evaluates only the v2.0.1 changelog line. That understates and mischaracterizes the package. mll-lab/laravel-strict-stubs is a curated set of strictly typed generator stubs covering models, controllers, migrations and more — it injects declare(strict_types=1), final classes, and explicit return/param types into everything php artisan make:* produces. The v2.0.1 brace alignment is genuinely cosmetic, but the package's value proposition is a house code-style policy encoded in scaffolding, not formatting parity for one stub. Any decision framed around "cosmetic patch" is evaluating the wrong thing.

Architecture fit. Excellent, and deliberately so. The package has essentially no runtime surface: it ships .stub files and relies on Laravel's native stub:publish mechanism, where Laravel's generators check a project-root stubs/ directory before falling back to framework defaults. There is no service provider meddling, no middleware, no config merge, nothing in the request path. From an architecture standpoint this is about as inert as a dependency can be — the entire blast radius is "what a developer sees immediately after running a generator."

Integration feasibility. High in the mechanical sense, low in the decision sense. Mechanically it is composer require --dev plus php artisan stub:publish; a developer can have it working in ten minutes. The decision-level difficulty is that the package is archived with 2 stars, a composite score of 0.155, and no release since February 2023. That combination means we are not adopting a maintained baseline — we are adopting a snapshot that nobody is going to update. Our real choice is not buy-vs-build, it is harvest-and-own vs write-from-scratch, and harvesting wins on effort by a wide margin.

Technical risk. Concentrated almost entirely in staleness, not in runtime behavior:

  • Silent drift across Laravel majors. Laravel's own stubs evolve — new generator types (enums, casts, form requests, policies), and changed shapes such as protected function casts(): array replacing the $casts property on models. An archived stub set will not track these. The failure is quiet: make:model succeeds, produces a file that compiles, but omits conventions the rest of the codebase now assumes. That is worse than a loud break.
  • Placeholder/token compatibility. Stubs are template strings with tokens like {{ namespace }}, {{ class }}, {{ model }}. If framework token contracts change, a stale stub either throws or emits malformed code. This must be diffed, not assumed.
  • final by default is a policy decision disguised as a tooling default. final on Eloquent models breaks Mockery-based test doubles and any legacy inheritance pattern. Teams that mock models in tests — common in older suites — will hit this on day one. This is the single largest source of "why is this package annoying" tickets.
  • declare(strict_types=1) on generated controllers can surface TypeErrors where request input coercion was previously implicit. Correct behavior, but it converts latent bugs into runtime errors at the boundary, and that should be a deliberate choice rather than a side effect of scaffolding.

Key questions to answer before adoption:

  1. Which Laravel major was v2.0.0/v2.0.1 built against, and what is our target major? What is the delta in framework stub inventory?
  2. Which generators does our team actually use? Adopting the full set to use four of them is unnecessary surface.
  3. Do we mock Eloquent models anywhere? If yes, final needs an explicit exception policy before rollout.
  4. Are stubs published to project-root stubs/ (override semantics) and does anything else in our stack publish to that path?
  5. Does stub:publish overwrite hand-edited stubs on re-run, and what is our recovery story if it does?
  6. What is the MIT attribution obligation if we vendor the files into our own template repo?

Integration Approach

Stack fit. Strong for Laravel 8–10 era applications on PHP 8.1+, which is almost certainly the package's support window given the 2023 release date. Fit degrades for Laravel 11/12, where the framework's own stubs have moved and this package has not. Verify by direct diff against vendor/laravel/framework/src/Illuminate/Foundation/Console/stubs/ (and the per-generator stub locations) at our pinned version — that diff is the compatibility assessment, and it takes under an hour.

Recommended migration path — vendor, don't depend. Given the archived status, I would not add a long-lived Composer dependency on this package. Instead:

  1. Create a throwaway branch and composer require --dev mll-lab/laravel-strict-stubs.
  2. Run php artisan stub:publish to materialize the stub set.
  3. Diff each generated stub against the framework default for our Laravel version.
  4. Port the deltas we actually want — strict_types, final, explicit return types — into framework-accurate stubs.
  5. Commit those stubs to the repo (or better, to our shared project skeleton / internal Laravel template).
  6. Remove the package from composer.json.

This converts an unmaintained supply-chain item into roughly a dozen files of code we own and can edit freely. It also eliminates the "we can't customize without forking" problem the prior assessment correctly flagged.

Compatibility and sequencing.

  • Sequence: inventory generators used → diff stubs against current framework → decide final/strict-types policy with engineering → vendor adapted stubs into the template repo → wire a CI gate that runs PHPStan/Larastan and Pint against freshly generated code (a smoke test that scaffolds into a temp dir and lints) → roll out to new projects only.
  • Do not retrofit existing code. This package only affects newly generated files. Applying it to existing services changes nothing until someone runs a generator, which makes rollout risk asymmetric and easy to contain.
  • For multi-repo orgs: the correct integration point is the internal Laravel skeleton/template repository, not N individual composer.json files. One maintained stub set, inherited by every new service, no per-repo dependency to audit.

If we insist on the dependency route (defensible for a single small team wanting zero setup): pin the exact version, accept that we own any Laravel-major breakage, and add a CI job that scaffolds a model/controller/migration and lints the output so drift surfaces as a red build rather than as bad code in a PR.

Operational Impact

Maintenance. The package itself requires none — because nobody is maintaining it. The maintenance burden transfers entirely to us at each Laravel major upgrade: re-diff our vendored stubs against the new framework stubs and port any new placeholders, methods, or generator types. Realistically a few hours per major, done by whoever owns developer tooling. That is a small, predictable, schedulable cost — and it is the same cost we would pay to write the stubs from scratch, just paid later and with a better starting point.

Support. None, in the formal sense. Archived repository, two stars, no vendor. Community issue tracker is effectively dead. We should not plan around upstream fixes; the vendoring approach is precisely what makes this acceptable, because after step 6 above there is no upstream to depend on.

Scaling. Runtime scaling impact is zero — nothing ships to production. Organizational scaling is the real axis: N repositories each carrying the package or a copy of the stubs is N maintenance points and N drift surfaces. Centralizing in the project skeleton collapses that to one. Worth doing even for a small fleet, because the cost of centralization is a single PR and the cost of drift is inconsistent code style across services discovered months later.

Failure modes, ranked by likelihood × impact:

  1. Silent stub drift after a Laravel major — generated code omits new framework conventions. Highest likelihood, moderate impact, mitigated by the CI scaffold-and-lint smoke test.
  2. final classes breaking test doubles — Mockery cannot mock final classes; legacy suites that mock models will fail. High likelihood on adoption day, mitigated by explicit policy and an allowlist of exceptions.
  3. Strict-types TypeErrors at controller boundaries — surfaces pre-existing coercion bugs as runtime failures. Correct but disruptive; mitigate by introducing on new projects first.
  4. Stub path collision — another package or a hand-edited stubs/ directory publishing to the same paths. Detected immediately in local testing; low impact.
  5. Accidental overwrite of customized stubs on re-running stub:publish. Low likelihood if we vendor and drop the publish step, which is another argument for vendoring.

Ramp-up. Effectively nil. A single README paragraph — "generated code is strict-typed and final by default; stubs live in stubs/; edit them there" — covers it. The genuine ramp-up cost is not learning the package, it is the policy conversation: convincing engineers that final and strict_types are house standard, and agreeing on where exceptions are legitimate. That conversation is worth having regardless of whether we adopt this package, which is arguably its strongest argument — it gives us a concrete, already-written artifact to react to instead of an abstract style debate.

Recommendation. Harvest the stubs, vendor them into the internal Laravel template, drop the dependency. Do not standardize on the package as a live dependency; the archived status makes that a liability with no compensating upstream value. Adopt the conventions enthusiastically, and the artifact as a one-time starting point.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route