مقدمة في البرمجة غير المتزامنة في PHP
\n\nيعمل PHP التقليدي بشكل متزامن: يتم تنفيذ كل عملية بشكل تسلسلي. إذا احتاج السكريبت إلى إرسال طلب HTTP أو قراءة ملف، فإنه ينتظر اكتمال العملية، مما يمنع تنفيذ بقية الكود. بالنسبة لتطبيقات الويب ذات التحميل العالي، يصبح هذا عنق زجاجة. تحل البرمجة غير المتزامنة هذه المشكلة، مما يسمح بتنفيذ مهام متعددة في وقت واحد دون حظر التدفق الرئيسي.
\n\nفي هذا الدليل، سنشرح كيف تعمل البرمجة غير المتزامنة في PHP، وما هي الأدوات المتاحة وكيفية استخدامها عمليًا. ستتعرف على المولدات، ومكتبات ReactPHP و Swoole، بالإضافة إلى الإمكانيات الجديدة في PHP 8.1 - Fiber.
\n\nأساسيات البرمجة غير المتزامنة
\n\nما هي البرمجة غير المتزامنة ولماذا نحتاجها؟
\n\nتخيل أنك تحضر وجبة الإفطار. النهج المتزامن: تضع الغلاية، تنتظر حتى تغلي، ثم تبدأ في قلي البيض. النهج غير المتزامن: تضع الغلاية وأثناء تسخين الماء، تقوم بالتوازي بإعداد العجة. في PHP، هذا يعني أنه بدلاً من انتظار الرد من قاعدة البيانات أو API خارجي، يمكنك تنفيذ كود آخر.
\n\nالمزايا الرئيسية للنهج غير المتزامن:
\n- \n
- زيادة الأداء في عمليات الإدخال/الإخراج (الشبكة، الأقراص، قواعد البيانات) \n
- توفير موارد الخادم - عدد أقل من الخيوط يعالج المزيد من الطلبات \n
- إمكانية إنشاء تطبيقات الوقت الفعلي (الدردشات، الإشعارات، البث المباشر) \n
مشكلة الكود المتزامن
\n\nلنأخذ مثالًا كلاسيكيًا: الحصول على بيانات من واجهتي API خارجيتين. سيتم تنفيذ الكود المتزامن بشكل تسلسلي:
\n\n<?php\nfunction fetchData($url) {\n $ch = curl_init($url);\n curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n $result = curl_exec($ch); // حظر أثناء الطلب\n curl_close($ch);\n return $result;\n}\n\n$start = microtime(true);\n$data1 = fetchData('https://api.example.com/users');\n$data2 = fetchData('https://api.example.com/posts');\necho "الوقت: " . (microtime(true) - $start);\n?>\n\nإذا استغرق كل طلب ثانيتين، فسيكون إجمالي وقت التنفيذ 4 ثوانٍ، على الرغم من أنه كان بإمكاننا تنفيذ الطلبات بالتوازي.
\n\nأدوات البرمجة غير المتزامنة في PHP
\n\n1. المولدات (yield) - برمجة غير متزامنة خفيفة
\n\nظهرت المولدات في PHP 5.5 وتسمح بإنشاء دوال يمكنها إيقاف تنفيذها مؤقتًا وإعادة التحكم إلى الكود المستدعي. هذا هو الأساس لإنشاء coroutines.
\n\n<?php\nfunction generator() {\n echo "بداية المولد\\n";\n yield 1;\n echo "بعد أول yield\\n";\n yield 2;\n echo "النهاية\\n";\n}\n\n$gen = generator();\nforeach ($gen as $value) {\n echo "تم الاستلام: $value\\n";\n}\n?>\n\nيمكن استخدام المولدات لتنظيم عمليات غير محظورة بالتزامن مع حلقة الأحداث. ومع ذلك، هذا لا يكفي للبرمجة غير المتزامنة الكاملة - هناك حاجة إلى مكتبة.
\n\n2. ReactPHP - مكتبة موجهة بالأحداث
\n\nReactPHP هي مكتبة شائعة للبرمجة غير المتزامنة. توفر حلقة أحداث (Event Loop)، ومآخذ توصيل غير محظورة، وعميل وخادم HTTP. التثبيت عبر Composer:
\n\ncomposer require react/event-loop react/http\n\nمثال لطلب HTTP غير متزامن:
\n\n<?php\nrequire 'vendor/autoload.php';\n\nuse React\\EventLoop\\Factory;\nuse React\\HttpClient\\Client;\nuse React\\HttpClient\\Response;\n\n$loop = Factory::create();\n$client = new Client($loop);\n\n$request = $client->request('GET', 'https://api.example.com/data');\n$request->on('response', function (Response $response) {\n $response->on('data', function ($chunk) {\n echo "تم استلام جزء: " . strlen($chunk) . " بايت\\n";\n });\n $response->on('end', function () {\n echo "اكتمل الطلب\\n";\n });\n});\n$request->end();\n\necho "تم إرسال الطلب، في انتظار...\\n";\n$loop->run();\n?