This document provides a quick reference for the main classes and methods in the Support package.
Namespace: KevinBHarris\Support\Models\Ticket
Properties:
ticket_number(string) - Unique ticket identifiersubject(string) - Ticket subjectdescription(text) - Ticket descriptionstatus_id(int) - Foreign key to Statuspriority_id(int) - Foreign key to Prioritycategory_id(int) - Foreign key to Categorycustomer_name(string) - Customer namecustomer_email(string) - Customer emailassigned_to(int) - User ID of assigneeaccess_token(string) - Token for portal accessfirst_response_at(datetime) - First response timestampresolved_at(datetime) - Resolution timestampclosed_at(datetime) - Closure timestampsla_due_at(datetime) - SLA due date
Relationships:
status()- BelongsTo Statuspriority()- BelongsTo Prioritycategory()- BelongsTo Categorynotes()- HasMany Noteattachments()- MorphMany Attachmentwatchers()- HasMany WatcheractivityLogs()- HasMany ActivityLog
Methods:
isOverdue(): bool- Check if ticket is past SLAcalculateSlaDue(): void- Calculate and set SLA due date
Example:
$ticket = Ticket::create([
'subject' => 'Help needed',
'description' => 'I need assistance',
'customer_name' => 'John Doe',
'customer_email' => 'john@example.com',
'status_id' => 1,
'priority_id' => 2,
'category_id' => 1,
]);
$ticket->calculateSlaDue();
$ticket->save();
if ($ticket->isOverdue()) {
// Handle overdue ticket
}Namespace: KevinBHarris\Support\Models\Status
Properties:
name(string) - Status namecode(string) - Unique status codecolor(string) - Color hex codesort_order(int) - Display orderis_active(bool) - Active flag
Example:
$status = Status::create([
'name' => 'In Progress',
'code' => 'in_progress',
'color' => '#3b82f6',
'sort_order' => 5,
]);Namespace: KevinBHarris\Support\Models\Priority
Properties:
name(string) - Priority namecode(string) - Unique priority codecolor(string) - Color hex codesort_order(int) - Display orderis_active(bool) - Active flag
Namespace: KevinBHarris\Support\Models\Category
Properties:
name(string) - Category nameslug(string) - Unique slugdescription(text) - Category descriptionsort_order(int) - Display orderis_active(bool) - Active flag
Namespace: KevinBHarris\Support\Models\Note
Properties:
ticket_id(int) - Foreign key to Ticketcontent(text) - Note contentis_internal(bool) - Internal note flagcreated_by(int) - User ID of creatorcreated_by_name(string) - Creator name
Relationships:
ticket()- BelongsTo Ticketattachments()- MorphMany Attachment
Example:
$note = Note::create([
'ticket_id' => $ticket->id,
'content' => 'We are working on your issue',
'is_internal' => false,
'created_by' => auth()->id(),
'created_by_name' => auth()->user()->name,
]);Namespace: KevinBHarris\Support\Models\Attachment
Properties:
attachable_type(string) - Polymorphic typeattachable_id(int) - Polymorphic IDname(string) - Original filenamefilename(string) - Stored filenamemime_type(string) - MIME typesize(int) - File size in bytespath(string) - Storage path
Relationships:
attachable()- MorphTo (Ticket or Note)
Namespace: KevinBHarris\Support\Models\Watcher
Properties:
ticket_id(int) - Foreign key to Ticketuser_id(int) - User ID (nullable)email(string) - Watcher emailname(string) - Watcher name
Example:
$watcher = Watcher::create([
'ticket_id' => $ticket->id,
'email' => 'manager@example.com',
'name' => 'Support Manager',
]);Namespace: KevinBHarris\Support\Models\CannedResponse
Properties:
title(string) - Response titleshortcut(string) - Unique shortcut codecontent(text) - Response contentis_active(bool) - Active flag
Example:
$response = CannedResponse::create([
'title' => 'Welcome Message',
'shortcut' => '/welcome',
'content' => 'Thank you for contacting us!',
]);Namespace: KevinBHarris\Support\Models\ActivityLog
Properties:
ticket_id(int) - Foreign key to Ticketaction(string) - Action typedescription(text) - Action descriptionproperties(json) - Additional propertiesuser_id(int) - User IDuser_name(string) - User name
Example:
ActivityLog::create([
'ticket_id' => $ticket->id,
'action' => 'status_changed',
'description' => 'Status changed from New to Open',
'properties' => ['old' => 'New', 'new' => 'Open'],
'user_id' => auth()->id(),
'user_name' => auth()->user()->name,
]);Namespace: KevinBHarris\Support\Models\Rule
Properties:
name(string) - Rule namedescription(text) - Rule descriptionconditions(json) - Rule conditionsactions(json) - Rule actionssort_order(int) - Execution orderis_active(bool) - Active flag
Namespace: KevinBHarris\Support\Events\TicketCreated
Properties:
ticket(Ticket) - The created ticket
Example:
event(new TicketCreated($ticket));Namespace: KevinBHarris\Support\Events\TicketUpdated
Properties:
ticket(Ticket) - The updated ticketchanges(array) - Array of changes
Example:
event(new TicketUpdated($ticket, ['status' => 'Open']));Namespace: KevinBHarris\Support\Events\NoteAdded
Properties:
note(Note) - The added note
Example:
event(new NoteAdded($note));Namespace: KevinBHarris\Support\Services\SlackService
Methods:
notifyTicketCreated(Ticket $ticket): void- Send Slack notification for new ticketnotifyTicketUpdated(Ticket $ticket, array $changes): void- Send Slack notification for ticket update
Example:
$slackService = app(SlackService::class);
$slackService->notifyTicketCreated($ticket);Access configuration using Laravel's config() helper:
// Email settings
config('support.email.from_address');
config('support.email.from_name');
// SLA settings
config('support.sla.low'); // 72 hours
config('support.sla.medium'); // 48 hours
config('support.sla.high'); // 24 hours
config('support.sla.urgent'); // 4 hours
// Slack settings
config('support.slack.enabled');
config('support.slack.webhook_url');
config('support.slack.channel');
// Attachment settings
config('support.attachments.max_size');
config('support.attachments.allowed_extensions');
config('support.attachments.storage_path');All admin routes are protected by ['web', 'admin'] middleware:
GET /admin/support/tickets- List ticketsGET /admin/support/tickets/create- Create ticket formPOST /admin/support/tickets- Store ticketGET /admin/support/tickets/{id}- View ticketGET /admin/support/tickets/{id}/edit- Edit ticket formPUT /admin/support/tickets/{id}- Update ticketDELETE /admin/support/tickets/{id}- Delete ticketPOST /admin/support/tickets/{id}/notes- Add notePOST /admin/support/tickets/bulk- Bulk actions
Similar CRUD routes exist for:
/admin/support/statuses/admin/support/priorities/admin/support/categories/admin/support/canned-responses/admin/support/rules
Public routes protected by ['web'] middleware:
GET /support/contact- Contact formPOST /support/contact- Submit ticketGET /support/ticket/{token}- View ticketPOST /support/ticket/{token}/reply- Reply to ticket
Add custom scopes to models:
// In Ticket model
public function scopeOverdue($query)
{
return $query->whereNotNull('sla_due_at')
->where('sla_due_at', '<', now());
}
// Usage
$overdueTickets = Ticket::overdue()->get();// In Ticket model
public function getIsOverdueAttribute(): bool
{
return $this->isOverdue();
}
// Usage
if ($ticket->is_overdue) {
// Handle overdue
}Customize mail templates by publishing views and editing:
resources/views/vendor/support/emails/ticket-created.blade.phpresources/views/vendor/support/emails/ticket-updated.blade.phpresources/views/vendor/support/emails/note-added.blade.php
All views extend admin::layouts.master for admin views and use standalone HTML for portal views.
You can override views by publishing them and editing in:
resources/views/vendor/support/