FlowingDev

PHP، بدون توصيلات: سيرفرك الشخصي في تبويب متصفح

اكتشف كيف تسمح لك WebAssembly بتشغيل مفسّر PHP حقيقي مباشرة في متصفحك، مما يتيح الاختبار الفوري والنماذج الأولية بدون الحاجة لإعداد سيرفر.

جرّب الأداة: ملعب PHP

في جملة واحدة

ملعب PHP يشغل مفسّر PHP الفعلي—البرنامج الذي ينفذ السكريبتات الخاصة بك—مباشرة في متصفح الويب الخاص بك باستخدام تقنية مذهلة تسمى WebAssembly، بدون الحاجة إلى سيرفر.

المشكلة التي يحلها

لعقود من الزمن، كان تشغيل PHP يعني شيئًا واحدًا: إعداد سيرفر. سواء كان جهازًا ماديًا في مركز بيانات، أو سيرفرًا افتراضيًا خاصًا في السحابة، أو حزمة محلية مثل XAMPP/MAMP/Docker على حاسوبك المحمول، كنت بحاجة إلى بيئة مخصصة. كانت PHP، بحكم تعريفها، لغة جانب السيرفر.

هذا خلق الكثير من العناء للمهام البسيطة. هل تريد اختبار دالة جديدة للمصفوفات؟ التحقق من كيفية تعامل json_encode مع كائن معين؟ تصحيح تعبير نمطي (regular expression) صعب؟ كان عليك تشغيل السيرفر المحلي، وإنشاء ملف .php جديد، وكتابة الكود، ثم فتحه في المتصفح أو تشغيله من سطر الأوامر. كان الأمر أشبه بالحاجة إلى تسخين فرن صناعي ضخم فقط لتحميص شريحة خبز واحدة.

كانت هذه الضريبة على الإعداد مؤلمة بشكل خاص لـ:

  • المتعلمين: كان على المبتدئين المصارعة مع إعدادات السيرفر حتى قبل أن يتمكنوا من كتابة أول echo "Hello, World!";.
  • المختبرين السريعين: المطورون ذوو الخبرة الذين يحتاجون إلى بيئة "مسودة" كانوا يمرون بعملية متعددة الخطوات لمهمة لا تستغرق 30 ثانية.
  • المتعاونين: مشاركة مقتطف من الكود كانت تعني لصق النص والأمل في أن يكون لدى الشخص الآخر بيئة متوافقة لتشغيله.

كانت المشكلة الأساسية هي الاقتران الوثيق بين لغة PHP وبيئة السيرفر التي تعمل فيها. كنا بحاجة إلى طريقة لفصل مفسّر PHP عن السيرفر، لجعله محمولاً ومتاحًا على الفور. وهنا يأتي دور WebAssembly.

كيف تعمل من الداخل

السحر الذي يتيح لك تشغيل لغة من جانب السيرفر في متصفح من جانب العميل هو WebAssembly، أو "Wasm" اختصارًا. إنه تحول جوهري في ما يمكن للمتصفح القيام به، وملعب PHP هو مثال رائع على قوته.

سحر WebAssembly (Wasm)

فكر في محرك JavaScript في متصفحك كعامل متخصص للغاية وبارع بشكل لا يصدق في لغة واحدة: JavaScript. لسنوات، كانت تلك هي اللغة الوحيدة التي يتحدثها. إذا أردت تشغيل كود في المتصفح، كان عليك كتابته بلغة JavaScript (أو لغة يتم تحويلها إلى JavaScript، مثل TypeScript).

غيرت WebAssembly قواعد اللعبة. إنها صيغة تعليمات ثنائية منخفضة المستوى—ليست لغة تكتبها يدويًا بقدر ما هي هدف للترجمة (compilation target). الأمر أشبه بشحن أجزاء آلة مجمعة مسبقًا بدلاً من كتيب تعليمات من IKEA. يمكن ترجمة لغات مثل C و C++ و Rust إلى ملف .wasm. يمكن للمتصفح بعد ذلك أخذ هذا الملف وتنفيذه بسرعة شبه أصلية، أسرع بكثير مما يمكنه عادةً تفسير JavaScript.

والأهم من ذلك، أن Wasm يعمل في نفس "صندوق الرمل" الآمن (secure sandbox) مثل JavaScript، مما يعني أنه لا يمكنه الوصول عشوائيًا إلى الملفات على جهاز الكمبيوتر الخاص بك أو العبث بنظام التشغيل.

ترجمة PHP إلى Wasm

إذًا، كيف ينطبق هذا على PHP؟ مفسّر PHP القياسي، محرك Zend، مكتوب بلغة C. هذا هو المفتاح. بما أن المفسّر هو برنامج C، يمكننا استخدام سلسلة أدوات خاصة لترجمته إلى WebAssembly بدلاً من ملف تنفيذي تقليدي لنظام Windows أو Linux.

الأداة الأكثر شيوعًا لهذه المهمة هي Emscripten. تأخذ الكود المصدري لـ PHP وتقوم بأمرين:

  1. ترجمة كود C إلى ملف .wasm. هذا هو محرك PHP الأساسي، الآن بتنسيق يمكن للمتصفح تشغيله.
  2. توليد كود JavaScript "لاصق" (glue code). يعمل كود JS هذا كجسر بين عالم Wasm وعالم JavaScript في المتصفح. يتولى تحميل وحدة Wasm، وتمرير البيانات ذهابًا وإيابًا، وربط المدخلات والمخرجات.

تبدو العملية المبسطة كما يلي: الكود المصدري لـ PHP بلغة C -> مترجم Emscripten -> php.wasm + glue.js

المتصفح كنظام تشغيل مصغّر

عندما تقوم بتحميل صفحة ملعب PHP، يصبح متصفحك نظام تشغيل مؤقتًا ومستقلاً لمفسّر PHP.

  1. الجلب (Fetching): يقوم متصفحك بتنزيل ملف php.wasm وكود JavaScript اللاصق.
  2. التهيئة (Instantiation): يخبر الكود اللاصق محرك JavaScript في المتصفح بتحميل وحدة Wasm. هذا ينشئ نسخة من مفسّر PHP في الذاكرة.
  3. البيئة الافتراضية: هنا يصبح الأمر ذكيًا. تتوقع PHP أن تكون قادرة على القيام بأشياء مثل قراءة الملفات والكتابة إلى الإخراج القياسي. ينشئ الكود اللاصق بيئة افتراضية لها:
    • الإخراج القياسي (stdout): عندما يستخدم سكريبت PHP الخاص بك echo أو print، لا تكتب وحدة Wasm إلى طرفية (terminal). بدلاً من ذلك، تكتب إلى مخزن مؤقت في الذاكرة (memory buffer) يمكن لكود JavaScript اللاصق قراءته. ثم تأخذ واجهة المستخدم للملعب هذا الإخراج وتعرضه على الشاشة.
    • نظام ملفات افتراضي: يوفر Emscripten نظام ملفات في الذاكرة (يُطلق عليه غالبًا MEMFS). عندما يحاول كود PHP الخاص بك file_put_contents('data.txt', '...')، فإنه لا يكتب على محرك الأقراص الثابتة. إنه يكتب إلى ملف محاكى داخل كائن JavaScript في ذاكرة المتصفح. هذا الملف يوجد فقط طالما أن جلسة الصفحة نشطة.

عندما تكتب كود PHP الخاص بك وتضغط على "تشغيل"، يقوم JavaScript الخاص بالملعب بتمرير السكريبت الخاص بك كسلسلة نصية إلى نسخة Wasm. يقوم محرك PHP المترجم بتنفيذه، ويتم التقاط مخرجاته بواسطة كود JS اللاصق، وتظهر النتيجة على شاشتك—كل ذلك داخل تبويب متصفح واحد.

// A conceptual look at the JS side of a playground
async function runMyPhp() {
  // 1. Load the Wasm module and its JS bridge
  const php = await createPHPWasmModule();

  // 2. The PHP code from the editor
  const userCode = '<?php echo "The answer is " . (6 * 7); ?>';

  // 3. Execute the code via the bridge
  const output = php.run(userCode);

  // 4. Display the captured output
  document.getElementById('output-area').textContent = output;
  // -> Displays "The answer is 42"
}

قصص من الواقع

التحقق السريع من خوارزمية

يقوم ديفون بمراجعة pull request لزميله. يحتوي الكود على دالة معقدة تستخدم array_map و array_filter لتحويل بعض بيانات المستخدم. يبدو المنطق كثيفًا، وديفون ليس متأكدًا بنسبة 100% من أنه يغطي جميع الحالات الهامشية. الطريقة القديمة: سحب الفرع، تشغيل composer install، تشغيل سيرفر محلي، كتابة سكريبت اختبار مؤقت، وتشغيله. الطريقة الجديدة: نسخ الدالة المكونة من 10 أسطر، لصقها في ملعب PHP، تعريف مصفوفة عينة، والنقر على "تشغيل". في خمس ثوانٍ، يظهر الناتج. يجرب مصفوفة عينة مختلفة بقيم null. الناتج... خطأ. لم تكن الدالة قوية كما بدت. يلصق الكود المصحح ورابطًا للملعب في تعليق مراجعة الكود.

الدرس المستفاد: الملاعب تقلل من "جهد البدء" اللازم لاختبار منطق معزول من دقائق إلى ثوانٍ، مما يشجع على التحقق الأكثر صرامة.

إصلاح التوثيق أثناء التنقل

سام على متن قطار، تتصفح توثيق مكتبة PHP مفتوحة المصدر على هاتفها. تلاحظ مثال كود لإنشاء PDF يبدو قديمًا. بدون حاسوبها المحمول أو بيئة تطوير مناسبة، كان عليها في العادة أن تدون ملاحظة عقلية للتحقق من الأمر لاحقًا. بدلاً من ذلك، تفتح ملعب PHP في متصفح هاتفها، تلصق كود المثال، وتشغله. كما توقعت، يظهر إشعار إيقاف استخدام (deprecation notice). تقوم بتعديل الكود مباشرة في الملعب حتى يعمل بشكل صحيح، ثم تقدم pull request للتوثيق مباشرة من متصفح هاتفها.

الدرس المستفاد: الملاعب تفصل التطوير عن جهاز معين، مما يجعل من الممكن الاختبار والتصحيح والمساهمة من أي مكان به متصفح ويب.

جلسة التعلم الحية

تقوم المدربة ماريا بتدريس دورة PHP تمهيدية. في السنوات السابقة، كان الأسبوع الأول كابوسًا في محاولة جعل كل طالب—على مزيج من أجهزة Windows و Mac و Linux—يقوم بتثبيت وتهيئة حزمة سيرفر محلية. هذا العام، ترسل للفصل رابطًا واحدًا لملعب PHP. تقوم بكتابة مثال مباشرة على شاشتها، ويمكن لكل طالب تشغيل وتعديل نفس الكود تمامًا على أجهزتهم على الفور. عندما يسأل طالب، "ماذا يحدث إذا استخدمت علامات اقتباس مفردة بدلاً من المزدوجة؟"، يمكنهم تجربتها بأنفسهم على الفور، مما يعزز حس الاكتشاف والتغذية الراجعة الفورية.

الدرس المستفात: الملاعب هي أدوات تعليمية مذهلة تقضي على حواجز الإعداد وتحول التعلم إلى عملية تفاعلية وتجريبية.

أخطاء ومزالق شائعة

  • توقع وجود سيرفر ويب كامل. ملعب PHP ليس بديلاً لـ Apache أو Nginx. إنه يشغل PHP في سياق سطر الأوامر (CLI). هذا يعني أن المتغيرات الشاملة (superglobals) مثل $_GET و $_POST و $_SERVER لن تكون ممتلئة لأنه لا يوجد طلب HTTP وارد لتزويدها بالبيانات.
  • نسيان نظام الملفات المؤقت. إذا كتبت ملفًا باستخدام file_put_contents()، فإنه يعيش في نظام ملفات مؤقت في الذاكرة. لا يتم حفظه على جهاز الكمبيوتر الخاص بك. إذا قمت بتحديث الصفحة، فسيختفي هذا الملف إلى الأبد.
  • تجاهل حدود موارد المتصفح. يعمل سكريبت PHP الخاص بك ضمن حدود تبويب المتصفح. حلقة لا نهائية أو سكريبت يستهلك كمية هائلة من الذاكرة لن يؤدي فقط إلى إبطاء السيرفر؛ بل يمكن أن يجمد أو يعطل تبويب المتصفح بالكامل.
  • افتراض أن دوال الشبكة تعمل ببساطة. دوال PHP التي تقوم بطلبات شبكة خارجية، مثل file_get_contents('https://api.example.com') أو عمليات cURL، تخضع لنموذج أمان المتصفح. سيتم حظرها بواسطة سياسات مشاركة الموارد عبر المصادر (Cross-Origin Resource Sharing - CORS) ما لم يتضمن الملعب بروكسي خاصًا أو طبقة محاكاة للتعامل معها.
  • الاعتماد على ملحقات PHP محددة. قد لا يتضمن مفسّر PHP المترجم إلى Wasm جميع الملحقات التي اعتدت عليها (مثل gd لمعالجة الصور، أو xdebug للتصحيح، أو برامج تشغيل قواعد البيانات مثل pdo_mysql). تقتصر قدراته على الملحقات التي تم تجميعها في بناء Wasm المحدد هذا.

لماذا يجب أن تكون في دائرة اهتمامك

يجب أن تفكر في ملعب PHP كلما كان لديك سؤال في PHP يبدأ بـ "أتساءل ماذا يحدث لو...". إنها المفكرة المثالية لمطور PHP الحديث.

إنها ليست لبناء تطبيقك التالي، ولكنها أداة لا غنى عنها للحظات التي بين ذلك:

  • النمذجة الأولية: بناء دالة أو كلاس بسرعة.
  • تصحيح الأخطاء (Debugging): عزل جزء منطقي به خطأ عن بقية تطبيقك.
  • التعلم: تجربة ميزات أو دوال لغة جديدة دون أي إعداد.
  • المشاركة: إنشاء مثال عملي وقابل للتنفيذ من الكود الخاص بك لمشاركته مع الزملاء أو في تقارير الأخطاء.

في عالم بيئات التطوير المعقدة، يعد ملعب PHP نسمة هواء منعشة—طريقة بسيطة وفورية وقوية لمجرد كتابة بعض PHP.

تعمق أكثر

  • WebAssembly Official Site: المصدر الرسمي لكل ما يتعلق بـ Wasm.
  • MDN WebAssembly Docs: توثيق Mozilla الممتاز وسهل الفهم حول كيفية عمل Wasm في المتصفح.
  • Emscripten Documentation: التوثيق الرسمي لسلسلة الأدوات المستخدمة لترجمة مشاريع C/C++ مثل PHP إلى WebAssembly.
  • PHP.net: دليل PHP الرسمي. الملعب يشغل هذا المحرك، لذا فهذا هو مرجعك لمعرفة وظائف الدوال.
  • The php-wasm Project: أحد المشاريع مفتوحة المصدر الرئيسية التي كانت رائدة في محاولة تشغيل PHP في المتصفح عبر Wasm.

كيف يفهم المحرر الشيفرة

ألوان الصياغة تأتي من محلل اللغة، لا من تشغيل البرنامج. يتعرف CodeMirror وLezer على الرموز والبنية محليًا في المتصفح. تجمع الاقتراحات الكلمات المحجوزة والأسماء المحلية عند دعمها والمقاطع الجاهزة ومرجعًا مدمجًا صغيرًا؛ ويكشف المرور فوق رمز موثق عن توقيعه. الاقتراح لا يضمن وجود الواجهة في بيئة التنفيذ. يكتشف المحلل أخطاء الصياغة عند دعمها، لكنه لا يحل محل فحص الأنواع أو التشغيل: قد تفشل شيفرة سليمة نحويًا. يستخدم Ruby وLua أوضاعًا قائمة على الرموز وتشخيصات أكثر محدودية. لا يوجد خادم لغة بعيد، ولا تحتاج الشيفرة إلى مغادرة الجهاز.

CodeMirror & Lezer: MIT.

انتهينا من النظرية. حان وقت التطبيق — 100% في متصفحك.

جرّب الأداة: ملعب PHP