ويب-سوكيت في PHP: كيف تجعل موقعك يتحدث في الوقت الفعلي
\n\nتخيل موقعًا عاديًا. تضغط على زر - وتنتظر حتى يتم تحديث الصفحة. هذا مثل إرسال رسالة بالبريد: ترميها في الصندوق وتأمل أن تصل. والآن تخيل أنك تتحدث عبر الهاتف - تسمع المحاور فورًا. WebSockets هي تمامًا هذا "الهاتف" للويب. ونعم، هذا يعمل على PHP.
\n\nيعتقد الكثيرون أن WebSocket هي حكر على Node.js أو Python. لكن PHP، رغم أنها أُنشئت "للصق" HTML، فقد تجاوزت مهدها منذ زمن. اليوم سنشرح كيفية إنشاء تطبيق وقت فعلي على PHP - سواء كان دردشة، شريط إشعارات، أو تحليلات حية. وبدون أي حلول مؤقتة.
\n\nإذا حاولت يومًا إنشاء دردشة حية على PHP عبر long polling ورأيت الخادم ينهار تحت 1000 طلب في الثانية - فهذه المقالة لك. WebSockets تغير قواعد اللعبة.
\n\nما هو WebSocket ولماذا PHP صديقة له؟
\n\nWebSocket هي قناة اتصال ثنائية الاتجاه بين المتصفح والخادم. على عكس HTTP حيث يبدأ العميل الطلب دائمًا، هنا يمكن للخادم إرسال البيانات إلى العميل بنفسه. هذا يعطي وقتًا فعليًا حقيقيًا، وليس مجرد محاكاة له.
\n\nالفرق الرئيسي عن long polling (عندما يسأل العميل باستمرار "هل هناك أخبار؟") - في WebSocket تبقى الاتصالات مفتوحة. بمجرد إنشائها - وتتواصل دون انقطاع. توفير هائل في حركة المرور والموارد.
\n\nPHP، كلغة، تنفذ البرامج النصية بشكل تسلسلي. لكن هذا لا يمنعها من أن تكون خادمًا ممتازًا لـ WebSocket. السر في الهندسة: نحن لا نشغل PHP عبر خادم ويب (Apache/Nginx) لكل اتصال، بل نستخدمها كخادم مستقل (daemon). وهنا تظهر المكتبات على المسرح.
\n\nمكتبات WebSocket على PHP: ماذا تختار؟
\n\nأشهر مكتبتين - وكلتاهما تستحقان الاهتمام:
\n\n- \n
- Ratchet - جد WebSocket في PHP. موثوق، مجرّب، لكنه قديم الطراز بعض الشيء. يستخدم نموذج الأحداث القائم على
ReactPHP. مناسب تمامًا للدردشات البسيطة والإشعارات. \n - Swoole - وحش. ليست مجرد مكتبة، بل محرك كامل يعيد كتابة نواة PHP. يوفر عدم التزامن، coroutines، وأداء يقترب من Go. لكنه يتطلب تثبيت إضافة على الخادم. \n
للتعارف الأول، أوصي بـ Ratchet - فهو أسهل في التعلم ولا يتطلب تعديل php.ini. بالإضافة إلى أنه يعمل بشكل رائع مع ReactPHP، الذي سنتطرق إليه اليوم أيضًا.
\n\nنكتب خادم WebSocket بسيط على PHP باستخدام Ratchet
\n\nلننشئ خادم echo أساسي. سيقبل الرسائل من العميل ويعيد إرسالها إليه. هذا هو "Hello, World" الكلاسيكي لـ WebSocket.
\n\nأولاً، نثبّت Ratchet عبر Composer. افتح الطرفية في جذر المشروع:
\n\ncomposer require cboden/ratchet\n\nالآن، لننشئ ملف server.php:
<?php\nrequire __DIR__ . '/vendor/autoload.php';\n\nuse Ratchet\\MessageComponentInterface;\nuse Ratchet\\ConnectionInterface;\n\nclass EchoServer implements MessageComponentInterface {\n public function onOpen(ConnectionInterface $conn) {\n echo "اتصال جديد: {$conn->resourceId}\\n";\n }\n\n public function onMessage(ConnectionInterface $from, $msg) {\n echo "تم الاستلام: {$msg}\\n";\n $from->send("صدى: {$msg}");\n }\n\n public function onClose(ConnectionInterface $conn) {\n echo "الاتصال {$conn->resourceId} مغلق\\n";\n }\n\n public function onError(ConnectionInterface $conn, \\Exception $e) {\n echo "خطأ: {$e->getMessage()}\\n";\n $conn->close();\n }\n}\n\n// تشغيل الخادم\nuse Ratchet\\Server\\IoServer;\nuse Ratchet\\Http\\HttpServer;\nuse Ratchet\\WebSocket\\WsServer;\n\