الإشعارات والبريد الإلكتروني في Laravel
يوفر Laravel نظامًا قويًا ومرنًا لإرسال الإشعارات عبر قنوات متعددة بما في ذلك البريد الإلكتروني والرسائل النصية وSlack وتخزين قاعدة البيانات. يسهل نظام الإشعارات إخطار المستخدمين حول الأحداث في تطبيقك.
إعداد البريد الإلكتروني
قبل إرسال البريد، قم بتكوين برنامج تشغيل البريد في ملف .env:
# استخدام SMTP
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="${APP_NAME}"
# استخدام Mailgun
MAIL_MAILER=mailgun
MAILGUN_DOMAIN=your-domain.com
MAILGUN_SECRET=your-mailgun-key
# استخدام SendGrid
MAIL_MAILER=sendgrid
SENDGRID_API_KEY=your-sendgrid-key
ملاحظة: بالنسبة لـ Gmail، تحتاج إلى استخدام كلمات مرور التطبيقات (وليس كلمة مرور Gmail العادية) إذا تم تمكين المصادقة الثنائية. قم بإنشاء واحدة في إعدادات أمان حساب Google الخاص بك.
إنشاء فئات البريد (Mailables)
تمثل Mailables رسائل البريد الإلكتروني كفئات PHP. قم بإنشاء mailable باستخدام Artisan:
php artisan make:mail WelcomeEmail
php artisan make:mail OrderConfirmation --markdown=emails.orders.confirmation
مثال على فئة mailable:
<?php
namespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class WelcomeEmail extends Mailable
{
use Queueable, SerializesModels;
public $user;
public $verificationUrl;
public function __construct(User $user, string $verificationUrl)
{
$this->user = $user;
$this->verificationUrl = $verificationUrl;
}
public function build()
{
return $this->subject('مرحبًا بك في ' . config('app.name'))
->view('emails.welcome')
->with([
'userName' => $this->user->name,
'url' => $this->verificationUrl,
]);
}
}
إرسال البريد الإلكتروني
أرسل البريد باستخدام واجهة Mail:
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
// إرسال فوري
Mail::to($user->email)->send(new WelcomeEmail($user, $verificationUrl));
// إرسال إلى مستلمين متعددين
Mail::to($user)
->cc('manager@example.com')
->bcc('admin@example.com')
->send(new OrderConfirmation($order));
// وضع البريد في قائمة الانتظار للمعالجة في الخلفية
Mail::to($user->email)->queue(new WelcomeEmail($user, $url));
// وضع في قائمة الانتظار مع تأخير
Mail::to($user->email)
->later(now()->addMinutes(10), new WelcomeEmail($user, $url));
بريد Markdown
يدعم Laravel قوالب بريد إلكتروني جميلة ومتجاوبة باستخدام Markdown:
// إنشاء mailable بـ markdown
php artisan make:mail InvoicePaid --markdown=emails.invoice.paid
Mailable مع markdown:
<?php
class InvoicePaid extends Mailable
{
public $invoice;
public function build()
{
return $this->markdown('emails.invoice.paid')
->subject('تم دفع الفاتورة - #' . $this->invoice->id);
}
}
قالب Markdown (resources/views/emails/invoice/paid.blade.php):
@component('mail::message')
# تم دفع الفاتورة
شكرًا لك على الدفع!
**الفاتورة:** #{{ $invoice->id }}
**المبلغ:** ${{ number_format($invoice->amount, 2) }}
@component('mail::button', ['url' => route('invoices.show', $invoice)])
عرض الفاتورة
@endcomponent
@component('mail::panel')
تم وضع علامة على هذه الفاتورة كمدفوعة في {{ $invoice->paid_at->format('M d, Y') }}.
@endcomponent
@component('mail::table')
| المنتج | الكمية | السعر |
|:-----|:--------:|------:|
@foreach($invoice->items as $item)
| {{ $item->name }} | {{ $item->quantity }} | ${{ number_format($item->price, 2) }} |
@endforeach
@endcomponent
مع الشكر،<br>
{{ config('app.name') }}
@endcomponent
نصيحة: خصص تصميم بريد markdown عن طريق نشر أصول البريد: php artisan vendor:publish --tag=laravel-mail
نظام الإشعارات
الإشعارات أكثر تنوعًا من البريد، وتدعم قنوات متعددة. قم بإنشاء إشعار:
php artisan make:notification NewOrderNotification
php artisan make:notification PaymentReceived --markdown=notifications.payment-received
مثال على فئة إشعار:
<?php
namespace App\Notifications;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\BroadcastMessage;
class NewOrderNotification extends Notification
{
use Queueable;
public $order;
public function __construct(Order $order)
{
$this->order = $order;
}
// تحديد القنوات المستخدمة
public function via($notifiable)
{
return ['mail', 'database', 'broadcast'];
}
// إشعار البريد الإلكتروني
public function toMail($notifiable)
{
return (new MailMessage)
->subject('طلب جديد #' . $this->order->id)
->line('لقد تلقيت طلبًا جديدًا.')
->line('إجمالي الطلب: $' . number_format($this->order->total, 2))
->action('عرض الطلب', route('orders.show', $this->order))
->line('شكرًا لاستخدامك تطبيقنا!');
}
// إشعار قاعدة البيانات
public function toDatabase($notifiable)
{
return [
'order_id' => $this->order->id,
'order_total' => $this->order->total,
'customer_name' => $this->order->customer->name,
'message' => 'طلب جديد #' . $this->order->id,
];
}
// إشعار البث (للوقت الفعلي)
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'order_id' => $this->order->id,
'message' => 'تم استلام طلب جديد',
]);
}
// إشعار المصفوفة
public function toArray($notifiable)
{
return [
'order_id' => $this->order->id,
'order_total' => $this->order->total,
];
}
}
إرسال الإشعارات
أرسل الإشعارات باستخدام trait Notifiable:
use App\Notifications\NewOrderNotification;
// إرسال إلى مستخدم واحد (نموذج المستخدم يجب أن يستخدم trait Notifiable)
$user->notify(new NewOrderNotification($order));
// إرسال إلى مستخدمين متعددين
$admins = User::where('role', 'admin')->get();
Notification::send($admins, new NewOrderNotification($order));
// إشعار مجهول (إرسال بدون نموذج مستخدم)
Notification::route('mail', 'guest@example.com')
->route('slack', config('services.slack.webhook'))
->notify(new NewOrderNotification($order));
إشعارات قاعدة البيانات
قم بتخزين الإشعارات في قاعدة البيانات لمراكز الإشعارات داخل التطبيق:
// إنشاء جدول الإشعارات
php artisan notifications:table
php artisan migrate
استرجاع الإشعارات ووضع علامة مقروءة عليها:
// الحصول على جميع الإشعارات
$notifications = $user->notifications;
// الحصول على الإشعارات غير المقروءة
$unread = $user->unreadNotifications;
// وضع علامة مقروءة
$user->unreadNotifications->markAsRead();
// وضع علامة على إشعار محدد كمقروء
$notification = $user->notifications->find($id);
$notification->markAsRead();
// الحصول على بيانات الإشعار
foreach ($user->unreadNotifications as $notification) {
echo $notification->data['message'];
echo $notification->created_at->diffForHumans();
}
// حذف إشعار
$notification->delete();
قنوات الإشعارات
يدعم Laravel قنوات إشعارات متعددة بشكل افتراضي:
// تثبيت قناة إشعارات Slack
composer require laravel/slack-notification-channel
// في فئة الإشعار
public function via($notifiable)
{
$channels = ['database'];
if ($notifiable->email_notifications) {
$channels[] = 'mail';
}
if ($notifiable->slack_webhook) {
$channels[] = 'slack';
}
return $channels;
}
// إشعار Slack
public function toSlack($notifiable)
{
return (new SlackMessage)
->from('بوت الطلبات', ':shopping_cart:')
->to('#orders')
->content('تم استلام طلب جديد!')
->attachment(function ($attachment) {
$attachment->title('الطلب #' . $this->order->id)
->fields([
'العميل' => $this->order->customer->name,
'الإجمالي' => '$' . number_format($this->order->total, 2),
]);
});
}
تحذير: ضع دائمًا في قائمة الانتظار الإشعارات التي ترسل طلبات خارجية (بريد إلكتروني، Slack، SMS) لتجنب حظر تطبيقك. استخدم واجهة ShouldQueue في فئات الإشعارات.
الإشعارات القابلة للوضع في قائمة الانتظار
اجعل الإشعارات قابلة للوضع في قائمة الانتظار لأداء أفضل:
<?php
use Illuminate\Contracts\Queue\ShouldQueue;
class NewOrderNotification extends Notification implements ShouldQueue
{
use Queueable;
// تحديد اتصال قائمة الانتظار
public $connection = 'redis';
// تحديد اسم قائمة الانتظار
public $queue = 'notifications';
// عدد مرات المحاولة
public $tries = 3;
// المهلة بالثواني
public $timeout = 60;
}
تمرين 1: أنشئ إشعار "PasswordChanged" يرسل عبر البريد الإلكتروني وقاعدة البيانات. يجب أن يستخدم البريد الإلكتروني markdown ويتضمن زرًا للاتصال بالدعم إذا لم يقم المستخدم بإجراء التغيير.
تمرين 2: أنشئ نظام تفضيلات إشعارات حيث يمكن للمستخدمين تمكين/تعطيل إشعارات البريد الإلكتروني وقاعدة البيانات. عدّل طريقة via() للإشعار لاحترام هذه التفضيلات.
تمرين 3: ابنِ مكون مركز إشعارات يعرض الإشعارات غير المقروءة مع عدد الشارات. أضف وظيفة لوضع علامة على الإشعارات كمقروءة عند النقر عليها وحذفها.
اختبار الإشعارات
اختبر الإشعارات باستخدام تأكيدات Laravel المدمجة:
use Illuminate\Support\Facades\Notification;
public function test_user_receives_welcome_email()
{
Notification::fake();
$user = User::factory()->create();
$user->notify(new WelcomeEmail($user, 'http://verify.url'));
Notification::assertSentTo($user, WelcomeEmail::class);
Notification::assertSentTo(
$user,
WelcomeEmail::class,
function ($notification, $channels) use ($user) {
return $notification->user->id === $user->id;
}
);
}
توفر الإشعارات والبريد طريقة موحدة ومستقلة عن القناة لإبقاء المستخدمين على اطلاع. في الدرس التالي، سنستكشف الأحداث والمستمعين لبناء تطبيقات مفصولة ومدفوعة بالأحداث.