directorytree/runnable
A lightweight Laravel package that lets Eloquent models run their own actions. Add the trait, define runnable methods, and invoke reusable model-specific logic in a clean, testable way instead of scattering it across controllers, jobs, and services. Keeps behavior close to the data it acts on.
Architecture fit: Runnable addresses a narrow but real seam in Laravel applications: focused, single-purpose classes (actions, command handlers, small domain services) that are invoked through the service container rather than constructed inline. For teams already standardized on container injection and PHPUnit/Pest, the package formalizes two things a TPM usually has to enforce by convention alone — "one class, one job" and "fake at the boundary, don't mock the call site." That makes it an enabler for a service-layer architecture decision rather than a platform bet. Fit degrades sharply outside Laravel, in service-locator-heavy legacy code, or in queue-/event-first architectures where job-level faking already covers the testing need.
Integration feasibility: Low effort, high uncertainty. The mechanical work is a Composer require, service-provider auto-discovery, converting a bounded set of classes to the runnable contract, and registering fakes in tests. The v1.0.2 fix matters for planning: it corrects fakes being silently bypassed when a class is resolved with explicit constructor parameters (app()->make(Action::class, ['dependency' => $dep])), which is a common Laravel idiom. Pin ≥1.0.2. The uncertainty is validation, not complexity — 11 stars, 0 dependents, single-org maintainer, and a release date (2026-10-02) that is future-dated and must be verified before it appears in any dependency inventory or audit trail.
Technical risk: Technical risk is low; supply-chain and ownership risk are moderate. There is no third-party production validation, no commercial support, and no dependents to signal hardening. Concrete technical risks to scope: container binding collisions with existing bindings, fake state leaking across tests (especially under parallel execution), behavioral drift between real and faked classes, version-matrix gaps on Laravel/PHP, and resolution semantics under Octane or long-running queue workers. MIT licensing gives a fork/vendor escape hatch, but exercising it converts a one-line dependency into an owned internal asset.
Key questions: Which PHP and Laravel versions are in the supported/tested matrix, and does the maintainer run CI across them? Does fake resolution behave identically across make, call, method injection, queued jobs, and Octane? Is the intended scope production runtime, test-only, or both — and is there a guardrail preventing test fakes from being active in production? How are contextual bindings, interface bindings, unions, and nested dependencies handled? Does it compose cleanly with Mockery, Pest, and parallel test runners? What is the maintainer's release cadence and responsiveness expectation? Is the 2026-10-02 date accurate? If the package stalls, what is the cost to vendor or fork under MIT?
Stack fit: Best fit is a Laravel modular monolith or a multi-squad Laravel codebase that already resolves business logic from the container and wants a uniform testing seam. It is a poor fit for non-Laravel PHP, heavy facade/service-locator code, or teams without test discipline — the package doesn't create the seam, it standardizes one you already have.
Migration path: Adopt as a dev/test dependency first; do not make it a runtime dependency until it has earned that. Pick one bounded module with real side effects and existing test friction (checkout, billing, onboarding, a third-party integration wrapper). Convert a handful of focused classes, replace hand-rolled fakes and Mockery boilerplate with package-registered fakes, and keep existing interfaces or thin adapters in place so call sites are reversible by deleting an import. Codify the decision in an ADR only after the pilot produces numbers; otherwise you'll be writing standards for a pattern you haven't validated.
Compatibility: Confirm the Composer constraint, auto-discovery behavior, and PHPUnit/Pest versions before the pilot, not during it. Test the specific path v1.0.2 fixes (explicit constructor parameters), plus nested dependencies, contextual bindings, queued jobs, and parallel test execution. Inventory existing container bindings in the pilot module for collisions, and verify fakes can be reset or scoped reliably between tests.
Sequencing: (1) Engineering spike plus version-matrix check, timeboxed to 1–2 days. (2) Pilot in one low-risk module with a baseline captured beforehand — test runtime, flake rate, mock count per test. (3) Add CI guardrails for fake leakage and container-resolution regressions. (4) Document the pattern and review against agreed success criteria after one sprint. (5) Decide: expand as a team convention, hold as tactical, or fork/vendor. Gate each step on measured simplification, not on the elegance of the abstraction.
Maintenance: Code footprint is small, so routine maintenance is minimal. The real exposure is vendor risk: a small project with no dependents and limited visible maintainership may stagnate mid-adoption. Pin an exact version, subscribe to releases and issues, and pre-agree the threshold at which the team forks or vendors. Assign a named internal owner from day one — this package is small enough that "everyone owns it" reliably means nobody does.
Support: No commercial support or SLA. Support is GitHub issues plus maintainer goodwill. Treat it as a tactical developer-productivity utility, not strategic infrastructure, until adoption and cadence signals justify otherwise. Budget a small, ongoing allocation (a few hours per quarter) for upgrade review, security scanning, and documentation upkeep.
Scaling: Runtime impact should be negligible — container resolution is already on the request and job path. Test-suite scaling may improve via fakes, but parallel test execution is where global fake state and binding leakage surface; validate it before the pattern spreads across squads. If the pattern extends to production hot paths or long-running workers, verify behavior under Octane and queue workloads before rollout.
Failure modes: Fake bypass when classes are resolved with explicit constructor parameters (fixed in v1.0.2 — pin it); stale fakes leaking across tests; binding collisions with existing container registrations; breakage on Laravel major upgrades; package abandonment; accidental activation of test fakes in production; behavioral drift between a real and faked class that tests cannot see. Mitigate with integration tests that exercise the real path, fake lifecycle/reset hooks, a CI version matrix, version pinning, production-environment guards, and an internal adapter layer that keeps blast radius to a file or two.
Ramp-up: Low for Laravel engineers — the concepts map directly onto the container, action classes, and Bus::fake()-style testing they already know. Expect 1–2 days for the spike and a single short team walkthrough; the learning curve is fake registration and container-resolution semantics, not a new paradigm. TPM should timebox the pilot, define success criteria up front (reduced per-test setup, fewer mocks, faster CI, lower flake rate), and hold a go/no-go review after one sprint with a written fork-or-drop fallback.
How can I help you explore Laravel packages today?