WebSocket في PHP: إنشاء تطبيقات الوقت الفعلي من الصفر
تتطلب تطبيقات الويب الحديثة استجابة فورية لإجراءات المستخدمين. بروتوكول HTTP القياسي، الذي يعمل وفق مبدأ "طلب-استجابة"، غير مناسب للمهام التي تحتاج فيها البيانات إلى التحديث في الوقت الفعلي - مثل الدردشات، الإشعارات، أسعار البورصة أو الألعاب عبر الإنترنت. حل هذه المشكلة هو WebSocket. في هذه المقالة، سنشرح كيفية تنفيذ WebSocket في PHP، وسننشئ دردشة بسيطة، ونستعرض أفضل الممارسات.
ما هو WebSocket ولماذا هو مطلوب في PHP؟
WebSocket هو بروتوكول اتصال يوفر اتصالاً ثنائي الاتجاه مستمراً بين العميل (المتصفح) والخادم. على عكس HTTP، بعد إنشاء الاتصال، يمكن نقل البيانات في كلا الاتجاهين في أي لحظة دون الحاجة إلى طلبات متكررة. هذا أمر بالغ الأهمية لتطبيقات الوقت الفعلي.
تُعتبر PHP تقليدياً لغة للمنطق من جانب الخادم، تعمل وفق نموذج "تشغيل-تنفيذ-إنهاء". ومع ذلك، مع ظهور المكتبات غير المتزامنة مثل Ratchet و ReactPHP، أصبحت PHP أداة كاملة لإنشاء خوادم WebSocket. المزايا الرئيسية لاستخدام WebSocket في PHP:
- توصيل فوري للبيانات - دون تأخير ناتج عن طلبات HTTP المتكررة.
- تقليل الحمل على الخادم - اتصال واحد يحل محل عشرات طلبات Long Polling.
- سهولة التكامل - إذا كان مشروعك يعمل بالفعل على PHP، فلن تحتاج لتغيير مجموعة التقنيات.
تثبيت وإعداد مكتبة Ratchet
للعمل مع WebSocket في PHP، سنستخدم مكتبة Ratchet (بالاشتراك مع ReactPHP). يتم التثبيت عبر Composer:
composer require cboden/ratchetبعد التثبيت، سننشئ كلاساً أساسياً لخادم WebSocket. في Ratchet، يتم تنفيذ الخادم من خلال واجهة MessageComponentInterface، والتي تحتوي على أربع دوال:
onOpen- تُستدعى عند اتصال عميل جديد.onMessage- تعالج الرسالة الواردة.onClose- تُفعّل عند فصل العميل.onError- تعالج أخطاء الاتصال.
مثال على خادم بسيط:
<?phpuse Ratchet\\MessageComponentInterface;use Ratchet\\ConnectionInterface;
class ChatServer implements MessageComponentInterface { protected $clients;
public function __construct() { $this->clients = new \\SplObjectStorage; }
public function onOpen(ConnectionInterface $conn) { $this->clients->attach($conn); echo "اتصال جديد: {$conn->resourceId}"; }
public function onMessage(ConnectionInterface $from, $msg) { foreach ($this->clients as $client) { if ($from !== $client) { $client->send($msg); } } }
public function onClose(ConnectionInterface $conn) { $this->clients->detach($conn); echo "تم إغلاق الاتصال {$conn->resourceId}"; }
public function onError(ConnectionInterface $conn, \\Exception $e) { echo "خطأ: {$e->getMessage()}"; $conn->close(); }}تشغيل خادم WebSocket والجزء العميل
لتشغيل الخادم، سننشئ ملف server.php:
<?phprequire __DIR__ . '/vendor/autoload.php';
use Ratchet\\Server\\IoServer;use Ratchet\\Http\\HttpServer;use Ratchet\\WebSocket\\WsServer;
$server = IoServer::factory( new HttpServer( new WsServer( new ChatServer() ) ), 8080);
echo "خادم WebSocket يعمل على المنفذ 8080";$server->run();قم بتشغيل الخادم باستخدام الأمر:
php server.php
```