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 Eloquent Flag Laravel Package

cybercog/laravel-eloquent-flag

Add boolean flags to any Eloquent model with cybercog/laravel-eloquent-flag. Mark records as flagged, unflag or toggle them, and query flagged or unflagged rows using clean, expressive methods and local scopes—no extra boilerplate needed.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. Trait-composition only: no service provider, no container bindings, no publishable config, no shipped migrations. The package adds nothing to the application boot cycle, which makes it trivially adoptable and trivially removable. The design is two-dimensional — boolean (is_published) vs timestamp (published_at) storage, crossed with classic (default query returns flagged records) vs inverse (default query returns unflagged records) scope direction. That maps cleanly onto the lifecycle states most Laravel apps hand-roll: draft/published, pending/approved, active/expired, kept/discarded.

The important framing for planning: this is a behavior layer, not a workflow engine. It gives publish() / undoPublish() / isPublished() / isNotPublished(), a handful of query macros (withNotPublished(), onlyNotPublished()), and two model events (published, publishedUndone). Approval chains, permissions, and transition guards remain ours.

Integration feasibility. High. Columns plus one trait import plus an optional shouldApplyXxxScope(): bool method per model. No vendor publish step, no config file, no queue worker, no scheduled task. Composer install and go. The only design decision that carries weight is whether the scope is applied — and it is opt-in per model, which is the package's single best safety property and also the thing most likely to be applied without thinking.

Technical risk.

  • Global scope data omission — highest risk. Once shouldApplyXxxScope() returns true, every Eloquent query on that model silently excludes unflagged rows: admin panels, exports, aggregates, relationship eager loads, API endpoints. Inverse variants invert the default. Reports quietly returning fewer rows than reality is the failure mode that erodes trust in the tooling.
  • Scope escape hatches. DB::table(), toBase(), joined tables, and withoutGlobalScopes() all bypass the behavior. Any BI or reporting layer built on the query builder will disagree with the ORM, silently.
  • Classic vs inverse confusion. Two parallel trait trees with near-identical names is a real defect source. There is no mixing of classic and inverse on one model.
  • Timestamp flags conflate state with audit. published_at answers "when," never "who" or "why." Undo leaves no trace unless we listen to publishedUndone ourselves.
  • HasKeptFlag performs writes you didn't ask for — sets is_kept = false on create and true on update. Any model with existing observers needs verification of ordering.
  • Vendor concentration. 134 stars, single-vendor namespace, no ecosystem integrations; the low opportunity score (2.42) reflects a mature niche rather than a growing one. Active support through Laravel 13 mitigates the abandonment tail, but the code surface is small enough that forking is cheap insurance.
  • No global kill switch. The absence of a service provider means no way to disable all flag scopes centrally during an incident. Remediation is per-model code change and redeploy.

Key questions.

  1. For each candidate model: do we need the scope, or only the boolean helpers? Applying scope to admin-facing models is usually a mistake.
  2. Do we need attribution ("who flipped this"), or is "when" sufficient? If attribution is required, we own the audit table and event listeners.
  3. Do any models genuinely need inverse semantics, or is inverse just how a queue view would be written? Inverse traits are a separate import and a separate mental model — justify each one.
  4. Have we sized the indexes? Every applied scope adds a predicate; a lone boolean index on a large table is low-selectivity and near-useless.
  5. Is this domain allowed to depend on a small third-party package whose semantics must not drift (compliance, billing, published-content visibility)? If yes, pin exact versions and fork-readiness is a precondition, not a contingency.

Integration Approach

Stack fit. Laravel 9–13, PHP 8.0–8.5 covers essentially any current Laravel estate, including one mid-upgrade. Composer-only, MIT, PSR-12, declare(strict_types=1) throughout — it will pass an existing style gate. Note that the package's own suite runs on Orchestra Testbench with in-memory SQLite, so its guarantees are framework-level, not database-level; Postgres/MySQL behavior, index plans, and collation edge cases are ours to validate. That's normal for a package of this shape but should be stated explicitly to whoever owns the data layer.

Migration path. Purely additive — no rewrite, no data migration tooling required.

  1. Add columns (is_published boolean default false, published_at nullable timestamp) alongside existing state columns.
  2. Backfill from the current source of truth.
  3. Add the trait without shouldApplyXxxScope(); verify writes, casts, and events fire correctly.
  4. Only then enable the scope, model by model.

The step that changes behavior is #4, not #3. Treat it as a release, not a refactor.

Compatibility considerations.

  • SoftDeletes stack with these scopes; interaction order and resulting SQL are our responsibility to verify.
  • Filament / Nova / custom admin will produce "records are missing" tickets the day a scope turns on. Either exclude admin models from scope application or use explicit withoutGlobalScope in resources — never both inconsistently.
  • Preview and draft endpoints authenticated by token need explicit scope overrides; a default-published model hides drafts from the people whose job is reviewing them.
  • HasKeptFlag must not be attached to models with write observers until ordering is confirmed.
  • Inverse traits are per-model imports; document which model uses which direction in a single table.

Sequencing.

  1. Spike one non-critical model (Article-class) end-to-end in a branch; capture query plans and index requirements.
  2. Write a one-page internal convention: model → trait → scope applied y/n → columns → events consumed.
  3. Add listeners for published / publishedUndone into our audit log if attribution is needed.
  4. Roll out scope application model-by-model behind a feature flag, with a reconciliation job that diffs scoped counts against raw table counts to catch unintended filtering.
  5. Defer custom flag types. Extending the package means 4 source files and 5+ test locations per flag; a local trait wrapping a boolean column is cheaper and doesn't create fork debt.

Verdict. Adopt for lifecycle state on a bounded, explicitly enumerated set of content models. Do not adopt as the system of record for compliance-critical state without wrapping it, and budget a fork (MIT makes this free) once the model list stabilizes.

Operational Impact

Maintenance. Low steady-state effort, high conceptual care. No runtime service, no queue, no cron, no migrations to run. Upgrade cost tracks Laravel majors and the support matrix suggests the package keeps pace — budget one verification cycle per Laravel major rather than continuous attention. The asymmetry to flag: using the package is nearly free, extending it is not. Resist upstreaming custom flags.

Support. Self-serve. Small community, single-vendor namespace, no commercial backing. Mitigation is cheap and should be pre-approved rather than deferred: vendor the source into our own namespace or a private Composer VCS once the adopted model list is final. Roughly a day of work that converts abandonment risk from a project to a chore.

Scaling. No overhead beyond the WHERE predicate each applied scope introduces. Performance is entirely an indexing question. Design composite indexes around the columns actually filtered and sorted on (is_published, published_at, deleted_at-style) rather than indexing the boolean alone, which on a mature table gives the planner little to work with. No N+1, memory, or connection-pool characteristics are introduced by the package itself.

Failure modes to instrument.

  • Silent row omission — dominant risk. Countermeasure: an assertion suite per scoped model comparing Eloquent counts to raw DB::table() counts, run in CI.
  • Inverted scope direction — classic/inverse mix-up yields exactly-wrong admin views. Countermeasure: review checklist plus a documented model→direction table.
  • Reporting drift — query-builder and BI paths bypass scopes entirely and will disagree with the app. Countermeasure: own this divergence deliberately; state which paths are authoritative.
  • Missing attribution — undo operations leave no record unless we listen to the events.
  • Unexpected writes — HasKeptFlag touching is_kept on create/update.
  • Kill-switch absence — no central disable during an incident; per-model code change required.

Ramp-up. Low for any mid-level Laravel developer — idiomatic traits and global scopes, roughly half a day to read the source of the two or three flags actually in use. The real cost is team-wide comprehension of scope semantics, which is a documentation and code-review problem rather than a training problem. Budget a short internal write-up ("which models are scoped and why") and make every withoutGlobalScope call an explicit, reviewed decision instead of an ad-hoc escape hatch. Realistic onboarding: one sprint for the first model end-to-end, near-zero marginal cost per model thereafter.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib