Overview
NutriFit uses Laravel’s notification system to send automated email notifications for authentication events, appointments, clinical records, and account management.
All notifications implement ShouldQueue interface for asynchronous processing, ensuring fast response times.
Architecture
The notification system is built on Laravel’s notification framework with queue support:
use Illuminate\Bus\ Queueable ;
use Illuminate\Contracts\Queue\ ShouldQueue ;
use Illuminate\Notifications\Messages\ MailMessage ;
use Illuminate\Notifications\ Notification ;
class ExampleNotification extends Notification implements ShouldQueue
{
use Queueable ;
public function via ( object $notifiable ) : array
{
return [ 'mail' ];
}
public function toMail ( object $notifiable ) : MailMessage
{
return ( new MailMessage )
-> subject ( 'Subject Line' )
-> greeting ( 'Hello!' )
-> line ( 'Notification content...' )
-> action ( 'Action Button' , url ( '/' ));
}
}
Notification Types
Authentication Notifications
WelcomeNotification Sent after email verification to welcome new users
VerifyEmailNotification Email verification link for new accounts
ResetPasswordNotification Password reset link when requested
PasswordChangedNotification Confirmation after password change
Welcome Email Example
app/Notifications/WelcomeNotification.php
class WelcomeNotification extends Notification implements ShouldQueue
{
use Queueable ;
public function toMail ( object $notifiable ) : MailMessage
{
return ( new MailMessage )
-> subject ( '🎉 ¡Bienvenido a NutriFit!' )
-> greeting ( '¡Hola ' . $notifiable -> name . '!' )
-> line ( '¡Gracias por registrarte en NutriFit! Nos alegra que formes parte de nuestra comunidad.' )
-> line ( 'Tu cuenta ha sido creada exitosamente y ya puedes empezar a usar todas nuestras funcionalidades:' )
-> line ( '✅ Agendar citas con nutricionistas profesionales' )
-> line ( '✅ Mantener tu historial clínico organizado' )
-> line ( '✅ Recibir seguimiento continuo de tu progreso' )
-> action ( 'Explorar NutriFit' , url ( '/paciente/dashboard' ))
-> salutation ( '¡Bienvenido al equipo! ' . config ( 'app.name' ));
}
}
Account Management Notifications
UserAccountEnabledNotification
Sent when administrator enables a disabled account
UserAccountDisabledNotification
Sent when administrator disables an account
PersonalDataCreatedNotification
Sent when nutritionist creates patient’s personal data
Appointment Notifications
The system sends comprehensive appointment-related notifications:
Creation
Confirmation
Reminders
Rescheduling
Cancellation
AppointmentCreatedNotification (to Nutritionist)app/Notifications/AppointmentCreatedNotification.php
public function toMail ( object $notifiable ) : MailMessage
{
$appointmentDate = $this -> appointment -> start_time -> format ( 'd/m/Y' );
$appointmentTime = $this -> appointment -> start_time -> format ( 'H:i' );
$patientName = $this -> appointment -> paciente -> name ;
return ( new MailMessage )
-> subject ( '🗓️ Nueva Cita Agendada - NutriFit' )
-> greeting ( '¡Hola Dr(a). ' . $notifiable -> name . '!' )
-> line ( 'Se ha agendado una nueva cita en tu calendario.' )
-> line ( '**Paciente:** ' . $patientName )
-> line ( '**Fecha:** ' . $appointmentDate )
-> line ( '**Hora:** ' . $appointmentTime )
-> action ( 'Ver Detalles' , url ( '/nutricionista/dashboard' ));
}
AppointmentCreatedForPatientNotification (to Patient)Confirms booking to the patient AppointmentConfirmedForPatient Sent when nutritionist confirms the appointment
AppointmentReminderNotification app/Notifications/AppointmentReminderNotification.php
public function toMail ( object $notifiable ) : MailMessage
{
$appointmentDate = $this -> appointment -> start_time -> format ( 'd/m/Y' );
$appointmentTime = $this -> appointment -> start_time -> format ( 'H:i' );
// Determinar si es para paciente o nutricionista
$isPaciente = $notifiable -> role -> name === 'paciente' ;
$otherPerson = $isPaciente
? 'Dr(a). ' . $this -> appointment -> nutricionista -> name
: $this -> appointment -> paciente -> name ;
return ( new MailMessage )
-> subject ( '⏰ Recordatorio: Cita Mañana - NutriFit' )
-> greeting ( '¡Hola ' . $notifiable -> name . '!' )
-> line ( 'Te recordamos que tienes una cita mañana.' )
-> line ( '**' . ( $isPaciente ? 'Nutricionista' : 'Paciente' ) . ':** ' . $otherPerson )
-> line ( '**Fecha:** ' . $appointmentDate )
-> line ( '**Hora:** ' . $appointmentTime )
-> action ( 'Ver Detalles' ,
url ( $isPaciente ? '/paciente/citas' : '/nutricionista/dashboard' ))
-> line ( 'Por favor, llega puntual a tu cita.' );
}
Sent 24 hours before appointment to both patient and nutritionist AppointmentRescheduledNotification Sent when appointment time is changed
AppointmentCancelledByPatient (to Nutritionist)Notifies nutritionist of patient cancellation AppointmentCancelledByNutricionista (to Patient)Notifies patient of nutritionist cancellation
Clinical Record Notifications
AttentionCompletedNotification
Sent to patient when nutritionist completes clinical attention:
app/Notifications/AttentionCompletedNotification.php
class AttentionCompletedNotification extends Notification implements ShouldQueue
{
use Queueable ;
public function __construct (
public Attention $attention
) {}
public function toMail ( object $notifiable ) : MailMessage
{
$appointmentDate = $this -> attention -> appointment -> start_time -> format ( 'd/m/Y' );
$appointmentTime = $this -> attention -> appointment -> start_time -> format ( 'H:i' );
$nutricionistaName = $this -> attention -> nutricionista -> name ;
$weight = $this -> attention -> attentionData -> weight ?? 'N/A' ;
$bmi = $this -> attention -> attentionData -> bmi ?? 'N/A' ;
return ( new MailMessage )
-> subject ( '✅ Atención Nutricional Completada - NutriFit' )
-> greeting ( '¡Hola ' . $notifiable -> name . '!' )
-> line ( 'Tu atención nutricional ha sido completada exitosamente.' )
-> line ( '**Nutricionista:** Dr(a). ' . $nutricionistaName )
-> line ( '**Fecha de atención:** ' . $appointmentDate . ' a las ' . $appointmentTime )
-> line ( '**Peso registrado:** ' . $weight . ' kg' )
-> line ( '**IMC:** ' . number_format ( $bmi , 2 ))
-> line ( 'Se ha generado un plan nutricional personalizado con diagnóstico y recomendaciones específicas para ti.' )
-> action ( 'Ver Reporte Completo' ,
url ( '/paciente/citas/' . $this -> attention -> appointment_id ))
-> line ( 'Recuerda seguir las recomendaciones de tu nutricionista para alcanzar tus objetivos de salud.' );
}
}
ContactFormNotification
Sent to administrators when users submit the contact form.
Sending Notifications
Direct Sending
Notifications are sent using Laravel’s notification facade:
use App\Notifications\ AppointmentCreatedNotification ;
// Send to single user
$user -> notify ( new AppointmentCreatedNotification ( $appointment ));
// Send to multiple users
Notification :: send ( $users , new WelcomeNotification ());
Queued Processing
All notifications implement ShouldQueue for background processing:
class AppointmentReminderNotification extends Notification implements ShouldQueue
{
use Queueable ;
// Notification will be processed in background
}
Queued notifications prevent blocking the request-response cycle, providing better user experience.
Queue Workers
Configuration
Configure queue connection in .env:
QUEUE_CONNECTION = database
# or
QUEUE_CONNECTION = redis
# or
QUEUE_CONNECTION = sync # For development
Running Queue Workers
Development
Production
Testing
Processes queued jobs. Use Ctrl+C to stop. php artisan queue:work --daemon
Or use Supervisor for automatic restart: /etc/supervisor/conf.d/nutrifit-worker.conf
[program:nutrifit-worker]
process_name =%(program_name)s_%(process_num)02d
command =php /path/to/nutrifit/artisan queue:work -- sleep =3 -- tries =3
autostart =true
autorestart =true
user =www-data
numprocs =2
redirect_stderr =true
stdout_logfile =/path/to/nutrifit/storage/logs/worker.log
# Process only one job then exit
php artisan queue:work --once
# Increase verbosity
php artisan queue:work -vvv
Queue Monitoring
# List failed jobs
php artisan queue:failed
# Retry failed job
php artisan queue:retry < job-i d >
# Retry all failed jobs
php artisan queue:retry all
# Flush failed jobs
php artisan queue:flush
Scheduled Notifications
Appointment Reminders
Reminders are sent via scheduled command:
app/Console/Commands/SendAppointmentReminders.php
class SendAppointmentReminders extends Command
{
protected $signature = 'appointments:send-reminders' ;
public function handle ()
{
$tomorrow = Carbon :: tomorrow () -> toDateString ();
$appointments = Appointment :: whereDate ( 'start_time' , $tomorrow )
-> whereHas ( 'appointmentState' , function ( $query ) {
$query -> whereIn ( 'name' , [ 'confirmada' , 'pendiente' ]);
})
-> with ([ 'paciente' , 'nutricionista' ])
-> get ();
foreach ( $appointments as $appointment ) {
$appointment -> paciente -> notify (
new AppointmentReminderNotification ( $appointment )
);
$appointment -> nutricionista -> notify (
new AppointmentReminderNotification ( $appointment )
);
}
}
}
Schedule Configuration
Add to app/Console/Kernel.php:
protected function schedule ( Schedule $schedule )
{
// Send appointment reminders daily at 9 AM
$schedule -> command ( 'appointments:send-reminders' )
-> dailyAt ( '09:00' );
}
Running Scheduler
Add to crontab:
* * * * * cd /path-to-nutrifit && php artisan schedule:run >> /dev/null 2>&1
Email Configuration
SMTP Setup
Configure email in .env:
MAIL_MAILER = smtp
MAIL_HOST = smtp.mailtrap.io
MAIL_PORT = 2525
MAIL_USERNAME = your-username
MAIL_PASSWORD = your-password
MAIL_ENCRYPTION = tls
MAIL_FROM_ADDRESS = [email protected]
MAIL_FROM_NAME = "${ APP_NAME }"
Testing Emails
Use Mailtrap or similar for development:
# Send test notification
php artisan tinker
>>> $user = User::first ();
>>> $user - > notify ( new \A pp \N otifications \W elcomeNotification ());
Notification Customization
Custom Styling
Publish notification templates:
php artisan vendor:publish --tag=laravel-notifications
Customize in resources/views/vendor/notifications/.
Multi-Channel Notifications
Add additional channels:
public function via ( object $notifiable ) : array
{
return [ 'mail' , 'database' , 'broadcast' ];
}
public function toDatabase ( object $notifiable ) : array
{
return [
'appointment_id' => $this -> appointment -> id ,
'message' => 'New appointment scheduled' ,
];
}
Best Practices
Implement ShouldQueue on all notifications to prevent blocking requests
Provide direct links to relevant pages in notification emails
Use recipient’s name and include specific details
Use descriptive subjects with emojis for visual recognition
Regularly check and retry failed notification jobs
Test all notification types in development environment
Troubleshooting
If notifications aren’t being sent, check these common issues:
Queue Not Processing
# Check if queue worker is running
ps aux | grep "queue:work"
# Start queue worker
php artisan queue:work
Failed Jobs
# View failed jobs
php artisan queue:failed
# Check error details
php artisan queue:failed-table
php artisan migrate
Email Not Sending
# Test email configuration
php artisan config:clear
php artisan cache:clear
# Check logs
tail -f storage/logs/laravel.log
Appointments Learn about appointment scheduling
Authentication Explore authentication system
Clinical Records Understand clinical attention workflow