›
›
›
  1. docs
  2. ›
  3. byrcsc/laravel-assignment
1.x
Browse documentationOpenClose

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Assignments and slots
  • Assigning and offering
  • Selection policies
  • Scopes and rotation
  • Profiles
  • The queue
  • Offer cascades

Operations

  • Expiry and scheduling
  • Reading assignments
  • Notifications
  • Events and listeners
  • Concurrency guarantees

Reference

  • Configuration
  • API reference
  • Console commands
  • Exceptions
  • Testing
  • Troubleshooting

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Assignments and slots
  • Assigning and offering
  • Selection policies
  • Scopes and rotation
  • Profiles
  • The queue
  • Offer cascades

Operations

  • Expiry and scheduling
  • Reading assignments
  • Notifications
  • Events and listeners
  • Concurrency guarantees

Reference

  • Configuration
  • API reference
  • Console commands
  • Exceptions
  • Testing
  • Troubleshooting

byrcsc/laravel-assignment · 1.x

Introduction.

Laravel Assignment routes work to people and teams, and records who held what.

An enquiry needs a tradie. A callout needs a crew. A lead needs a sales agent. A ticket needs whoever is on shift. Two requests arrive at once and both pick the same person, so one of them silently overwrites the other. Nobody can answer who held the record last week, because the only column that ever held that answer was overwritten too.

Laravel Assignment gives you the slot and the history. Any Eloquent model can be assigned, any Eloquent model can take assignments, and at most one open assignment per slot is enforced by a database constraint rather than by an application check.

$enquiry->assign($tradie);          // active immediately
$enquiry->assignee();               // the Tradie, or null
$enquiry->reassign($otherTradie);   // ends the old row, opens the new one
$enquiry->assignments;              // every row, oldest first

Your application keeps ownership of its users, its teams, its eligibility rules, and whatever being assigned actually means.

RequirementSupported versions
PHP8.3, 8.4
Laravel12.x, 13.x
DatabasesMySQL, PostgreSQL, SQLite

The package follows semantic versioning: upgrading within 1.x is safe. Source and issues live on GitHub.

The three nouns

An assignable is anything that gets assigned: an enquiry, an order, a ticket, a callout. Add the Assignable trait to that model.

An assignee is anything that takes an assignment: a user, a crew, a team. Add the Assignee trait to that model.

A role is an optional label that lets one assignable hold more than one assignee at a time. A callout can hold a crew and a tradie at once, because each role is its own slot. Leave the role off and an assignable has one slot.

What is included

  • Two verbs: assign() writes an active assignment, offer() writes one the assignee has to accept or decline.
  • One open assignment per assignable and role, enforced by a unique index, so two concurrent callers cannot both fill the same slot.
  • Four selection policies (RoundRobin, LeastWorkload, Random, FirstAvailable) and any closure, behind one SelectionPolicy contract.
  • Per-scope rotation state, row locked during selection, so round robin cursors do not skip or repeat a turn under concurrency.
  • Profiles: one class per assignable model, holding the candidates, the policy, the scope, and the mode, so assignment can run with no arguments.
  • A priority queue for assignables that nobody can take yet, flushed by priority and then first in, first out.
  • Offer cascades that pass a declined or expired offer to the next candidate and stop when the candidates run out.
  • Expiry decided by the timestamp, so an overdue offer stops holding its slot whether or not a scheduled command has run.
  • Events for every transition, and four assignee notifications that are swappable or removable in config.

What it does not do

The package draws its edges deliberately. What follows describes what it sets out to do, not a list of planned work.

  • Deciding who is eligible. The engine never asks whether a candidate belongs in the pool. You pass the candidates, and passing an ineligible model produces an assignment rather than an error. Territory, skill, shift, and capacity are queries on data your application already owns. See selection policies.
  • Screens. No Blade views beyond the notification mail, no Livewire, no Nova resources.
  • Database-defined pools or rules. Candidate lists and admin-editable routing rules belong to your application.
  • Authorization. assign() and offer() are ordinary method calls with no policy behind them.
  • Approval of assignments. Pair the package with byrcsc/laravel-approval and drive it from the events.
  • SLA or escalation timers beyond the offer TTL.
  • Notifying anyone but the assignee. Managers, watchers, and dashboards listen to events.

Design boundaries

Four decisions shape most of the rest.

The open-slot rule is a database constraint. An internal slot column holds the role while a row is open and null once it ends, under a unique index on the assignable and that column. The loser of a race gets an exception, never a duplicate. Moving the check into PHP would break the package's central promise.

Assignments end, they are not deleted. An ended row records ended_at and an ended_reason of unassigned, reassigned, declined, expired, or completed. The rows are the history, and there is no separate audit table.

Timestamps decide expiry. An offer whose expires_at has passed stops holding its slot immediately. assignment:tick advances cascades and flushes the queue; it is never required for a read to be correct.

Eligibility and selection are separate jobs. Your application answers who can take the work. The engine answers who gets it, among the candidates you passed, fairly and atomically.

What to read next

  • Installation and setup to create the tables and add the traits.
  • Quick start to assign an enquiry to a tradie end to end.
  • Assignments and slots for what a slot is and when it is occupied.
NextInstallation and setup
View source

On this page

  1. The three nouns
  2. What is included
  3. What it does not do
  4. Design boundaries
  5. What to read next