unisharp/buyable
UniSharp Buyable is a Laravel package for adding purchase functionality to Eloquent models. It offers a lightweight way to mark items as buyable and build simple cart, checkout, or order workflows without reinventing core ecommerce logic.
Architecture fit. The package occupies a narrow, well-understood seam: it defines a Buyable contract (price, currency, purchasability) plus a trait that satisfies it on any Eloquent model. That is idiomatic Laravel — contracts for swappable behavior, traits for opt-in reuse — and it keeps pricing concerns out of cart, checkout, and order code. Conceptually this is the right shape for a product catalog that spans plans, physical goods, and services. The abstraction is deliberately thin, which is both its virtue (low coupling, no config sprawl, no schema ownership) and its weakness (it is a handful of interfaces we could write ourselves in an afternoon).
Integration feasibility. Mechanically trivial if it installs: composer require, use the trait, implement the contract. The real gate is Composer resolution. A package last released 2018-03-21 will almost certainly constrain illuminate/support and illuminate/database to the 5.5–5.7 line and predate PHP 8 typed-property and return-type enforcement. On Laravel 10/11/12 the install will likely fail on constraints, or succeed with --ignore-platform-reqs and then break at runtime on signature mismatches. This must be verified against our actual composer.json before any estimate is credible.
Technical risk. High, and concentrated in a single dimension: abandonment. Zero dependents and three stars mean no field validation — no one has exercised this against a real checkout in years, no security advisory coverage exists, and there is no upgrade path. The score of 0.315 is a fair reflection. The functional risk is modest (the logic is small and readable), but the supply-chain risk is not: we would be the only party who has ever cared whether it works on our framework version. There is also an unquantified correctness risk in how price is represented — a 2018-era package may return floats rather than integer minor units, which is the classic source of rounding drift in money handling.
Key questions.
composer.json constraints, and do they resolve on our Laravel/PHP versions?Money object? Is currency ISO-4217 validated or a free string?Verdict for the record: the pattern is worth adopting; the dependency probably is not. The likely recommendation is to implement the two or three interfaces in-house, or fork under our namespace, and treat the package as a design reference — unless the compatibility check comes back clean and the surface area turns out to be larger than the description suggests.
Stack fit. Designed for Laravel 5.x. If our stack is 5.5–5.7, fit is native and the integration is a one-line trait addition. If we are on 8+, treat it as incompatible-by-default and require a spike before commitment. This is the single decision point that determines whether the rest of this assessment matters.
Migration path. Three options, in order of preference:
Buyable (price, currency, isPurchasable()) in our domain layer, back it with a trait, and document it. Cost is measured in hours; we own the contract and its evolution. Recommended.app/Support or a private package, add return types and PHP 8 compatibility, add tests. Same ownership cost as option 1 but preserves any subtle behavior we would otherwise re-derive.Option 3 is a legitimate choice only if the trait is genuinely more than a stub; the description implies it may not be.
Compatibility. Beyond framework version, check: how the price accessor is named and typed (attribute vs. method), whether currency falls back to a configured default or returns null, and whether purchasability is a stored column, a computed check, or both. These determine how much adaptation code sits between the contract and our cart. Also confirm there is no implicit dependency on a specific cart or order package.
Sequencing.
use of the trait across catalog entities, starting with one product type as a canary.Steps 1 and 3 are cheap and reversible; step 5 is where switching cost accumulates, so it should come last.
Maintenance. Effectively zero upstream maintenance, which means all of it is ours. No release cadence, no issue triage, no patches. Budget for periodic framework-upgrade breakage as a recurring, if small, line item — and note that the breakage will surface as a fatal at boot, not as a test failure, unless we add coverage ourselves.
Support. None. No maintainer SLA, no community to escalate to, no Stack Overflow corpus. Internal support burden is low in absolute terms because the surface is small, but there is no backstop: a new engineer encountering this will have only the source and whatever we write down.
Scaling. Negligible. It is a contract and a trait — no migrations, no tables, no service provider overhead, no runtime cost. The one scaling-adjacent concern is data access: if price resolution reads a related table (e.g., a prices relation), naive rendering of catalog pages will produce N+1 queries, and a 2018-era trait will not warn about it. Enforce eager loading at the repository layer rather than relying on the package.
Failure modes.
Mitigations are cheap: one reconciliation test on money math, one eager-loading assertion, and an explicit README note stating we own this and where the fork boundary is.
Ramp-up. Hours, not days. A mid-level Laravel engineer can read the full source in an afternoon and be productive immediately. The cost is not learning the package; it is the decision overhead of owning it — which is precisely why the reimplement-in-house option deserves serious weight despite its higher day-one cost.
How can I help you explore Laravel packages today?