مقدمة في البرمجة غير المتزامنة في PHP
تقليديًا، تُعتبر PHP لغة متزامنة: يتم تنفيذ كل طلب بشكل تسلسلي، مما يمنع التنفيذ حتى اكتمال عملية الإدخال/الإخراج (مثل قراءة ملف أو استعلام قاعدة بيانات). ومع ذلك، مع تزايد شعبية تطبيقات الويب عالية التحميل والخدمات المصغرة، نشأت الحاجة إلى معالجة عشرات الآلاف من الاتصالات المتزامنة دون توسيع نطاق عدد العمليات. تحل البرمجة غير المتزامنة هذه المشكلة من خلال السماح بتنفيذ العمليات بشكل متزامن داخل خيط واحد.
في هذا الدليل، سنشرح كيفية عمل عدم التزامن في PHP، وما هي الأدوات المتاحة، وكيفية بناء تطبيقات غير محظورة بشكل صحيح. ستتعرف على المولدات (Generators)، والكوروتينات (Coroutines)، ومكتبات ReactPHP و Amp و Swoole، بالإضافة إلى الامتداد الجديد Fibers.
أساسيات عدم التزامن: Event Loop والإدخال/الإخراج غير المحظور
تعتمد البرمجة غير المتزامنة على مفهوم Event Loop (حلقة الأحداث). وهي حلقة لا نهائية تنتظر الأحداث وتعالجها: طلبات الشبكة، إتمام عمليات الإدخال/الإخراج، المؤقتات. بدلاً من انتظار اكتمال العملية، يقوم الكود بتسجيل دالة استرجاع (callback) يتم تنفيذها عندما تكون البيانات جاهزة. هذا يسمح بعدم إضاعة وقت المعالج في الانتظار.
تستخدم PHP تقليديًا دوال الحظر (مثل file_get_contents() أو sleep()). للعمل غير المتزامن، يجب استبدالها بنظيراتها غير المحظورة. إليك مثال بسيط باستخدام مكتبة ReactPHP:
<?phprequire 'vendor/autoload.php';
use React\\EventLoop\\Factory;use React\\Promise\\Promise;
$loop = Factory::create();
// قراءة ملف غير متزامنة$promise = new Promise(function ($resolve, $reject) use ($loop) { $loop->addTimer(0.001, function () use ($resolve) { $content = file_get_contents('/etc/hosts'); $resolve($content); });});
$promise->then(function ($data) { echo "تمت القراءة: " . strlen($data) . " بايت";});
echo "سيتم تنفيذ هذا الكود فورًا، دون انتظار قراءة الملف";$loop->run();?>في هذا المثال، يقوم addTimer بتسجيل مهمة سيتم تنفيذها في النقرة التالية من الحلقة. لا يتم حظر Event Loop، ونرى الرسالة فورًا، بينما تظهر نتيجة القراءة لاحقًا.
المولدات والكوروتينات: التحكم في تدفق التنفيذ
ظهرت المولدات (yield) في PHP 5.5 وتسمح بإيقاف تنفيذ الدالة مؤقتًا، مع إرجاع قيم وسيطة. على أساسها تُبنى الكوروتينات — خيوط خفيفة الوزن يمكنها التخلي عن التحكم طواعية. بالاقتران مع Event Loop، تسمح المولدات بكتابة كود يبدو متزامنًا ولكنه يُنفذ بشكل غير متزامن.
لنلقِ نظرة على مثال باستخدام مكتبة Amp، التي تستخدم الكوروتينات:
<?phprequire 'vendor/autoload.php';
use Amp\\Loop;use Amp\\Delayed;
// كوروتين غير متزامن$coroutine = function () { echo "بداية الكوروتين"; // نتوقف لمدة ثانية واحدة دون حظر yield new Delayed(1000); echo "مرت ثانية واحدة"; yield new Delayed(500); echo "مرت 0.5 ثانية أخرى";};
Loop::run(function () use ($coroutine) { // تشغيل الكوروتين $result = yield from $coroutine(); echo "تم إكمال الكوروتين";});?>في هذا الكود، يقوم yield new Delayed(1000) بإيقاف تنفيذ الكوروتين مؤقتًا، ونقل التحكم مرة أخرى إلى Event Loop. بعد ثانية واحدة، يستأنف التنفيذ من نفس النقطة. هذا يسمح بمعالجة آلاف من هذه الكوروتينات في وقت واحد، دون إنشاء عمليات جديدة.
المكتبات والأدوات للبرمجة غير المتزامنة في PHP
للعمل مع عدم التزامن في PHP، توجد عدة مكتبات ناضجة. دعنا نلقي نظرة على الثلاثة الأكثر شيوعًا.
ReactPHP
ReactPHP هي أقدم وأشهر مكتبة. توفر Event Loop، و Promise (مشابهة لتلك الموجودة في JavaS