NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Tickets for Laravel

Artisan commands

CommandDoes
tickets:install {--force}Publish the config and every migration, print the key types and the next steps.
tickets:doctor {--json}Check the installation; exit 1 on any error.
tickets:sweepFlag overdue and due-soon tickets — schedule every five minutes.
tickets:prune-fields {--dry-run} {--chunk=200}Forget orphaned custom field values.

The provider registers the commands but puts nothing on the scheduler:

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('tickets:sweep')->everyFiveMinutes();  // overdue and due-soon flags
Schedule::command('lifecycle:sweep')->everyMinute();     // closes resolved tickets after 7 days

tickets:install

  • Publishes tickets-config, then media-, likes-, reports-, approvals-, comments-, lifecycle-, attributes- and tickets-migrations (sluggable’s slug-history table is not needed).
  • Shows the six key-type settings to align before migrating — tickets.primary_key_type, tickets.key_type, lifecycle.key_type, lifecycle.actor_key_type, comments.key_type, attributes.key_type — with their current values (INVALID for a junk one).
  • Prints the next steps: migrate, the user model as an assignee, the Gate abilities, the two scheduler lines, tickets:doctor — and, while the doctor would report guest_links, the three ways to settle it — plus how to serve and customise the API. The route file is never published by the installer.
  • Idempotent: published files are kept unless --force, and a republished migration lands on the file it landed on before.

tickets:doctor

Read-only checks, by section. Each has a section, a code, a level (ok, warning, error) and a message; the exit code is 1 when any check is an error:

php artisan tickets:doctor          # exit 1 on any error
php artisan tickets:doctor --json   # {ok, checks: [{section, code, level, message}]}
SectionCodesLevelChecks
keysalignmentok / errorEvery key-type setting valid and the pairs equal.
keysuser_modelwarningThe default guard’s user model is keyed differently from tickets.key_type.
lifecyclecontract, not_a_definition, not_status_attribute, state_not_ticket_state, automation_*ok / errorThe configured lifecycle satisfies the ticket contract.
lifecyclelifecycle.<code>error / warning / oklifecycle-for-laravel’s own validation; the shipped close/dismiss ambiguous_target pair is ok, with a note.
lifecycleconveniencesok / warningWhich named conveniences the lifecycle supports; a warning when not all eight.
priorityenum, storedok / error / warningThe enum and default are usable; how many tickets hold a value the enum no longer has.
authorizationabilitiesok / warning / errorThe abilities are defined (Gate::has); undefined is a warning because a Gate::before is invisible to it.
aliasesmaps, requesters, assignables, watchables, projectsok / errorEach alias map valid; assignables implement Assignee, projects TicketProject.
guestsfieldsok / errorThe guest field definitions are valid.
conversationmeta, comments_authorizationok / error / warningThe comments table has the meta column; a warning while comments.authorization is on.
attachmentsdisk, temporary_urlsok / warning / errorThe attachments disk is not the web-served public disk; download URLs can be minted.
apipolicy, routes, guest_linksok / warning / errorThe policy class is valid; routes sit behind an auth* middleware; guest links can be minted — an error while guests are notified.
notificationsenabled, types, urlok / errorNotifications on or off, every type a packaged class, a subclass or false, the URL http(s).
duesoon_window, auto_close, scheduleok / errorThe durations parse; the reminder to schedule both sweeps.
configkeysok / warningA published config still holds routes.enabled, guests.enabled and attachments.mimes.

A fresh install exits 1 until it is configured: guest notifications are on by default and the default guest-link generator needs the guest routes, which ship off. Fix it with TICKETS_ROUTES=on, your own Contracts\GuestLinkGenerator, or TICKETS_NOTIFY_GUESTS=off.

tickets:sweep

Calls Tickets::sweep() and prints the counts. Each ticket is flagged at most once per due date, concurrent sweeps included; it never auto-closes — that is lifecycle:sweep:

php artisan tickets:sweep
# 3 tickets became overdue.
# 1 ticket is due soon.

tickets:prune-fields

Forgets the custom field values no field of their ticket accounts for any more; values of an inactive field are kept. The one step that cannot be undone:

OptionMeaning
--dry-runCount only (5 orphaned field values would be forgotten.).
--chunk=200Tickets per chunk, a whole number from 1 to 999999 (anything else exits with an error).
php artisan tickets:prune-fields --dry-run
php artisan tickets:prune-fields --chunk=500

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.