تم إعداد ترجمة للمقال خصيصًا لطلاب دورة "Laravel" .
يتوقع مستخدم الويب الحديث أن يكون على علم بكل ما يحدث في التطبيق. لن ترغب في أن تكون موقع الويب الذي لا يحتوي حتى على قائمة منسدلة بالإشعارات ، والتي يمكن العثور عليها الآن ليس فقط في جميع مواقع الشبكات الاجتماعية ، ولكن بشكل عام في كل مكان هذه الأيام.لحسن الحظ ، مع Laravel و Pusher ، فإن تنفيذ هذه الوظيفة بسيط للغاية.إخطارات الوقت الحقيقي
من أجل توفير تجربة مستخدم إيجابية ، يجب عرض الإشعارات في الوقت الفعلي. تتمثل إحدى الطرق في إرسال طلب AJAX بانتظام إلى الخادم وتلقي أحدث الإشعارات ، إن وجدت.أفضل طريقة هي استخدام إمكانات WebSockets وتلقي الإخطارات عند إرسالها. هذا هو بالضبط ما سنقوم بتطبيقه في هذه المقالة.انتهازي
Pusher هي خدمة ويب لدمج وظائف ثنائية الاتجاه في الوقت الحقيقي من خلال WebSockets في تطبيقات الويب والجوال.يحتوي على واجهة برمجة تطبيقات بسيطة جدًا ، لكننا سنجعل استخدامه أسهل مع Laravel Broadcasting و Laravel Echo.في هذه المقالة ، سنضيف إشعارات في الوقت الفعلي إلى مدونة حالية.مشروع
التهيئة
أولاً ، قمنا باستنساخ مدونة Laravel بسيطة:git clone https:
ثم سنقوم بإنشاء قاعدة بيانات MySQL وإعداد متغيرات البيئة لمنح التطبيق حق الوصول إلى قاعدة البيانات.نسخة دعونا env.example
في .env
وتحديث المتغيرات المرتبطة بها في قاعدة البيانات.cp .env.example .envDB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
الآن دعونا تثبيت تبعيات المشروع باستخدامcomposer install
وقم بتشغيل أمر الترحيل وملء البيانات لتعبئة قاعدة البيانات ببعض البيانات:php artisan migrate --seed
إذا قمت بتشغيل التطبيق وانتقلت إلى /posts
، يمكنك مشاهدة قائمة بالمشاركات التي تم إنشاؤها.تحقق من التطبيق ، سجل المستخدم وقم بإنشاء بعض الرسائل. هذا تطبيق بسيط للغاية ، ولكنه رائع للعرض.الاشتراك في المستخدمين
نود أن نمنح المستخدمين الفرصة للاشتراك في بعضهم البعض ، لذلك يجب أن ننشئ علاقة بين العديد من المستخدمين من أجل تحقيق ذلك.لنقم بإنشاء جدول محوري يربط المستخدمين بالمستخدمين. لنقم بإجراء ترحيل جديد followers
:php artisan make:migration create_followers_table --create=followers
نحتاج إلى إضافة العديد من الحقول إلى هذا الترحيل: user_id
لتمثيل المستخدم المشترك وحقل follows_id
لتمثيل المستخدم الذي تم الاشتراك فيه.تحديث الترحيل كما يلي:public function up()
{
Schema::create('followers', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index();
$table->integer('follows_id')->index();
$table->timestamps();
});
}
الآن دعنا ننتقل إلى إنشاء الجدول:php artisan migrate
دعنا نضيف أساليب علاقة للنموذج User
.
class extends Authenticatable
{
public function followers()
{
return $this->belongsToMany(self::class, 'followers', 'follows_id', 'user_id')
->withTimestamps();
}
public function follows()
{
return $this->belongsToMany(self::class, 'followers', 'user_id', 'follows_id')
->withTimestamps();
}
}
الآن بعد أن يكون للنموذج User
العلاقات اللازمة ، فإنه followers
يعيد جميع المشتركين في المستخدم ، follows
ويعيد جميع أولئك المشتركين فيه.سنحتاج إلى بعض الوظائف الإضافية التي تسمح للمستخدم بالاشتراك مع مستخدمين آخرين - follow
والتحقق مما إذا كان المستخدم مشتركًا في مستخدم معين - isFollowing
.
class extends Authenticatable
{
public function follow($userId)
{
$this->follows()->attach($userId);
return $this;
}
public function unfollow($userId)
{
$this->follows()->detach($userId);
return $this;
}
public function isFollowing($userId)
{
return (boolean) $this->follows()->where('follows_id', $userId)->first(['id']);
}
}
غرامة. بعد إعداد النموذج ، تحتاج إلى إنشاء قائمة بالمستخدمين.قائمة المستخدمين
لنبدأ بتحديد الطرق الضرورية./...
Route::group(['middleware' => 'auth'], function () {
Route::get('users', 'UsersController@index')->name('users');
Route::post('users/{user}/follow', 'UsersController@follow')->name('follow');
Route::delete('users/{user}/unfollow', 'UsersController@unfollow')->name('unfollow');
});
ثم حان الوقت لإنشاء وحدة تحكم جديدة للمستخدمين:php artisan make:controller UsersController
سنضيف طريقة إليها index
:
use App\User;
class UsersController extends Controller
{
public function index()
{
$users = User::where('id', '!=', auth()->user()->id)->get();
return view('users.index', compact('users'));
}
}
يجب إدخال الطريقة. لنقم بإنشاء طريقة عرض users.index
ووضع الترميز التالي فيه:@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-sm-offset-2 col-sm-8">
<!-- Following -->
<div class="panel panel-default">
<div class="panel-heading">
All Users
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<thead>
<th>User</th>
<th> </th>
</thead>
<tbody>
@foreach ($users as $user)
<tr>
<td clphpass="table-text"><div>{{ $user->name }}</div></td>
@if (auth()->user()->isFollowing($user->id))
<td>
<form action="{{route('unfollow', ['id' => $user->id])}}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit" id="delete-follow-{{ $user->id }}" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Unfollow
</button>
</form>
</td>
@else
<td>
<form action="{{route('follow', ['id' => $user->id])}}" method="POST">
{{ csrf_field() }}
<button type="submit" id="follow-user-{{ $user->id }}" class="btn btn-success">
<i class="fa fa-btn fa-user"></i>Follow
</button>
</form>
</td>
@endif
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection
يمكنك الآن زيارة الصفحة /users
للاطلاع على قائمة المستخدمين.اتبع وإلغاء المتابعة
في UsersController
الأساليب المفقودة follow
و unfollow
. دعنا ننفذها لإكمال هذا الجزء.
class UsersController extends Controller
{
public function follow(User $user)
{
$follower = auth()->user();
if ($follower->id == $user->id) {
return back()->withError("You can't follow yourself");
}
if(!$follower->isFollowing($user->id)) {
$follower->follow($user->id);
$user->notify(new UserFollowed($follower));
return back()->withSuccess("You are now friends with {$user->name}");
}
return back()->withError("You are already following {$user->name}");
}
public function unfollow(User $user)
{
$follower = auth()->user();
if($follower->isFollowing($user->id)) {
$follower->unfollow($user->id);
return back()->withSuccess("You are no longer friends with {$user->name}");
}
return back()->withError("You are not following {$user->name}");
}
}
لقد انتهينا بهذه الوظيفة. الآن يمكننا الاشتراك للمستخدمين وإلغاء الاشتراك منهم على الصفحة /users
.إشعارات
يوفر Laravel واجهة برمجة تطبيقات لإرسال الإشعارات عبر قنوات متعددة. يمكن إرسال البريد الإلكتروني والرسائل القصيرة وإشعارات الويب وأي أنواع أخرى من الإشعارات باستخدام فئة الإشعارات .سيكون لدينا نوعان من الإشعارات:- إشعار الاشتراك: يتم إرساله إلى المستخدم عندما يشترك فيه مستخدم آخر
- إشعار المشاركة: يتم إرساله إلى المشتركين في هذا المستخدم عند نشر مشاركة جديدة.
إشعار الاشتراك
باستخدام أوامر الحرفيين ، يمكننا إنشاء ترحيل للإعلامات:php artisan notifications:table
لنقم بالترحيل وننشئ هذا الجدول.php artisan migrate
سنبدأ بإشعارات الاشتراك. لنقم بتشغيل هذا الأمر لإنشاء فئة إعلام:php artisan make:notification UserFollowed
ثم نقوم بتعديل ملف فئة الإعلام الذي أنشأناه للتو:class UserFollowed extends Notification implements ShouldQueue
{
use Queueable;
protected $follower;
public function __construct(User $follower)
{
$this->follower = $follower;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'follower_id' => $this->follower->id,
'follower_name' => $this->follower->name,
];
}
}
مع هذه الأسطر القليلة من التعليمات البرمجية ، يمكننا بالفعل تحقيق الكثير. أولاً ، نطلب $follower
تنفيذ المثيل عند إنشاء هذا الإشعار.باستخدام هذه الطريقة via
، نطلب من Laravel إرسال هذا الإشعار عبر القناة database
. عندما يصادف Laravel هذا ، فإنه ينشئ إدخالًا جديدًا في جدول الإشعارات.user_id
و type
يتم تعيين الإخطارات تلقائيا، بالإضافة إلى أننا يمكن توسيع الإخطار مع بيانات إضافية. هذا ما هو عليه toDatabase
. ستتم إضافة المصفوفة التي تم إرجاعها إلى حقل data
الإعلام.وأخيرًا ، بفضل التنفيذShouldQueue
، سيقوم Laravel تلقائيًا بوضع هذا الإشعار في قائمة انتظار سيتم تشغيلها في الخلفية ، مما سيسرع الاستجابة. هذا منطقي لأننا سنضيف مكالمات HTTP عندما نستخدم Pusher لاحقًا.دعنا ننفذ إشعار اشتراك مستخدم.
use App\Notifications\UserFollowed;
class UsersController extends Controller
{
public function follow(User $user)
{
$follower = auth()->user();
if ( ! $follower->isFollowing($user->id)) {
$follower->follow($user->id);
$user->notify(new UserFollowed($follower));
return back()->withSuccess("You are now friends with {$user->name}");
}
return back()->withSuccess("You are already following {$user->name}");
}
}
يمكننا استدعاء طريقة الإخطار لنموذج المستخدم لأنه يستخدم بالفعل السمة المبلغة.أي نموذج تريد إخطاره يجب استخدامه للوصول إلى طريقة الإخطار.نحتفل بالإخطار على أنه "قراءةالإشعارات" ستحتوي على بعض المعلومات ورابط إلى المورد. على سبيل المثال: عندما يتلقى المستخدم إشعارًا حول رسالة جديدة ، يجب أن يحتوي الإشعار على نص إعلامي ، ويعيد توجيه المستخدم إلى الرسالة عند الضغط عليه ويتم وضع علامة عليه كمقروء.سنقوم بإنشاء طبقة تتحقق مما إذا كان هناك حدث في الطلب ?read=notification_id
ويضع علامة عليها كمقروءة.دعونا نجعل هذه الطبقة بالأمر التالي:php artisan make:middleware MarkNotificationAsRead
ثم دعنا نضع هذا الرمز في طريقة handle
الطبقة البينية:class MarkNotificationAsRead
{
public function handle($request, Closure $next)
{
if($request->has('read')) {
$notification = $request->user()->notifications()->where('id', $request->read)->first();
if($notification) {
$notification->markAsRead();
}
}
return $next($request);
}
}
من أجل تنفيذ الطبقة الخاصة بنا لكل طلب ، سنضيفها إلى $middlewareGroups
.
class Kernel extends HttpKernel
{
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\MarkNotificationAsRead::class,
],
];
}
بعد ذلك ، دعنا نعرض الإخطارات.عرض الإخطارات
نحتاج إلى إظهار قائمة الإشعارات باستخدام AJAX ، ثم تحديثها في الوقت الفعلي باستخدام Pusher. أولاً ، دعنا نضيف طريقة notifications
إلى وحدة التحكم:
class UsersController extends Controller
{
public function notifications()
{
return auth()->user()->unreadNotifications()->limit(5)->get()->toArray();
}
}
سيعيد هذا الرمز آخر 5 إشعارات غير مقروءة. نحتاج فقط إلى إضافة مسار لجعله متاحًا.
Route::group([ 'middleware' => 'auth' ], function () {
Route::get('/notifications', 'UsersController@notifications');
});
أضف الآن قائمة منسدلة للإشعارات في الرأس.<head>
<!--
<!-- Scripts -->
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
<!-- id JavaScript -->
@if(!auth()->guest())
<script>
window.Laravel.userId = <?php echo auth()->user()->id; ?>
</script>
@endif
</head>
<body>
<!--
@if (Auth::guest())
<li><a href="{{ url('/login') }}">Login</a></li>
<li><a href="{{ url('/register') }}">Register</a></li>
@else
<!--
<li class="dropdown">
<a class="dropdown-toggle" id="notifications" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span class="glyphicon glyphicon-user"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="notificationsMenu" id="notificationsMenu">
<li class="dropdown-header">No notifications</li>
</ul>
</li>
<!-- // ... // -->
أضفنا أيضًا متغيرًا عامًا window.Laravel.userId
إلى البرنامج النصي للحصول على معرف المستخدم الحالي.جافا سكريبت و SASS
سنستخدم Laravel Mix لتجميع JavaScript و SASS. أولاً ، نحتاج إلى تثبيت حزم npm.npm install
الآن دعنا نضيف هذا الرمز إلى app.js
:window._ = require('lodash');
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
var notifications = [];
const NOTIFICATION_TYPES = {
follow: 'App\\Notifications\\UserFollowed'
};
هذا مجرد التهيئة. سنستخدم الإشعارات لتخزين جميع كائنات الإشعارات ، سواء تم استردادها عبر AJAX أو Pusher.كما خمنت على الأرجح بالفعل ، فإنه NOTIFICATION_TYPES
يحتوي على أنواع الإشعارات.الآن دعنا نحصل على إشعارات ("GET") عبر AJAX.
$(document).ready(function() {
if(Laravel.userId) {
$.get('/notifications', function (data) {
addNotifications(data, "#notifications");
});
}
});
function addNotifications(newNotifications, target) {
notifications = _.concat(notifications, newNotifications);
notifications.slice(0, 5);
showNotifications(notifications, target);
}
بفضل هذا الرمز ، نتلقى أحدث الإشعارات من واجهة برمجة التطبيقات الخاصة بنا ونضعها في قائمة منسدلة.في الداخل ، addNotifications
نقوم بدمج الإشعارات الموجودة مع الإشعارات الجديدة باستخدام Lodash ، ونأخذ فقط آخر 5 ، والتي سيتم عرضها.نحتاج إلى المزيد من الوظائف لإنهاء المهمة.
function showNotifications(notifications, target) {
if(notifications.length) {
var htmlElements = notifications.map(function (notification) {
return makeNotification(notification);
});
$(target + 'Menu').html(htmlElements.join(''));
$(target).addClass('has-notifications')
} else {
$(target + 'Menu').html('<li class="dropdown-header">No notifications</li>');
$(target).removeClass('has-notifications');
}
}
تقوم هذه الوظيفة بإنشاء سطر من كافة الإعلامات ووضعه في القائمة المنسدلة.إذا لم يتم تلقي أي إشعارات ، فسيتم ببساطة عرض "لا توجد إشعارات".كما أنه يضيف فئة إلى الزر المنسدل ، والذي يغير اللون ببساطة عند وجود إشعارات. يشبه إلى حد ما إشعارات Github.أخيرًا ، بعض الوظائف المساعدة لإنشاء سلاسل الإخطار.
function makeNotification(notification) {
var to = routeNotification(notification);
var notificationText = makeNotificationText(notification);
return '<li><a href="' + to + '">' + notificationText + '</a></li>';
}
function routeNotification(notification) {
var to = '?read=' + notification.id;
if(notification.type === NOTIFICATION_TYPES.follow) {
to = 'users' + to;
}
return '/' + to;
}
function makeNotificationText(notification) {
var text = '';
if(notification.type === NOTIFICATION_TYPES.follow) {
const name = notification.data.follower_name;
text += '<strong>' + name + '</strong> followed you';
}
return text;
}
الآن نضيف هذا فقط إلى ملفنا app.scss
:
color:
}
دعونا تجميع الأصول:npm run dev
الآن إذا حاولت الاشتراك في أحد المستخدمين ، فسوف يتلقى إشعارًا. عندما ينقر عليه ، ستتم إعادة توجيهه إليه /users
، ويختفي الإشعار نفسه.إشعار وظيفة جديدة
سنقوم بإخطار المشتركين عندما ينشر مستخدم منشورًا جديدًا.لنبدأ بإنشاء فئة إعلام.php artisan make:notification NewPost
دعنا نعدل الصف المولد كما يلي:
use App\Post;
use App\User;
class NewArticle extends Notification implements ShouldQueue
{
protected $following;
protected $post;
public function __construct(User $following, Post $post)
{
$this->following = $following;
$this->post = $post;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'following_id' => $this->following->id,
'following_name' => $this->following->name,
'post_id' => $this->post->id,
];
}
}
بعد ذلك نحتاج إلى إرسال إشعار. هناك عدة طرق للقيام بذلك.أحب استخدام مراقبي Eloquent.دعونا ننشئ مراقبًا للبريد ونستمع إلى أحداثه. سنقوم بإنشاء فئة جديدة:app/Observers/PostObserver.php
namespace App\Observers;
use App\Notifications\NewPost;
use App\Post;
class PostObserver
{
public function created(Post $post)
{
$user = $post->user;
foreach ($user->followers as $follower) {
$follower->notify(new NewPost($user, $post));
}
}
}
ثم سجل المراقب في AppServiceProvider
:
use App\Observers\PostObserver;
use App\Post;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Post::observe(PostObserver::class);
}
}
الآن نحن بحاجة فقط لتنسيق الرسالة للعرض في JS:
const NOTIFICATION_TYPES = {
follow: 'App\\Notifications\\UserFollowed',
newPost: 'App\\Notifications\\NewPost'
};
function routeNotification(notification) {
var to = `?read=${notification.id}`;
if(notification.type === NOTIFICATION_TYPES.follow) {
to = 'users' + to;
} else if(notification.type === NOTIFICATION_TYPES.newPost) {
const postId = notification.data.post_id;
to = `posts/${postId}` + to;
}
return '/' + to;
}
function makeNotificationText(notification) {
var text = '';
if(notification.type === NOTIFICATION_TYPES.follow) {
const name = notification.data.follower_name;
text += `<strong>${name}</strong> followed you`;
} else if(notification.type === NOTIFICATION_TYPES.newPost) {
const name = notification.data.following_name;
text += `<strong>${name}</strong> published a post`;
}
return text;
}
وفويلا! يتم إخطار المستخدمين بالاشتراكات والمشاركات الجديدة! جربها بنفسك!اخرج في الوقت الحقيقي مع Pusher
حان الوقت لاستخدام Pusher لتلقي إشعارات في الوقت الفعلي عبر مآخذ الويب.سجل للحصول على حساب Pusher مجاني على pusher.com وأنشئ تطبيقًا جديدًا....
BROADCAST_DRIVER=pusher
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
قم بتعيين المعلمات لحسابك في ملف التكوين broadcasting
:
'connections' => [
'pusher' => [
'options' => [
'cluster' => 'eu',
'encrypted' => true
],
],
ثم نسجل App\Providers\BroadcastServiceProvider
في الصفيف providers
.
'providers' => [
App\Providers\BroadcastServiceProvider
],
نحتاج الآن إلى تثبيت PHP SDK و Laravel Echo من Pusher:composer require pusher/pusher-php-server
npm install --save laravel-echo pusher-js
نحن بحاجة إلى إعداد بيانات الإخطار للبث. دعونا نقوم بتعديل الإخطار UserFollowed
:
class UserFollowed extends Notification implements ShouldQueue
{
public function via($notifiable)
{
return ['database', 'broadcast'];
}
public function toArray($notifiable)
{
return [
'id' => $this->id,
'read_at' => null,
'data' => [
'follower_id' => $this->follower->id,
'follower_name' => $this->follower->name,
],
];
}
}
و NewPost
:
class NewPost extends Notification implements ShouldQueue
{
public function via($notifiable)
{
return ['database', 'broadcast'];
}
public function toArray($notifiable)
{
return [
'id' => $this->id,
'read_at' => null,
'data' => [
'following_id' => $this->following->id,
'following_name' => $this->following->name,
'post_id' => $this->post->id,
],
];
}
}
آخر شيء علينا القيام به هو تحديث JS الخاص بنا. افتح app.js
وأضف الكود التالي
window.Pusher = require('pusher-js');
import Echo from "laravel-echo";
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
cluster: 'eu',
encrypted: true
});
var notifications = [];
$(document).ready(function() {
if(Laravel.userId) {
window.Echo.private(`App.User.${Laravel.userId}`)
.notification((notification) => {
addNotifications([notification], '#notifications');
});
}
});
و هذا كل شيئ. تضاف الإخطارات في الوقت الحقيقي. يمكنك الآن اللعب مع التطبيق ومعرفة كيفية تحديث الإشعارات.استنتاج
يحتوي Pusher على واجهة برمجة تطبيقات سهلة الاستخدام للغاية تجعل تنفيذ الأحداث في الوقت الفعلي بسيطًا للغاية. بالاشتراك مع إشعارات Laravel ، يمكننا إرسال إشعارات عبر عدة قنوات (البريد الإلكتروني والرسائل القصيرة و Slack وما إلى ذلك) من مكان واحد. في هذا الدليل ، أضفنا وظائف لتتبع نشاط المستخدم في مدونة بسيطة وقمنا بتحسينها باستخدام الأدوات المذكورة أعلاه للحصول على بعض الوظائف السلسة في الوقت الفعلي.لدى Pusher و Laravel المزيد من الإشعارات: في نفس الوقت ، تتيح لك الخدمات إرسال رسائل Pub / sub في الوقت الفعلي إلى المتصفحات والهواتف المحمولة وأجهزة IOT. هناك أيضًا واجهة برمجة تطبيقات للحصول على حالة المستخدم عبر الإنترنت / دون اتصال.يرجى الاطلاع على وثائقهم ( مستندات دافع، دروس دافع ، مستندات Laravel ) لمعرفة المزيد حول استخدامها وإمكاناتها الحقيقية.إذا كان لديك أي تعليقات أو أسئلة أو توصيات ، فلا تتردد في مشاركتها في التعليقات أدناه!
تعلم المزيد عن الدورة.