Overview
The Appointment model manages scheduled visits between patients and doctors. It tracks appointment timing, status, reason for visit, and related notes.
Model Location: app/Models/Appointment.php
Features:
- Soft deletes enabled
- DateTime casting for start and end times
- Relationships with patients and doctors
- Status tracking (scheduled, confirmed, completed, cancelled, no_show)
Database Schema
Primary key, auto-incrementing
Foreign key to patients table. Cascades on delete.
Foreign key to users table. Cascades on delete.
Appointment start date and time
Appointment end date and time
Appointment status. Default: scheduledPossible values:
scheduled - Initial state when appointment is created
confirmed - Patient confirmed the appointment
completed - Appointment finished successfully
cancelled - Appointment was cancelled
no_show - Patient did not show up
Reason for the appointment visit
Additional notes about the appointment
Record creation timestamp
Record last update timestamp
Soft delete timestamp (null if not deleted)
Fillable Attributes
The following attributes can be mass-assigned:
ID of the patient for this appointment
ID of the doctor (User) for this appointment
Appointment start time (format: Y-m-d H:i:s)
Appointment end time (format: Y-m-d H:i:s)
Status: scheduled, confirmed, completed, cancelled, or no_show
Relationships
Patient
Get the patient associated with this appointment.
$appointment = Appointment::find(1);
$patient = $appointment->patient;
// Access patient information
echo $patient->full_name;
echo $patient->phone;
Relationship Type: belongsTo
Related Model: App\Models\Patient
Foreign Key: patient_id
Doctor
Get the doctor (User) associated with this appointment.
$appointment = Appointment::find(1);
$doctor = $appointment->doctor;
// Access doctor information
echo $doctor->name;
echo $doctor->email;
Relationship Type: belongsTo
Related Model: App\Models\User
Foreign Key: doctor_id
Owner Key: id (on users table)
Type Casting
The model automatically casts the following attributes:
start_time: Cast to Carbon datetime instance
end_time: Cast to Carbon datetime instance
Soft Deletes
The Appointment model uses soft deletes. Deleted records are not permanently removed from the database but marked with a deleted_at timestamp.
// Soft delete an appointment
$appointment->delete();
// Include soft deleted records
$allAppointments = Appointment::withTrashed()->get();
// Get only soft deleted records
$deletedAppointments = Appointment::onlyTrashed()->get();
// Restore a soft deleted appointment
$appointment->restore();
// Permanently delete
$appointment->forceDelete();
Usage Examples
Creating an Appointment
use App\Models\Appointment;
use Carbon\Carbon;
$appointment = Appointment::create([
'patient_id' => 1,
'doctor_id' => 5,
'start_time' => Carbon::parse('2026-03-10 09:00:00'),
'end_time' => Carbon::parse('2026-03-10 09:30:00'),
'status' => 'scheduled',
'reason' => 'Consulta general',
'notes' => 'Primera visita del paciente',
]);
Updating Appointment Status
$appointment = Appointment::find(1);
// Confirm appointment
$appointment->update(['status' => 'confirmed']);
// Mark as completed
$appointment->update(['status' => 'completed']);
// Cancel appointment
$appointment->update([
'status' => 'cancelled',
'notes' => 'Paciente solicitó cancelación',
]);
Querying Appointments
// Get today's appointments
$todayAppointments = Appointment::whereDate('start_time', today())
->with(['patient', 'doctor'])
->orderBy('start_time')
->get();
// Get upcoming appointments for a doctor
$doctorAppointments = Appointment::where('doctor_id', 5)
->where('start_time', '>=', now())
->where('status', '!=', 'cancelled')
->get();
// Get patient's appointment history
$patientHistory = Appointment::where('patient_id', 1)
->with('doctor')
->orderBy('start_time', 'desc')
->get();
Working with DateTime Casts
$appointment = Appointment::find(1);
// Access as Carbon instances
$duration = $appointment->end_time->diffInMinutes($appointment->start_time);
echo "Duration: {$duration} minutes";
// Format dates
echo $appointment->start_time->format('d/m/Y H:i');
echo $appointment->start_time->diffForHumans(); // "2 hours from now"
// Check if appointment is in the past
if ($appointment->start_time->isPast()) {
echo "This appointment has already occurred";
}
Finding Available Time Slots
// Check if a time slot is available for a doctor
$hasConflict = Appointment::where('doctor_id', 5)
->where('status', '!=', 'cancelled')
->where(function ($query) use ($startTime, $endTime) {
$query->whereBetween('start_time', [$startTime, $endTime])
->orWhereBetween('end_time', [$startTime, $endTime]);
})
->exists();
Filtering by Status
// Get all confirmed appointments
$confirmed = Appointment::where('status', 'confirmed')->get();
// Get appointments that need follow-up (no-show)
$noShows = Appointment::where('status', 'no_show')
->with('patient')
->get();
// Get completed appointments for billing
$completedToday = Appointment::where('status', 'completed')
->whereDate('start_time', today())
->get();
Eager Loading Relationships
// Efficiently load appointments with related data
$appointments = Appointment::with([
'patient' => function ($query) {
$query->select('id', 'full_name', 'phone', 'email');
},
'doctor' => function ($query) {
$query->select('id', 'name', 'email');
}
])
->whereBetween('start_time', [now()->startOfWeek(), now()->endOfWeek()])
->get();