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 Model Expires Laravel Package

maize-tech/laravel-model-expires

A Laravel package that gives Eloquent models expiration dates. Add the trait, set an expiry, and use scopes to query active or expired records. Includes commands to prune expired models automatically, keeping your database clean and your data fresh.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Scope of this assessment: First formal assessment of maize-tech/laravel-model-expires, performed at release 1.2.0. No prior baseline exists, so this documents the package as a new candidate dependency rather than a delta review.

Architecture fit: The package follows the idiomatic Laravel package shape — a trait applied to Eloquent models that introduces an expiry timestamp, a global scope that hides expired records by default, and an Artisan command intended for scheduled purging. This is a well-worn pattern (conceptually "soft deletes, but for time") and slots into a standard Laravel domain layer without requiring a service container rebind, custom query builder, or event bus of its own. For teams already comfortable with SoftDeletes, the mental model transfers almost directly.

Integration feasibility: Low-friction. Expected path is composer require, publish/run a migration adding a nullable expires_at column, add the trait, and schedule the purge command. No external services, no credentials, no infrastructure prerequisites. The primary integration cost is not installation but semantic: deciding which models should expire, what expiry means (hidden vs. deleted vs. archived), and how existing queries behave once a global scope is active.

Technical risk:

  • Framework compatibility is the headline of this release. PR #22 adds Laravel 12 and 13 support. Laravel 13 support is the item that most needs verification — confirm whether the constraint targets a stable major or a pre-release, and confirm the supported PHP range, since neither is stated in the release notes.
  • Change velocity is low and code churn is near-zero. Every other entry in 1.2.0 is a Dependabot bump to GitHub Actions (laravel-pint-action, fetch-metadata). That is CI hygiene, not product change. Low churn is reassuring for stability but weak evidence of active maintenance.
  • Bus factor. PR #22 is a first-time contributor's change, and the project appears to be a small vendor-backed OSS package. There is no stated support SLA. The mitigation is cheap: the core behavior is small enough to fork or reimplement internally in roughly a day if the package is abandoned.
  • Global scope is the sharpest edge. Any silently applied scope can break reporting queries, admin panels, exports, and raw/DB:: queries that bypass Eloquent. This is a design-consequence risk, not a defect.
  • Behavioral coupling with SoftDeletes, model observers, and queued jobs that serialise models is unverified for this package.

Key questions to resolve before adoption:

  1. Does expiry hide, soft-delete, or hard-delete — and is that configurable per model?
  2. Is expires_at indexed by the published migration, and is null treated as "never expires"?
  3. What is the actual composer.json constraint for laravel/framework and php, and is Laravel 13 stable or dev-only?
  4. Is the purge command chunked/batch-safe, and does it fire model events?
  5. Timezone and storage format of the expiry column — UTC-normalised or app-timezone dependent?
  6. Is there an escape hatch (withExpired() / withoutGlobalScope) and is it documented?

Integration Approach

Stack fit: Targets conventional Laravel applications on Eloquent with a relational database. Best fit is content-oriented domains with a natural lifecycle — invitations, trials, OTP/token tables, listings, cached artefacts, draft records. Poor fit for event-sourced or heavily audited schemas where records must never silently disappear from reads.

Migration path:

  1. Add a nullable expires_at timestamp with an index via a new migration; do not modify existing columns.
  2. Backfill deliberately: decide whether legacy rows get NULL (never expire) or a computed date. NULL-means-immortal is the safe default for rollout, since it makes the change a no-op until data is populated.
  3. Apply the trait to one low-risk model first. Keep the global scope disabled or scoped narrowly until queries are audited.
  4. Introduce the scheduled purge only after the read path is validated.

Compatibility: Audit every read path that touches the target models — API resources, admin listings, exports, analytics jobs, and raw query builder calls. Anything using DB::table() or withoutGlobalScope() will not honour expiry. Verify interaction with SoftDeletes (two overlapping scopes can produce confusing admin behavior) and with queued jobs that resolve models by ID after the record has expired.

Sequencing: Dev spike on a branch → confirm Laravel/PHP constraint resolution in composer.lock → staging migration plus query audit → schedule the purge command with overlap protection → production rollout model-by-model, not table-by-table wholesale.

Operational Impact

Maintenance: Expect near-zero code maintenance and a steady drip of Dependabot PRs in the upstream repo — a signal of hygiene, not of feature investment. Pin to ^1.2 and let Renovate/Dependabot surface majors. Budget a review whenever the package announces a new Laravel major, since that is historically the only substantive change type here.

Support: Community/vendor OSS with no contractual support. Treat the package as "adopt with an exit plan": keep the trait usage thin and centralised (e.g., a base model or shared concern) so replacing it with an in-house trait is a contained change rather than a codebase-wide edit.

Scaling: The purge command is the scaling pressure point. Large expiry volumes turn a scheduled job into a burst of deletes — watch for lock contention, replication lag, and long-running transactions. Prefer batched deletion with a bounded chunk size and a per-run cap; run off-peak. The expires_at index is non-negotiable at scale, both for the purge scan and for scoped reads.

Failure modes to instrument:

  • Scheduler or queue worker down → expired records remain visible and readable. Alert on purge job non-execution, not just on failure.
  • Global scope bypassed in raw queries → expired data leaks into reports or exports. Enforce via code review and, ideally, a query-linting rule.
  • Timezone drift between app, database, and server → records expire hours early or late. Standardise on UTC.
  • Cache layers holding pre-expiry payloads → expired records served from cache after the DB row is gone.
  • Mass-deletion misconfiguration → irreversible data loss where soft-delete semantics were assumed. Confirm the deletion verb before production.

Ramp-up: Low. A mid-level Laravel developer can adopt, migrate, and schedule purge in under a day; the real cost is the query audit, which is proportional to how widely the target models are read. Allocate review capacity for that audit rather than for the install itself.

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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core