Download the PHP package atannex/scopable without Composer

On this page you can find all versions of the php package atannex/scopable. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package scopable

atannex/scopable

Tests

Declarative state and date scopes for Laravel Eloquent. Declare a model's states once, then use them on queries and on loaded models.

Every state is a rule that does four things, so Post::published() and $post->inState('published') can never disagree:

  1. constrain a query to rows in the state;
  2. constrain a query to the inverse, NULLs included, so a state and its inverse always split the table in two;
  3. check a loaded model in PHP, with no query;
  4. change the model so it enters or leaves the state.

What you get:

Install

Declare

Shortcuts

Declaration Scopes it adds
published($column = 'published_at') published, scheduled, draft, unpublished (+ notX), date alias published
timestamp($name, $column, pending:, missing:, inverse:, date:) the same, with your names
toggle($name, $column = "is_{$name}", inverse:) $name, not{Name}, inverse
window($name, $from = 'starts_at', $until = 'ends_at', upcoming:, ended:, fromRequired:, untilRequired:) $name (now in [from, until)), optional upcoming and ended
expires($column = 'expires_at', $name = 'expired', inverse: 'unexpired') expired, unexpired, date alias expires (expiresInNext('7 days'))
highlight($name, $flag, $from, $until = null) flag true, start reached (required), end open or ahead
equals($name, $column, $values, otherwise:) column in values; otherwise is written by leaveState()
state($name, Rule $rule) anything
date($alias, $column) every period scope for that column
filter($name, $column) $name(...$values), not{Name}(...$values) (keeps NULLs)
sortable($column, $name = 'ordered', $direction = 'asc', then: []) $name(?$direction)

created, updated and deleted date aliases are added automatically when the model has those columns (see scopable.dates).

States from traits

A trait can bring its own states, like Laravel's boot{Trait}: a static defineScopes{TraitName}(Scopes $scopes) runs before the model's defineScopes(). That is how a package concern (matrix's IsModerated) gives every model using it the same states, while the model adds its own:

Every state can be chained with:

Rules

Rule Passes when Inverse
Rule::toggle('is_active', true) column is true false or NULL
Rule::reached('published_at') set and <= now NULL or > now
Rule::pending('published_at') set and > now NULL or <= now
Rule::missing('col') / Rule::present('col') NULL / NOT NULL the other
Rule::window('starts_at', 'ends_at', fromRequired: false, untilRequired: false) now in [from, until); NULL bounds are open unless required outside
Rule::upcoming('starts_at') / Rule::ended('ends_at') start ahead / end passed
Rule::equals('status', Status::Active), Rule::in('flag', [...]) value matches (enum casts compare by value) anything else or NULL
Rule::compare('budget', '>=', 1000) comparison holds; the value may be fn ($now) => … the opposite or NULL
Rule::under('impressions', 'max_impressions') cap is NULL (unlimited) or used < cap; a NULL counter counts as 0 cap reached
Rule::within('created_at', '7 days') in the last 7 days
Rule::olderThan('updated_at', '1 year') earlier than a year ago
Rule::related('category', 'published') a related row (in that state) exists none does
Rule::state('published') another state of the same model (loops are refused)
Rule::all(...), Rule::any(...), Rule::not(...) composites De Morgan
Rule::callback($query, $passes, $inverse) anything; without $passes, saved models are checked with a query by key

Query

Periods

For every date alias (created, updated, deleted, published, and any you register):

Suffix Example
Today Yesterday Tomorrow createdToday()
ThisWeek LastWeek NextWeek publishedThisWeek()
ThisMonth LastMonth NextMonth updatedLastMonth()
ThisQuarter LastQuarter NextQuarter createdThisQuarter()
ThisYear LastYear NextYear createdLastYear()
InPast InFuture publishedInFuture()
Between($from, $to) createdBetween('2026-01-01', '2026-03-31'); a date-only end covers that whole day
After Since Before Until After/Before are strict; Since/Until include the moment
On($date) createdOn('2026-05-03')
Within($duration) updatedWithin('7 days')
OlderThan($duration) updatedOlderThan('1 year')
InNext($duration) expiresInNext('3 days')
InYear($y) InMonth($m) InMonth($y, $m) createdInMonth(2026, 5)
In($text) createdIn('last 30 days'), createdIn('this week'), createdIn('2026-05')

lastDays(7) / In('last 7 calendar days') is today plus the six days before, for day-based stats. A column cast to date (a rollup's day) is compared with dates, not datetimes. Period::constrain($query, 'created_at', 'today') works on any model, HasScopes or not, and $period->applyOverlap($query, 'starts_at', 'ends_at') keeps rows whose own window overlaps the period.

You can also use ->wherePeriod('created', 'last month'), ->wherePeriod('starts_at', Period::nextWeek()) or $post->inPeriod('published', 'today').

Period works on its own too: Period::thisWeek()->apply($query, 'column'), Period::parse('older than 1 year')->contains($date).

Models

How rules change a model:

Rules that cannot be set directly (under, within, callback…) throw CannotChangeState with the reason.

Default states

Events

->tracked() states fire Atannex\Scopable\Events\StateEntered / StateLeft with $model, $state, $cause (saved or time) and $at. They are dispatched after the transaction commits, so a rollback never announces anything. A row created already in a tracked state fires StateEntered.

The clock moves states without a save (a scheduled post goes live; a campaign ends). List the models in scopable.models and schedule the sweep:

The sweep looks only at rows with a date that crossed "now" since the last run (an indexed range per boundary column), compares each tracked state then and now, and fires the difference. Use --since= to replay a window and --model= to limit the models.

Set scopable.events to false to turn off save events.

Filament

Needs filament/filament.

count: true runs one count per tab; pass numbers from countStates() to count every tab in one query.

Tooling

Config

Key Default
timezone app timezone the timezone calendar periods are cut in; bounds are converted to app.timezone for the query
week_starts_on 1 (Monday)
dates created, updated, deleted automatic date aliases
models [] models for scopable:sweep / scopable:show
events true save events
sweep.store / sweep.lookback / sweep.chunk default store / 10 minutes / 500

Testing

The suite runs every state of the fixtures against a grid of rows (NULLs, past, now, future) at many moments, and asserts that the query matches the PHP check and that the state and its inverse partition the table.


All versions of scopable with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/console Version ^11.0|^12.0
illuminate/database Version ^11.0|^12.0
illuminate/events Version ^11.0|^12.0
illuminate/support Version ^11.0|^12.0
nesbot/carbon Version ^3.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package atannex/scopable contains the following files

Loading the files please wait ...