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

Scopable Laravel Package

atannex/scopable

Scopable is a lightweight Laravel package that brings reusable, composable query scopes to Eloquent models. Define common filters once as scope classes and apply them across queries to keep filtering logic clean, consistent, and easy to maintain.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • atannex/scopable is a behavior layer over Eloquent models, not a subsystem: it adds declarative state scopes (published / scheduled / draft, active flags, schedule windows, expiry, highlights, limits, composites) plus matching PHP-side checks and mutators. That is the architecturally interesting part — it gives us a single source of truth for "is this row live?" across query filtering, API serialization, and in-memory guard clauses.
  • Best fit is any domain with an editorial or time-boxed lifecycle: CMS/marketing pages, promotions and catalog visibility, announcements, feature-flag-like active windows, entitlement expiry.
  • The pain it removes is real and currently spread across our codebase: ad-hoc where('published_at', '<=', now()) clauses, inconsistent draft handling between list endpoints, and PHP checks that drift from SQL filters. Consolidating those into one declarative vocabulary is a maintainability win independent of the vendor.
  • Fits as a leaf dependency. It does not appear to own queues, storage, or HTTP concerns, so it should not constrain our layering — provided it stays a thin trait and not a global-scope side effect (see risks).

Integration feasibility

  • Installation is a single composer require; no infrastructure, no services, no credentials. Integration cost is essentially engineering time for adoption and testing.
  • Hard gates: PHP 8.2+ and Laravel 11 or 12 only. This is the first thing to validate against our fleet — any app on Laravel 10 or PHP 8.1 is immediately out of scope.
  • The README is the only integration documentation referenced; the release notes do not state whether the package ships migrations, publishes config, or expects specific column names (published_at, scheduled_at, expires_at, is_active, is_highlighted). That single unknown determines whether this is a greenfield convenience or a retrofit project.
  • Feasible for both greenfield models and retrofits where columns already exist in a compatible shape.

Technical risk

  • Vendor maturity. v1.0.0 is the first stable release from a small publisher. Semver guarantees start now, but the declared surface is broad (states, windows, composites, limits, default states, transition events), so 1.x will likely add opinionated behavior. Treat 1.x minors as reviewable, not auto-mergeable.
  • Opinionated lifecycle behavior. "Default states" and "transition events" imply boot-time hooks and model event dispatch. These can collide with existing observers, audit logging, search indexing, and notification pipelines.
  • Global vs local scopes. If any of these states are implemented as global scopes, records can silently vanish from admin tooling, exports, and reporting queries. This is the highest-severity unknown.
  • Semantic ambiguity. "Limits" and "composites" are undefined in the release notes and need concrete examples before we commit.
  • Test and maintenance posture unknown. No stated CI matrix, coverage, license, or maintainer commitment — standard OSS due diligence applies.

Key questions

  1. Does the package ship migrations, or does it require exact column names/types? Are table and column names configurable?
  2. Are states implemented as local scopes only, or do any register global scopes?
  3. What exactly do limits and composites express, with query examples?
  4. Are transition events standard Laravel events (queueable/listenable) or custom hooks? Do they fire inside the transaction?
  5. What is the backfill story for existing rows with NULL or partial date columns?
  6. What indexes do the date-window and period scopes assume, and how is timezone handled?
  7. License, CI matrix, test coverage, and maintainer/response history?

Integration Approach

Stack fit

  • Laravel 11 (security support through early 2026) and Laravel 12 align with a current-baseline stack, and PHP 8.2+ matches what most teams already run. Confirm the fleet inventory before scoping work; the package effectively forces an upgrade on laggards rather than coexisting with them.
  • Fits cleanly alongside Eloquent-centric code and requires no changes to our deployment topology, caching layer, or CI beyond the PHP/Laravel version floor.

Migration path

  • Phase 0 — Validation spike (days, not weeks). Install in a sandbox, inspect the package source for global scopes and migrations, and run the README examples against a throwaway model. Output: a one-page findings note answering the key questions above.
  • Phase 1 — Pilot on one non-critical content model. Adopt scopes on read paths only, keep legacy query helpers in place, and add contract tests asserting the new scopes return the same result sets as the existing queries across boundary cases (exact publish instant, expiry instant, timezone edges).
  • Phase 2 — Convert read paths. Listing endpoints, API filters, and sitemap/feed generation. Instrument listing counts before and after.
  • Phase 3 — Convert write paths. Introduce mutators, default states, and transition events, wiring the events into the existing notification/indexing pipeline behind a feature flag.
  • Phase 4 — Decommission legacy helpers and document the canonical state vocabulary.

Never combine a schema change with scope adoption in the same release.

Compatibility

  • Audit for naming collisions: existing scopePublished, scopeActive, or isPublished() methods on target models will conflict or silently shadow.
  • Verify coexistence with SoftDeletes, existing observers, and any external index (Meilisearch/Elasticsearch/Algolia) that replicates filtering logic — external indexes will not inherit these scopes and must be updated in lockstep.
  • Check API resource serialization and any toArray() consumers, since new mutators and accessors change payload shape.
  • Wrap the package in a thin internal trait or repository adapter so the dependency is swappable if the vendor stalls.

Sequencing

  1. Vendor due diligence (license, security, maintenance signals).
  2. Version floor decision for PHP/Laravel across the fleet.
  3. Sandbox spike and findings review.
  4. Pilot on one model, one release cycle of observation.
  5. Standardize and document; only then convert remaining models in priority order.

Operational Impact

Maintenance

  • Steady-state cost is low: a pinned ^1.0 constraint, a thin internal adapter, and a package owner who reviews minor bumps. The recurring cost is governance — keeping every model's state vocabulary consistent once the pattern is established.
  • Small-publisher risk means slower patch turnaround. Plan to vendor-fork or patch locally in an emergency rather than assume upstream responsiveness.

Support

  • Community/OSS support only; no SLA, no escalation path. Budget a named internal owner and treat upstream issues as something we may have to fix ourselves.
  • Onboarding material should be a one-page internal convention doc (canonical column names, state map, timezone rule, event wiring), not just a link to the README.

Scaling

  • Scopes compile to query-builder constraints, so filtering stays in the database — the right side of the wire. The scaling risk is index coverage: composite indexes on (state, published_at, expires_at) are required before data volume grows, and date-window scopes evaluated against now() inhibit query-cache reuse and can be function-wrapped (non-index-friendly) if implemented carelessly.
  • Watch for N+1 or CPU cost if PHP-side checks like isPublished() are called per row inside loops over large collections; prefer collection-level filtering via the scopes.
  • Period scopes (createdThisWeek, publishedWithin) are convenient but easy to call in dashboards at scale — review their generated SQL before exposing them to reporting endpoints.

Failure modes

  • Silent disappearance of content from listings due to timezone mismatch between app and database, or a boundary condition at the exact publish/expiry instant.
  • Global-scope leakage hiding records in admin, export, or analytics paths.
  • Scheduled content never transitioning because no scheduler/queue worker runs the transition, or because transitions rely on read-time evaluation only.
  • Lost transition events if dispatched inside a transaction that rolls back, breaking downstream notifications or index updates.
  • Behavior drift on minor upgrade, particularly around default states.
  • Legacy/new path divergence during phased rollout, producing inconsistent counts between surfaces.

Mitigations: standardize on UTC everywhere, add boundary-condition tests as a merge gate, alert on anomalous listing counts, feature-flag the rollout, and keep contract tests comparing new scopes against known-good queries for one release cycle.

Ramp-up

  • Low individual ramp: an Eloquent-fluent engineer will be productive within an hour of reading the README. Team ramp is mostly about agreeing on conventions, which is where TPM effort should go — run a short internal demo, publish the convention doc, and nominate the package owner before broad adoption.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
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