juanrube/ticketit
Ticketit is a simple helpdesk ticket system for Laravel 10–12 that integrates with Laravel auth. Supports users/agents/admins, ticket creation and comments, auto agent assignment by department/queue, admin dashboard with stats, localization, and image uploads.
Install via Composer
composer require juanrube/ticketit
Run migrations and publish assets:
php artisan vendor:publish --provider="JuanRube\Ticketit\TicketitServiceProvider"
php artisan migrate
Configure Routes
Add Ticketit routes in routes/web.php:
Route::prefix('tickets')->group(function () {
require __DIR__.'/ticketit.php';
});
Set Up Middleware
Ensure auth middleware is applied to Ticketit routes (default in published config).
First Ticket Creation
/tickets/create./tickets/admin – Overview of tickets, agents, and stats./tickets – View, comment, and manage personal tickets./tickets/agent – Assign, resolve, and reply to tickets.config/ticketit.php – Adjust roles, permissions, and auto-assignment rules.// Check if current user is a user (not agent/admin)
if (auth()->user()->hasRole('user')) {
$tickets = \JuanRube\Ticketit\Models\Ticket::where('user_id', auth()->id())->get();
}
// Assign ticket to self
$ticket->assignTo(auth()->id());
// Force-reassign a ticket
$ticket->forceAssignTo($agentId);
config/ticketit.php:
'auto_assign' => [
'enabled' => true,
'department_field' => 'department_id',
'agent_selection' => 'least_busy', // or 'random'
],
// Override agent selection
Ticketit::extend(function ($ticket) {
return \JuanRube\Ticketit\Models\Agent::where('department_id', $ticket->department_id)
->orderBy('last_assigned_at', 'asc')
->first();
});
open, pending, resolved, closed.$ticket->resolve(); // Marks as resolved
$ticket->close(); // Finalizes ticket
\JuanRube\Ticketit\Models\Ticket::resolved(function ($ticket) {
// Send notification
});
// In AppServiceProvider
\JuanRube\Ticketit\Facades\Ticketit::setLocale('es');
php artisan vendor:publish --tag=ticketit-lang
Edit resources/lang/vendor/ticketit/.// Override notification template
\JuanRube\Ticketit\Mail\TicketCreated::createUrlUsing(function ($ticket) {
return route('tickets.show', $ticket->id);
});
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('tickets', \JuanRube\Ticketit\Http\Controllers\Api\TicketController::class);
});
ticket_metadata table:
$ticket->metadata()->create([
'key' => 'priority',
'value' => 'high',
]);
// In TicketitServiceProvider
Ticketit::macro('getUserDepartment', function ($user) {
return $user->company->support_department_id;
});
Role Conflicts
can() checks align with hasRole():
// ❌ Avoid hardcoding roles
if (auth()->user()->role === 'admin') { ... }
// ✅ Use Ticketit’s permission system
if (auth()->user()->can('manage_tickets')) { ... }
php artisan ticketit:permissions if roles are misconfigured.Auto-Assignment Failures
config/ticketit.php → 'auto_assign' => ['enabled' => true].SELECT * FROM agents WHERE department_id = ? AND active = 1;
agent_selection logic.Email Configuration
.env:
MAIL_MAILER=smtp
MAIL_FROM_ADDRESS="support@yourdomain.com"
php artisan ticketit:test-email.Asset Publishing
php artisan vendor:publish --tag=ticketit-assets
php artisan view:clear
Log Auto-Assignment
config/ticketit.php:
'debug' => [
'log_auto_assign' => true,
],
storage/logs/laravel.log.Ticket State Transitions
dd($ticket->fresh()) to inspect state after actions like resolve().pending state due to validation errors in comments.Middleware Conflicts
auth middleware is applied.users table role column).Custom Ticket Actions
// In AppServiceProvider
View::composer('ticketit::ticket.show', function ($view) {
$view->with('customActions', [
'escalate' => route('tickets.escalate', $ticket->id),
]);
});
Override Views
php artisan vendor:publish --tag=ticketit-views
resources/views/vendor/ticketit/.Hooks for Business Logic
// In EventServiceProvider
public function boot() {
\JuanRube\Ticketit\Models\Ticket::created(function ($ticket) {
// Trigger Slack notification
});
}
TicketCreatedTicketAssignedTicketResolvedTicketClosedCustom Departments
departments table or use a many-to-many relationship:
// Add to User model
public function departments() {
return $this->belongsToMany(Department::class, 'user_departments');
}
Default Role Assignment
'user' role. Override in AppServiceProvider:
use JuanRube\Ticketit\Models\User;
User::created(function ($user) {
$user->role = 'agent'; // Force role
$user->save();
});
File Uploads
public/uploads/ticketit is writable:How can I help you explore Laravel packages today?