المحتوى عن 'php'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 35 نتائج

  1. ما هي لغة البرمجة التي يجب عليك تعلمها؟ بايثون، PHP أم روبي؟ ربما أكبر سؤال يواجه مطوري الويب المبتدئين هي ما هي أفضل لغة برمجة يجب تعلمها للوظيفة المستقبلية والآفاق، هنالك العديد من لغات البرمجة التي يجب عليك الاختيار منها وكل واحدة لديها نقاط القوة والضعف، ربما أهم مصدر مقلق هو المدة التي تستغرقه كل لغة للتعلم، وهذا يختلف من لغة إلى أخرى، فما الذي ينبغي تعلمه للحصول على أفضل وظيفة ناجحة في البرمجة؟ عندما بدأتُ تعلم تطوير الويب بحثتُ كثيرا حوله وجعلني هذا مرتبكًا بعض الشيء، فلم أتمكن من الحصول على إجابة نهائية حول ما هي أفضل لغة لأن كل كاتب له وجهة نظر مختلفة، وكان جميع الكتّاب يقارنون اللغات دون إعطاء استنتاج شامل. لذلك، في هذه المقالة، سأقارن بين اللغات البرمجة الحديثة الثلاثة، PHP وبايثون وروبي، وقبل كل شيء، أريد أن أظهر لك بعض البيانات القديمة التي وجدتها عندما بدأت بالتعلم حول تطوير الويب، وهذه البيانات القديمة مأخوذة من هنا وعلى الرغم من قِدَمِهَا إلا أنها تحتوي على بعض الحقائق المفيدة حول تاريخ هذه اللغات. بايثون ضد PHP ضد روبي من هذه المقارنة بين PHP وبايثون وروبي، ستجد أنه من الواضح: الطلب العالي على PHP في السوق. مبرمجي PHP مطلوبين بكثرة. قابلية استخدام PHP ضعيفة. تعلم واستخدام بايثون هو الأسهل. بايثون هي الأسرع. تعلم روبي هو الأصعب. يملك روبي أعلى قابلية استخدام. لكن كما قلت سابقًا، هذه مقارنة مختصرة، ومن هذه المقارنة لا يمكننا الاستنتاج أن PHP هو الأفضل وأن روبي هو الأسوأ، فهنالك أسئلة أخرى لم نرد عليها بعد. ما هي اللغة الأكثر أمانًا؟ ما هي القيود الأخرى على هذه اللغات؟ ما هي مزايا وأشكال الدعم الأخرى لهذه اللغات؟ ما هي نسبة وظيفة/مطور وما متوسط رواتب المطورين؟ ما هي اللغة الأكثر أمانا؟ يعتمد أمن الموقع/التطبيق في المقام الأول على المبرمج وليس لغة البرمجة، فمن المعروف أن PHP هي لغة برمجة غير آمنة، وهذا بسبب أن صياغة PHP ليست بسهولة صياغة بايثون أو روبي، وبسبب هذه الصياغة المعقدة (قابلية القراءة منخفضة) فإن فرص حدوث الأخطاء أكبر. فإذا كان المبرمج/المطور لا يخطئ، فليست PHP لغة غير آمنة، وفي الواقع، لدى PHP5 سمعة طيّبة مقارنة بالإصدارات القديمة، وكنتيجة لذلك، لا يوجد في الواقع استنتاج قوي حول مسألة أمن اللغة. ما هي قيود هذه اللغات؟ PHP: يملك الكثير من الصيغ المطولة من C++/C وبيرل، مع الكثير من الأقواس المعقوفة وعلامات الدولار و “→”. جدول مربك لأسماء الدوال، فتمتلك المكتبة المدمجة مجموعة كبيرة من اتفاقيات التسمية، ويملك الدوال في العادة على بادئة للدلالة على مصدرها (ولكنها لا تمتلك ذلك في كثير من الأحيان). تكون الدوال في العادة في أصناف لمحاكاة مساحات الأسماء (namespace). ليست مناسبة للتطبيقات الكبيرة: صعوبة الصيانة لأنها لا تتكون من وحدات بشكل جيّد. نوع ضعيف: التحويل الضمني قد يفاجئ المبرمجين الغافلين ويؤدي إلى أخطاء غير متوقعة، على سبيل المثال، تتساوى السلاسل “1000” و“1e3” عند المقارنة لأنها تحوّل ضمنيا إلى أعداد كسرية. لغة برمجة سكربتية، ليست لغة برمجة كائنية التوجه. بايثون: لا تملك بيان ‘switch’ ولا هيكل ‘do … while’. عوامل الزيادة والنقصان والتعيين (التعيين هو بيان فقط في بايثون). العامل/البيان الثلاثي (… ? … : …). بيئة مناسبة (مثبتة عادة). لا توجد مبدلات (modifier) خاصة، محمية و عامة للخصائص والأساليب. لا تملك abstract ومبدلات نهائية للأصناف والأساليب. روبي: قد تكون صعبة التعلم. تفتقر إلى موارد المعلومات. وقت المعالج بطيء (وقت CPU) بالمقارنة مع لغات برمجة أخرى. التطوير والتحديث أبطأ. ما هي مزايا وأشكال الدعم الأخرى لهذه اللغات؟ PHP: سهلة التعلم للمبتدئين وللمطورين القادمين من لغات ذات صياغة مشابهة مثل C و C++ و C# وجافا وجافا سكربت، إلخ. تدعم جميع خوادم ويب الرئيسية مثل اباتشي، مايكروسوفت IIS، Netscape و الخوادم الشخصية و خادم iPlanet… الخ. مقبولة للغاية من قبل صناعات عديدة وهي أكثر شعبيّة من بقية لغات البرمجة. سهولة استضافة PHP مباشرة دون أي إعدادات للخادم لأن استضافة المواقع صعبة بالنسبة للمبتدئين. يعتبر إطار zend هو الأشهر في PHP، وبعض الأطر الأخرى مثل Yii وLaravel وCodeigniter أعطت قوة كبيرة لـ PHP. من السهل تطوير أي نوع من CMS بسرعة. بايثون: سهولة الصياغة والقراءة، وسهلة التعلم للذين لا يمتلكون خبرة في البرمجة. لغة برمجة أغراض عامة. لغة برمجة كائنية التوجه. بايثون مناسبة جدا لـ glue. مكتبة قياسية ضخمة، كمثال عشوائي، تملك بايثون محللين لـ XML، قراء وكتّاب لملفات zip وcsv، مكتبات لاستخدام كل بروتوكول إنترنت ونوع بيانات، الخ. هياكل بيانات متطور كالقوائم والقواميس. أطر كبيرة لتطوير الويب مثل جانغو وFlask. روبي: تعتبر روبي لغة كائنية التوجه أكثر من بايثون وPHP. تم تطوير روبي لجعل عمل المطور سهل. تسمح الإضافات الأصناف والوحدات المستدعية بالتوسع والتغيير عن طريق الشيفرة البرمجية الخاصة بالمستخدمة بعد استدعائها، فالأصناف لا تغلق في روبي، حيث يمكنك تغييرها لاحقا. كتل الشيفرة البرمجية الخاصة بروبي أقوى من lambda الخاص ببايثون. كل شيء يرجع قيمة (بما في ذلك بيان ‘if’) ، وبسبب هذا، من السهل كتابة شيفرة برمجية مشابهة للدالة مقارنة بالبايثون وأسهل عند سلسلة الأوامر. مكتبات Gem الخاصة بالروبي، فالكثير من gem المتاحة تجعل فعل أي مهمة سهلةً بأقل جهد. قوة روبي في تطوير الويب هو إطار ريلز، فهو سحري جدًا، فلن تحتاج إلى القلق بشأن الوظائف الأساسية لتطوير الويب مثل التعديل والحذف البسيط، بل يمكنك التركيز على الخوارزميات المعقّدة الأخرى. يعتقد الروبي في إعطاء المبرمج الحرية والقوة. ما هي نسبة وظيفة/مطور وما متوسط رواتب المطورين؟ هذا السؤال شخصي للغاية ولن تكون له إجابة عامة بسيطة، فأغلب الوظائف والمبرمجين يستخدمون PHP، وأدى هذا إلى ضعف الرواتب بصفة عامة، ومع ذلك، فهذا لا يعني أن رواتب جميع المطورين/المبرمجين ضعيف، فبعض المطورين يحصلون على أموالٍ كثيرةٍ. هنالك فرص عمل كثيرة لمبرمجي بايثون وروبي بما أنهم يمتلكون عدد قليل من المبرمجين، لكن الطلب أقل في العادة. استنتاج عام: دعونا نلخص كل هذا باختصار: PHP وبايثون سهل التعلم بالنسبة للمبتدئين. PHP هي الأكثر طلبًا في العمل. PHP جيّدة للمواقع الصغيرة. (على الرغم من أن هنالك الكثير من المواقع الكبيرة مثل فيسبوك و ويكيبيديا مكتوبة بلغة PHP لكن ضمّن إليها لغات أخرى. تغيير موقع من لغة برمجة إلى لغة أخرى ليست مهمة سهلة). بايثون هي أفضل لغة للأغراض العامة. تُفضل إطارات بايثون (جانغو) وروبي (ريلز) أكثر من أي إطار آخر لبرمجة الويب. يمكنك اختيار أي واحدة منهم، فإذا لم تكن تبحث عن هدف كبير فبايثون هي الأفضل ليس فقط بسهولة تعلمها بل لأنها للأغراض العامة وتملك العديد من المميزات الكبيرة مثل هياكل البيانات، لكن جميع لغات البرمجة لديها نطاقات خاصة بها مثل اللاعبين في أي لعبة. ترجمة -وبتصرّف- للمقال PYTHON vs PHP vs RUBY لصاحبه Harish Kumar
  2. يحتار المطورون في اختيار أفضل إطار لمشاريعهم وسيكون هذا تحديًا حقيقيًا للمبتدئين في الأطر الحديثة. بعد العمل على الأطر الثلاثة (Django، Laravel و Rails – والذي يُعرف باسم Ruby On -rails)، سأقارن بين هذه الأطر الرائعة على أساس شعارها، سهولة تعلمها، أدائها، قوة وضعف مكتباتها وقوالبها، دعمها، آفاقها المستقبلية، فرص العمل، التكلفة والصيانة. ملاحظة: ينتقد بعض المعجبين عند التحدث عن نقاط ضعف أطرهم، ولا أستطيع فعل أي شيء لأنه لا يمكن إخفاء الحقيقة، كل إطار لديه بعض المزايا مع بعض العيوب. المقدمة لغة البرمجة أهم فرق بين هذه الأطر هي أن Django بلغة بايثون، Laravel بلغة PHP وRails بلغة الروبي، لذا إذا كنت تنوي استخدام أي من هذه الأطر فيجب عليك تعلم لغتها أولاً، وبسبب هذا، العديد من المطورين يختارون الإطار الذي يتطابق مع اللغة التي يعرفونها. إن التحول من لغة إلى أخرى ليس صعبًا بل يحتاج إلى بعض الوقت، وإذا احترت في اختيار لغة البرمجة، فهذه مقارنة بين لغات بايثون و PHP وروبي. الشعار جميع هذه الأطر من نوع MVC وشعارها ‘لا تكرر نفسك’ أي تدعم إعادة الاستخدام وقابلية النقل، وجميعها مشاريع مجانية ومفتوحة المصدر. المواقع بعض المواقع المعروفة تستخدم Django مثل Pinterest، Instagram، Mozilla، The Washington Times، Disqus، the Public Broadcasting Service و Bitbucket. في حين أن Laravel هو إطار جديد، حيث صدر في يونيو عام 2011، لكنه أصبح مشهورا جدا، ومن بين المواقع التي تستخدمه هي Deltanet Travel، Sublimity، Neighborhood Lender، Sendity و MyRank. يعتبر Rails من الأطر الرائعة فمن المواقع التي تستخدمه Twitter، Shopify، SoundCloud، Heroku، Github، Bloomberg و Hulu. سهولة التعلم على الرغم من أن الأطر الثلاثة لديها مجتمعات كبيرة وتوثيق رسمي، إلا أن تعلم Django وLaravel أسهل بكثير من تعلم Rails، فالتوثيق الحالي ل Django يجعلها الأسهل، وإذا كنت تملك خلفية PHP فيمكنك تعلم Laravel في غضون أسبوعين أو ثلاثة أسابيع، وهذه هي الوثائق الرسمية: وثائق Django ووثائق Laravel وثائق Rails. الأداء الأمن جميع هذه الأطر آمنة جدا إذا لم يرتكب المبرمج أخطاء، فيمتلك Django برمجيات وسيطة ويمتلك Rails Active Records وأما Laravel فيمتلك برمجيات HTTP وسيطة، وتوفر كل هذه الأطر رموز csrf للنماذج. لا يوجد فرق أمني كبير بين هذه الأطر، وكل هذا يعتمد على خبرة المبرمج. تحديث:أشار بعض القراء أن المبرمجين هم بشر وسيخطئون، لذا سأقول في هذه الحالة أن Django هو الأكثر أمانا وLaravel هو الأقل أمانًا، اطلع على هذا التوثيق عن أمن Django وهذا دليل أمن Rails و هذا دليل أمن Laravel، وسأقول أيضا أنه لا يوجد إطار آمن بشكل كامل لأن المطورين هم أيضا بشر، ويمكنك زيادة الأمن لكنك لا تستطيع جعله آمن بنسبة 100%، لكن إذا كتبت التعليمات البرمجية بعناية وحذر فإن جميع الأطر متساوية من ناحية الأمن. السرعة جميع الأطر مكتوبة بشكل صحيح، لذلك سرعتها تعتمد على اللغة البرمجة المستخدمة، فDjango هو الأسرع بسبب البايثون و Laravel هي الأبطأ بسبب PHP. الوقت المطلوب لإنشاء تطبيق إذا كنت تفهم الإطار بشكل كامل فإن إنشاء تطبيق Rails هو الأسرع لأنه يوفر لك الكثير من الاختصارات وبهذا ستكتب أقل عدد من الأسطر البرمجية. ومن جهة أخرى، Laravel هو الأبطأ ولا يوفر مكتبة قوية. إذا كان المشروع معقد فإن الفرق الزمني بين تطبيقات Django وRails سيكون صغيرًا بسبب صياغة بايثون المريحة للمتابعة وأقل أرباك، أما بالنسبة لـ Laravel فيجب عليك كتابة الكثير من الأسطر البرمجية وهذا قد يسبب لك بعض الإرباك وسترتفع نسبة الأخطاء. قوة وضعف المكتبة الأشياء المشتركة في جميع الأطر: جميعها MVC (يسمى Django MTV أيضا لكن على الرغم من أن الاسم مختلف إلا أن المفهوم هو نفسه). تركز جميع الأطر على قابلية القراءة وبساطة الشيفرة البرمجية وتوزيع الملفات. جميعها تستعلم تلقائيًا من قاعدة البيانات، فلا يجب عليك كتابة استعلامات قاعدة البيانات بشكل مباشر. تبنى الجداول تلقائيا في قاعدة البيانات من النماذج (models). جميع الأطر تملك نظام توجيه سهل وآمن، وتعرض صفحات الويب بشكل حيوي. تملك جميعها أنظمة قوالب خاصة بها وكل نظام قوالب غني بالمرشحات والدوال المعرّفة مسبقًا، الفرق الوحيد في الصياغة. جميعها مرنة ومحمولة مع تقنيات حديثة أخرى. Django يمتلك Django مكتبة قوية مع المميزات التالية: يعتبر قسم الإدارة المدمجة، المزخرف (decorator)، وأصناف المناظر نقاط قوة ل Django. الاستمارات المولدة تلقائيا للنماذج مع عملية التحقيق تجعلها سهلة للغاية. يدعم الإطار خاصية التخزين المؤقت وستتمكن من استخدام أي من أساليب التخزين المؤقت المتاحة. يدعم الأصناف البرمجيات الوسطيّة والتي يمكن أن تتدخّل في مراحل مختلفة من معالجة الطلب وتُنفّذ دوال مخصصة. يسمح لك نظام مرسل (dispatcher) داخلي لمكونات التطبيق اتصال الأحداث مع بعضها البعض عبر إشارات محددة مسبقا. يملك نظام تدويل يتضمن ترجمات لمكونات Django إلى لغات مختلفة. يملك نظام تسلسل الذي يمكنك من إنتاج وقراءة تمثيل XML و/أو JSON لمثيلات نموذج Django. واجهة بايثون مدمجة في إطار اختبار الوحدة. نظام مصادقة (authentication) موسّع. واجهة إدارة حيوية. أدوات لتوليد RSS وتغذيات (feed) خلاصات Atom. إطار مواقع تسمح ل Django واحد بتشغيل مواقع متعددة، ولكل منها المحتوى والتطبيقات الخاصة به. يملك أدوات لتوليد Google Sitemap. يملك تقنيات مدمجة للتخفيف من التزوير عبر الموقع، ثغرات XSS، ثغرات حقن SQL، تكسير كلمات المرور وهجمات الويب النموذجية، ومعظمها يعمل افتراضيا. إطار لإنشاء تطبيقات GIS. Laravel على الرغم من أن مكتبات Laravel ليست قوية مثل Django وRails إلا أنها كافية لإنشاء أي نوع من المواقع. يوفر Bundles و composer عدد من حزم نظام وحدات التحزيم والاعتماديات. التوجيه (Routing) – يوّفر طريقة سهلة وبسيطة لإدارة وتوجيه الروابط إلى متحكم أو دالة تُنفَّذ عند زيارة رابط محدَّد. دعم Eloquent ORM – خدمة أخرى مقدمة لتجريد وأتمتة جزء النموذج، حيث سنطبق التقنيات المتعارف عليها على الإعدادات. التهجيرات – طريقة لإصدار سكربتات قواعد البيانات بطريقة أنيقة للغاية، فلا حاجة للحفاظ على جميع التحققات على التهجيرات، يمكن لفريق عمل المشروع سحب الهجرة المقدمة وستعيّن جميعها وستكون جاهزة للعمل. إدارة قائمة الانتظار (Queue management) – لتجريد المهام غير الضرورية ووضعهم في قائمة الانتظار وجعل وقت استجابة المستخدم أسرع بكثير. دعم Redis، ويمكن توسيعها إلى memcached. حقن الإعتماديّة – اختبار سهل وأتمتة تحميل الإعتماديّة. Artisan – لإنشاء تطبيقات سطر الأوامر في لحظة. تعلم استخدام Laravel عن طريق هذه الدروس. Rails يتضمن Rails أدوات لجعل مهام التطوير الشائعة أسهل (خارج الصندوق)، مثل scaffolding الذي يستطيع إنشاء بعض النماذج تلقائيًا والمناظر اللازمة لموقع ويب الأساسي، بالإضافة إلى WEBrick وهو خادم ويب روبي بسيط الموزع مع روبي و Rake والذي هو نظام بناء موزع كـ gem. وتوفر هذه الأدوات جنبا إلى جنب مع Rails بيئة تطوير أساسية. Active record: يلعب دورا رئيسيا في تطبيقات Rails، وهو أفضل من Eloquent ORM في Laravel ومن النماذج في Django. اختصارات: يعبر الكثير من الناس الذين يأتون من لغات برمجة أو إطارات أخرى أن هذا الإطار سحري بسبب الاختصارات الكثيرة، فأغلب الأشياء معرّفة مسبقًا ويجب عليك كتابة بعض الأسطر البرمجية لإنشاء تطبيقات معقدة. التوجيه التلقائي: بعض الدوال الشائع في جدول قاعدة البيانات مثل الإنشاء ، التعديل والعرض مُعرّفة تلقائيًا، وهذا يعني أننا لا نحتاج إلى تضييع الوقت في المهام البسيطة ويمكننا قضاء وقت أطول على الأجزاء المعقدة من المشروع. سطر الأوامر: الكثير من الأشياء يمكن إنجازها عن طريق سطر الأوامر مثل استخدام rake وهي Ruby Make، أداة روبي مستقلة تستبدل أداة يونكس 'make' وتستخدم 'Rakefile' وملفات .rake لبناء قائمة مهام. في Rails، يُستخدم Rake لمهام الإدارة الشائعة، خاصة المعقدة منها التي تبني من بعضها البعض. تحتوي وحدة ActiveModelHelper على أساليب المساعدة لإنشاء النماذج من الكائنات بسرعة التي تتبع اتفاقيات Active Model، بداية من Active Record. خدمات الاستضافة يمكنك تشغيل أي تطبيق على VPS أو على خدمة استضافة مخصصة، وهذه مجموعة من الروابط لمواقع تسمح لك باستضافة مشروعك مجانا أو على خطط الاستضافة المشتركة. Django: بعض من المواقع التي تستضيف مشاريع Django هي: WebFaction، PythonAnywhere ، Heroku ، Digital Ocean ، Bulehost ، Dreamhost ، Arvixe و Google App Engine. Laravel: يمكنك الاستضافة على Heroku ، Bulehost ، Inmotion Hosting ، Site5 ، Dreamhost ، Digital Ocean و Arvixe. Rails: مواقع لتطبيقات Rails هي: Heroku ، Bulehost ، Dreamhost ، Arvixe ، Hosting24 و Digital Ocean. معايير أخرى كل هذه الأطر جيّدة في المستقبل، ففرص العمل، التكلفة والصيانة هي تقريبا نفسها ويمتاز Rails على Django وLaravel في شروط العمل، على الرغم من سرعة نمو Laravel. خاتمة يمكنك أن تختار أي واحدة من هذه الأطر حسب لغة البرمجة والخبرة، وإذا كنت هنا لتقرر أي واحدة يجب عليك تعلمها فأنا أفضل Rails، فعلى الرغم من صعوبة تعلمها إلا أنها مريحة أثناء إنشاء التطبيقات، إذا أردت أشياء سهلة مع الكثير من المميزات فاختر Django، فصياغة بايثون ونماذجه تجعله خيار جيدا، وعلى الرغم من أن تعلم Django قد يستغرق بعض الوقت إلا أنه ليس أصعب من Rails.إذا كانت لدي خبرة في PHP أو إذا أردت التعلم بسرعة فاختر Laravel. ترجمة -وبتصرّف- للمقال Django vs Laravel vs Rails لصاحبه Harish Kumar
  3. يظهر الخطأ 404 عندما تحاول زيارة صفحة غير موجودة في الموقع، ويميل أغلب الناس إلى ترك هذه الصفحة وعدم التفكير في تصميمها. لكن أخذ بعض الوقت وإنشاء تصميم لهذه الصفحة من الممكن أن يعطي تجربة استخدام مختلفة لزوار موقعك ويحدد قرار بقائهم في موقعك أو مغادرته في أسرع وقت. في الغالب عندما قمت بتصميم الموقع، قمت بتفقد صحة كل الروابط في الموقع حتى لا تظهر صفحة الخطأ للمستخدم لكن مع الوقت ربما تقوم بحذف منشور ما أو تغيّر اسمه. وأيضًا من الممكن أن يقوم المستخدم بزيارة الصفحة مباشرةً من دون تصفح الموقع مما سيقوده إلى صفحة الخطأ. يمكن تصميم هذه الصفحة ببساطة وسهولة بمساعدة قوالب صفحات ووردبريس الجاهزة. فهم الخطأ 404 رسالة الخطأ 404 هي عبارة عن رسالة ستظهر للزائر عند عدم وجود الصفحة التي يحاول زيارتها في الموقع. وهذه الصفحة موجودة بشكل افتراضي في ووردبريس لكن ليست موجودة في كل قوالب ووردبريس الموجودة على الإنترنت، إذا قمت بإنشاء قالب ووردبريس مخصص لموقعك، فذلك يزيد من فرصة بقاء المستخدم في موقعك حتى عندما لا يجد الصفحة التي يبحث عنها، عندما يجد صفحة 404 مبهجة وجميلة. الصفحة الافتراضية للخطأ 404 يتم تضمين صفحة الخطأ 404 مع بعض قوالب ووردبريس ولكن ليس بالضرورة كل القوالب التي تجدها على شبكة الإنترنت، مع أن ووردبريس تبحث بشكل افتراضي عن قالب الصفحة 404.php في القالب المفعّل في الموقع لكن إذا لم تجد هذا القالب سوف تظهر رسالة الخطأ الافتراضية لووردبريس والتي تعد غير ملائمة للمستخدم. إذا لم يكن قالب هذه الصفحة موجودًا، فيمكنك إنشاء قالب هذه الصفحة بسهولة. قم بإنشاء صفحة فارغة باسم 404.php. هذه هي التعليمات البرمجية التي سنبدأ بها: ملف 404.php <?php get_header(); ?> <h2>Error 404 - Page Not Found.</h2> <?php get_sidebar(); ?> <?php get_footer(); ?> التعليمات البرمجية السابقة ستقوم بإظهار مخرجات بسيطة، ضمن وسم h2. كما تستدعي أيضًا رأس الموقع (header)، الشريط الجانبي (sidebar)، وتذييل الموقع (footer) وكل هذه العناصر افتراضية ويمكنك تعديلها طبعًا لتناسب القالب الذي تقوم بتصميمه. العمل على قالب الصفحة أولًا، سنضيف مربع البحث إلى الصفحة لجعلها أكثر فائدة للمستخدم. وبهذه الطريقة، حتى إذا ظهرت هذه الصفحة لأحد الزوار، فسيكون لديه خيار البحث في موقعك بدلًا من المغادرة. ملف 404 – مع إضافة مربع البحث <?php get_header(); ?> <h2>Error 404 - Page Not Found.</h2> Search: <?php include(TEMPLATEPATH . "/searchform.php"); ?> <?php get_sidebar(); ?> <?php get_footer(); ?> جعل الصفحة أكثر ديناميكية كي نجعل صفحة 404 أكثر ديناميكية يمكننا استخدام ميزة إعادة التوجيه بحيث تظهر صفحة الخطأ للمستخدم لفترة وجيزة من الزمن ومن ثم يتم إعادة توجيه المستخدم إلى الصفحة الرئيسية للموقع. كما يمكن الاستفادة من هذه الصفحة في ارتفاع ترتيب الموقع في محركات البحث. في المثال التالي يمكننا البدء بتعديل ملف header.php من القالب الخاص بك. وإضافة ما يلي: <?php if (is_404()) { $redirectHome = get_option('home'); ?> <?php echo $redirectHome; ?> بعد إضافة هذه التعليمات، سنقوم الآن بتعديل ملف 404.php ليصبح بالشكل التالي: <?php get_header(); ?> <h1>Error 404 - File Not Found.</h1> <h3>Please <a href="<?php bloginfo('home'); ?>" Click here</a> to return to our home page, or you can wait to be redirected in 15 seconds.</h3> <?php get_footer(); ?> في المثال السابق ستظهر صفحة 404 للمستخدمين، ولكن بعد ذلك سيتم توجيههم تلقائيًا إلى الصفحة الرئيسية. بدلًا من تركهم محبطين من هذه الصفحة ومغادرتهم للموقع مع تجربة سيئة. قد لا يكون هذا المثال أفضل حل دائمًا، ولكن يمكن أن يكون مفيدًا لشخص يبحث عن شيء معين على موقعك. التأكد من عمل الصفحة يمكن التأكد أن صفحة 404 تعمل بكتابة رابط موقعك وإلحاقها بعنوان صفحة أو مقال تعرف أنه غير متواجد في موقعك. مثال: http://www.yourwebsitedomain.com/test404page.php إذا لم تعمل إذا لم يتم توجيهك إلى الصفحة هذا يعني أنه علينا تعديل ملف htaccess. على الخادم (server) كي نجعل صفحة 404 تعمل ابحث عن ملف htaccess. في تنصيب ووردبريس الخاص بك وأضف السطر التالي له: ErrorDocument 404 /index.php?error=404 لكن إذا لم يكن تنصيب الووردبريس في المجلد الجذر للخادم الخاص بك يجب الإشارة إلى المجلد الفرعي الذي نصبت عليه ووردبريس: ErrorDocument 404 /YOURSUBFOLDERNAME/index.php?error=404 هذا سيجبر الخادم على استخدام ملف 404.php مثال كامل التعليمات البرمجية أدناه تعطينا بعض الأفكار الجيدة التي يمكن استخدامها في صفحة 404 في حال لم يجد المستخدم ما يرغب في الوصول إليه، يمكنك ملاحظة هذه الخيارات التي تزيد من فرص بقائهم في الموقع، والوصول إلى ما يرغبون به. <?php get_header(); ?> <h1>404 Error</h1> We cannot seem to find what you were looking for. Maybe we can still help you. <ul> <li>You can search our site using the form provided below.</li> <li>You can visit <a href="<?php bloginfo?>"</a></li> <a href="<?php ('url'); ?>" the homepage.</a> <li>Or you can view some of our recent posts.</li> </ul> Search: TEMPLATEPATH . "/searchform.php"); ?> <h3>Recent Posts</h3> <ul> <?php query_posts('posts_per_page=5'); if (have_posts()) : while (have_posts()) : the_post(); ?> <li><a href="<?php the_permalink() ?>" title="Permalink for : <?php the_title(); ?>"><?php the_title(); ?></a> endwhile; endif; ?> </ul> <?php get_footer(); ?> يمكنك تغيير هذا المثال وتنسيقه ليناسب احتياجاتك. كل هذا المزيج من الخيارات يضمن بأن المستخدمين لن يغادروا الموقع مباشرًة، إذا لم يجدوا ما كانوا يبحثون عنه. جعل الصفحة أكثر ملائمة وبهجة للمستخدم لجعل هذه الصفحة أكثر جاذبية للمستخدم، يمكن استخدام العديد من الأفكار كوضع صور خلفية لهذه الصفحة أو كتابة تعليمات html خاصة لجعل هذه الصفحة أكثر قوة وتنوعًا وإليك بعض الأمثلة لصفحات 404 مميزة: Mundofox.com CSSRemix.com CSSRemix.com ChrisJennings.com ook.co.uk Youcastr.com Mixx.com JustCreativeDesign.com Agens.no Mushroomdigital.co.uk استخدمها بحكمة من الجيد دائمًا استخدام صفحة الخطأ 404 سواءً في ووردبريس أو في مواقع html الثابتة (static)، والاستفادة منها بوضع إعلانات مثلًا. هناك العديد من الطرق لتصميم صفحة 404 الخاصة بك، والعديد من الطرق أيضًا لمساعدة زوار الموقع في الوصول إلى ما يبحثون عنه، استخدم الأمثلة المذكورة أعلاه كما ترغب واختر ما يناسبك للوصول إلى أفضل نتيجة. ترجمة -وبتصرّف- للمقال How to Create a Custom WordPress 404 Error Page حقوق الصورة البارزة محفوظة لـ Freepik
  4. إذا كنت مهتمًا في تطوير ووردبريس فمن المؤكد أنك قمت بمحاولة تعديل قوالب ووردبريس سواء من خيارات القالب أو قمت بعمل قالب ابن من أجل تعديلات أكثر. تبعًا لتعريف موقع ووردبريس للقالب: مجموعة من الملفات التي تعمل معًا من أجل تشكيل واجهة للمستخدم. في هذا الدرس سوف نتعلم تطوير قوالب ووردبريس، سنبدأ مع الملفات الأساسية التي تشكل قالب ووردبريس وسوف نتقدم لنتعلم عن الحلقات وملفات ووردبريس الافتراضية، لتتمكن من عرض منشوراتك أو صفحات موقعك. بنهاية هذا الدرس سوف تكون قادرًا على بناء قالب ووردبريس الخاص بك. البداية إذا كنت جاهزًا و تملك نسخة ووردبريس تم تنصيبها على خادم محلي على حاسبك الشخصي، لنبدأ و نتعرف أين مكان القوالب في ووردبريس، توجد قوالب ووردبريس عادة في المسار wp-content/themes إذا ذهبت إلى هذا المسار داخل نسخة ووردبريس المثبتة على حاسبك فستجد عدة قوالب افتراضية من ووردبريس. لنقم بإنشاء قالب ووردبريس جديد. هناك بضع خطوات سهلة للقيام بذلك: أنشئ مجلد جديد في المجلد themes وأعطِه اسمًا مميزًا يشبه التالي my-awesome-theme. والآن في هذا المجلد قم بإنشاء ملفين باسم style.css و index.php الآن قم بفتح ملف style.css وانسخ التالي إليه: /* Theme Name: My Awesome Theme Theme URI: https://myawesometheme.awesome Author: Daniel Pataki Author URI: https://danielpataki.com Description: The theme for my awesome site Version: 1.0 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: my-awesome-theme This theme, like WordPress, is licensed under the GPL. Use it to make something cool, have fun, and share what you've learned with others. */ هذه التفاصيل ستظهر بشكل أوتوماتيكي في قسم تفاصيل القالب في شاشة Appearance->Themes في لوحة تحكم ووردبريس. إذا قمت بزيارة قسم Appearance->Themes سوف ترى قالبك بين القوالب المعروضة وأيضًا يمكنك تفعيله. لكن هذا القالب لا يملك أي تعليمات برمجية لذلك سترى شاشة بيضاء عند تفعيله وسنضيف التعليمات البرمجية قريبًا. كيف تعمل ملفات قوالب ووردبريس تعمل قوالب ووردبريس باستخدام صفحات ووردبريس الافتراضية. لأنها بذلك تقلل عدد الملفات التي نحتاجها لكل موقع مقارنة مع html التي تتطلب بناء صفحة مكررة كثيرة. لكن منذ ظهور php ومعالجتها للملفات على الخادم(server) يمكننا أن نوفر مساحة كبيرة في الملفات فمن الممكن أن يكون ملف واحد مسؤول عن عرض المقال المنشور أو عرض الصفحة ويمكن ل php أن تعرف ماذا نريد وبناء على ذلك تستبدل المعلومات في هذا الملف. ها هو مثال لنرى كيف يعمل ذلك: <!DOCTYPE html> <html> <head> <title>A single post template</title> </head> <body> <div id="site-header"> <h1>Welcome to my site</h1> <nav> <ul> <li><a href=''>Home</a></li> <li><a href=''>About</a></li> <li><a href=''>Contact</a></li> </ul> </nav> </div> <div id="article"> <h2 class="article-title"><?php the_title() ?></h2> <div class="article-content"><?php the_content() ?></div> <div class="article-meta">Published on <?php the_time( "Y-m-d" ) ?> by <?php the_author() ?></div> </div> <div id="site-footer"> <nav> <ul> <li><a href=''>Home</a></li> <li><a href=''>About</a></li> <li><a href=''>Contact</a></li> </ul> </nav> <div id="copyright">&copy; Daniel Pataki</div> </div> </body> </html> لاحظ أنك لا ترى محتوى ثابت مكتوب في هذه الملف، بدلًا من أن ترى عنوان المقال سترى دالة ()the_title و هي مسؤولة عن إخراج نص العنوان. هذه الدالة تحدد أي مقال تم طلبه حاليًا من خلال رابط الصفحة وتجلب المعلومات المناسبة من قاعدة البيانات لعرضها. وبذلك قمنا بعمل ملف لأي مقال في الموقع، وتأخذ ووردبريس هذه المرحلة إلى مستوى آخر وتقوم بفصل رأس وتذييل الموقع ووضعها في ملفات منفصلة واستدعائها عندما نريدها وليست نسخ رأس وتذييل الموقع كل مرة نحتاجهم فيها: <?php get_header() ?> <div id="article"> <h2 class="article-title"><?php the_title() ?></h2> <div class="article-content"><?php the_content() ?></div> <div class="article-meta">Published on <?php the_time( "Y-m-d" ) ?> by <?php the_author() ?></div> </div> <?php get_sidebar() ?> <?php get_footer() ?> كيف تعمل قوالب ووردبريس سوف نستعمل مجموعة من ملفات قالب ووردبريس في قالبنا الذي نقوم بصنعه، ما نحتاج لمعرفته هو أسماء الملفات التي تلزمنا لعمل الصفحات الأساسية للموقع وأسماء هذه الملفات محددة في وردبريس من التسلسل الهرمي لملفات قوالب ووردبريس. لنلقي نظرة على أنواع الصفحات التي نحتاجها: الصفحات الأرشيفية مثل (التصنيفات، الوسوم، أرشيفات الوسوم، الناشرين في الموقع) الصفحات الواحدة (المقال الواحد، الصفحة الواحدة، نوع المقال) الصفحة الرئيسية وصفحة كل المقالات صفحة الخطأ صفحة نتائج البحث تسمى هرمية لأن ووردبريس تبحث عن مجموعة من الملفات وتعرض الذي له هرمية أعلى. لنأخذ مثلًا صفحة المؤلف أولاً ووردبريس تبحث عن صفحة باسم هذه المؤلف إذا وجدتها سوف تقوم باستخدامها، لكن إن لم تجدها سوف تقوم بالبحث عن ملف برقم المستخدم وإذا لم تجدها ستتابع البحث عن ملف باسم author.php وإن لم تجده ايضًا ستبحث عن achive.php وإذا فشلت كل المحاولات السابقة سوف تعرض سوف تستخدم ملف index.php والذي هو حتمًا موجود لأنه مطلوب لإنشاء القالب. لاحظ أن ووردبريس تبدأ مع الملفات الخاصة ثم تقوم بالتعميم. وهذا أفضل لأنه يمكنك إنشاء ملف واحد من أجل أن يقوم باستخدامه لعرض المستخدم وهو author.php ولكن ربما تريد عمل ملف خاص لأحد المستخدمين وبذلك يمكنك استخدام اسم المستخدم مثال author-danielpataki.php. لنقم ببناء قالب عند بناء قالب جديد، فمن الأفضل بناء الأساسيات التي سأحتاجها في كل الصفحات. مثل أقسام رأس الموقع(header) وتذييل الموقع(footer). يجب أن يكون ما زال لديك ملفي index.php و style.css اللذان قمنا بإنشائهما، لذا لتبدأ. بناء الأساسيات عادة أقوم بعمل صورة للقالب كي يتم عرضه في لوحة تحكم ووردبريس في تفاصيل القالب. هذ ليس مطلوبًا بشدة عند بناء قالب لكنه يعطيني انطلاقة جيدة وإلهام لما سيكون عليه القالب إذا كان لديك صورة للتصميم فمن الأفضل أن تضعها، أو يمكنك الاستعانة بموقع Unsplash. عندما تحصل على صورة تعجبك، قم بقصها لتصبح بعرض 880px وبطول 660px، قم بتسميتها screenshot.png وضعها في مجلد القالب إذا أردت صورة بسرعة فيمكنك الاستعانة بهذه الصورة التي قم بعملها وتنزيلها من هنا. الخطوة القادمة هي كتابة تعليمات html الأساسية التي ستظهر في كل الصفحات مثل عنصر . لنبدأ بإنشاء ملف header.php داخل هذا الملف سنقوم بلصق تعليمات html كالتالي: <!DOCTYPE html> <html <?php language_attributes(); ?> class="no-js"> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="profile" href="http://gmpg.org/xfn/11"> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> الآن سنقوم بإنشاء ملف footer.php الذي سيحتوي وسوم الإغلاق للوسوم المفتوحة في ملف header.php : <?php wp_footer() ?> </body> </html> يجب أن أشير إلى دالتين هامتين و هما ()wp_head و ()wp_footer . عندما تقوم بإنشاء أي قالب يجب وضع ()wp_head مباشرة قبل إغلاق وسم <head> و دالة ()wp_footer مباشرة قبل إغلاق وسم <body> لأن هذا يساعد ووردبريس و الإضافات التي تنصبها على موقعك بوضع روابط ملفاتهم الخاصة هنا. الآن لنعد إلى ملف index.php إذا قمت بزيارة موقعك فستجد صفحة فارغة. هذا لأن ملف index.php فارغ ولم تقم باستعمال ملفات header.php و footer.php بعد. قم بإضافة التعليمات التالية إلى ملف index.php: <?php get_header() ?> My Awesome Theme <?php get_footer() ?> إذا زرت الصفحة مجددًا فيجب أن ترى عبارة "My Awesome Theme" وإذا اطلعت على الشيفرة المصدرية للصفحة فستجد الكثير من الأشياء هناك وليس عليك القلق بشأنها في الوقت الحالي. والآن من المؤكد بأنك ترغب بإضافة تنسيقات بما أن ملف style.css لا يتم استدعائه بشكل تلقائي، وربما تفكر بإضافة ملف style.css كما كنت تفعل عندما تصميم مواقع html ولكن في ورردبريس لا يجب عليك فعل ذلك أبدًا دع هذا الأمر لووردبريس. أنشئ ملف functions.php وأضف التعليمات التالية: <?php add_action( 'wp_enqueue_scripts', 'mat_assets' ); function mat_assets() { wp_enqueue_style( 'my-awesome-theme', get_stylesheet_uri() ); } التعليمات في ملف functions.php تخبر ووردبريس عن ملفات css الخاصة بك و بعدها تقوم ووردبريس باستدعاء ملفات في مكان وضعك لدالة ()wp_head و هذه هي وظيفة دالة ()wp_head أن تستدعي ملفاتك و بعض ملفات ووردبريس في رأس الموقع. الآن يمكنك تجربة وضع بعض التعليمات في ملف style.css ورؤية النتيجة مثل: body {background:red} قبل المتابعة لنضف بعض التعليمات البسيطة إلى ملفاتنا لتصبح أفضل وأجمل: في ملف header.php: <!DOCTYPE html> <html <?php language_attributes(); ?> class="no-js"> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="profile" href="http://gmpg.org/xfn/11"> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <div id="site-header"> <h1><?php bloginfo('title') ?></h1> </div> <div id='site-content'> في ملف footer.php: </div> <!-- site content --> <div id='site-footer'> <p>&copy; My Awesome Theme</p> </div> <?php wp_footer() ?> </body> </html> في ملف style.css: /* Theme Name: My Awesome Theme Theme URI: https://myawesometheme.awesome Author: Daniel Pataki Author URI: https://danielpataki.com Description: The theme for my awesome site Version: 1.0 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Text Domain: my-awesome-theme This theme, like WordPress, is licensed under the GPL. Use it to make something cool, have fun, and share what you've learned with others. */ html { height: 100%; background:#444; font-family: "Helvetica Neue", Arial, sans-serif; line-height: 1.5em; } #site-header { text-align: center; } #site-header h1 { font-size:32px; color: #ffffff; font-weight: 300; letter-spacing: 1px; } #site-content { max-width:625px; background: #fff; margin: 0 auto; padding: 22px; border-radius:5px; } #site-footer { color: #fff; text-align:center; font-size:12px; text-transform: uppercase; } الآن كل صفحة ستقوم بزيارتها في موقع ستبدو نفسها لأننا فقط نملك index.php والذي سترجع إليه ووردبريس عند عدم وجود أي صفحات. فهم حلقة ووردبريس الحلقة هي أساس عمل كل الصفحات في ووردبريس. لأن الحلقة تحوي المعلومات التي ستعرض على الصفحة. ووردبريس تعرف ماذا يجب أن تحتوي كل صفحة، وتعرف هذه من روابط الصفحات مثلًا صفحة المقال الواحد يجب أن تحتوي مقال واحد وصفحتك الرئيسية يجب أن تحتوي أحدث 10 مقالات وهذا كله تعرفه ووردبريس. هذه المعلومات يتم جلبها من قاعدة البيانات بشكل أوتوماتيكي وكل ما عليك القيام به هو تفعيل الحلقة من أجل عرض البيانات من الأفضل شرح هذا بمثال أضف هذه التعليمات إلى ملف index.php: <?php if( have_posts() ) : ?> <?php while( have_posts() ) : the_post() ?> <h2><a href='<?php the_permalink() ?>'><?php the_title() ?></a></h2> <div class="content"> <?php the_content() ?> </div> <?php endwhile ?> <?php else : ?> <p>Oh No, there are no posts!</p> <?php endif ?> عندما تنسخ هذه التعليمات وتزور صفحتك الرئيسية ستكتشف قوة ووردبريس وسحر قوالبها، سوف ترى قائمة مقالاتك التي قمت بإضافتها في لوحة تحكم ووردبريس. إذا قمت بالضغط على عنوان المقال سوف تذهب إلى صفحة تعرض لك هذا المقال بالرغم من أنك لم تقم بعمل صفحة للمقال الواحد. لنحلل التعليمات البرمجية ونرى كيف تعمل. كل هذا يبدأ مع عبارة if التي تتحقق من قيمة دالة have_posts(). هذه الدالة ستعيد قيمة true إذا كان هناك مقالات وقيمة false إذا لم يكن هناك مقالات لعرضها. كما ترى من عبارة else إذا لم يكن هناك مقالات فإننا نعرض رسالة للمستخدم بأنه ليس هناك مقالات. إذا كان هناك مقالات فإننا ننشئ حلقة while والتي لن تتوقف عن تنفيذ التعليمات التي بداخلها ما دامت دالة ()have_posts ترجع قيمة true. الدالة الأولى التي نستخدمها هي دالة ()the_post والتي تقوم بإعداد بعض البيانات لنا وتكمل الحلقة بعد ذلك، إذا كنا قد وصلنا للمقال الأخير هذا يعني أن دالة have_posts() ستعيد لنا false في المرة القادمة وبذلك تتوقف الحلقة و يتم تنفيذ التعليمات البرمجية التالية إذا كان هناك تعليمات باقية. عند عرض المقال، قمت بإضافة العنوان والمحتوى الكامل للمقال. لقد قمت باستخدام دالة ()the_permalink للحصول على رابط المقال، دالة ()the_title لعرض العنوان ودالة ()the_content لعرض محتوى المقال كاملًا. هذه الدوال تستخدم داخل حلقات ووردبريس وسوف تحدد المقال المطلوب كما هو متوقع. هكذا يبدو موقعي الآن: من الآن وصاعدًا عرض المقال بطرق مختلفة هي مسألة معرفة الدوال التي تستخدمها ووردبريس وإضافة بعض تعليمات CSS لجعل قالبك رائع، إليك بعض الدوال المفيدة التي تساعدك في عرض التصنيفات، الوسوم، تاريخ المقالات وأكثر من ذلك. القوالب وعبارة if ماذا تفعل إذا أردت عرض مقتطف من المقالات في الصفحة الرئيسية وكامل المقال في حال عرض المقال الواحد؟ في هذه الحالة لديك خيارين استخدام الدوال الشرطية التي توفرها ووردبريس أو عمل ملف قالب جديد. الدوال الشرطية التي توفرها ووردبريس تستخدم للتحقق من أشياء عديدة، على سبيل المثال إذا أردت معرفة إذا كنت تعرض مقال واحد أو عدة مقالات، إليك اللائحة الكاملة لهذه الدوال على موقع ووردبريس بمساعدة دالة ()is_singular يمكننا فعل التالي: <?php get_header() ?> <?php if( have_posts() ) : ?> <?php while( have_posts() ) : the_post() ?> <h2><a href='<?php the_permalink() ?>'><?php the_title() ?></a></h2> <div class="content"> <?php if( is_singular() ) : ?> <?php the_content() ?> <?php else : ?> <?php the_excerpt() ?> <?php endif ?> </div> <?php endwhile ?> <?php else : ?> <p>Oh No, there are no posts!</p> <?php endif ?> <?php get_footer() ?> الحل الآخر هو استخدام ملفين منفصلين index.php لعرض مقتطفات من المقالات وملف single.php لعرض المقال كاملًا. من المؤكد أنك تسأل أي طريقة هي الأفضل؟ ليس هناك إجابة واضحة لهذا السؤال لأنه يعتمد بالدرجة الأولى على ما تريد إنجازه. في الواقع، عرض جميع المقالات وعرض المقالة الواحدة مختلف بما يكفي لعمل ملفين منفصلين، ولكن هناك بعض القوالب التي تطبق الطريقتين. وبعض القوالب تذهب أبعد من ذلك وتقوم بإنشاء ملف خاص بالحلقة فقط. لأن هذا سيجعل التعليمات نفسها تستخدم من قبل جميع الصفحات بدلًا من نسخ الحلقة في كل مكان نريد تواجد الحلقة فيه. لنلقي نظرة على ملف index.php المعدل: <?php get_header() ?> <?php if( have_posts() ) { while( have_posts() ) { the_post(); get_template_part( 'template-parts/content', '' ); } } else { get_template_part( 'template-parts/content', 'none' ); } ?> <?php get_footer() ?> قمت بوضع كل محتوى المقال في ملف مختلف. دالة ()get_template_part تجلب المحتوى من ملف وتجمع الوسيط الثاني مع الأول بإضافة “-” للمسار. في حالة الاستدعاء الثاني داخل عبارة else الدالة ستحاول استدعاء ملف template-parts/content-none.php، في الاستدعاء الأول لهذه الدالة تركت الوسيط الثاني فارغًا وهذا سيستدعي template-parts/content.php. في ملف single.php، سأضيف نفس التعليمات ولكن سأضيف كلمة single للوسيط الثاني من دالة ()get_template_part . أخيرًا لنقم بعمل مجلد template-parts وبداخله 3 ملفات: content.php و content-single.php وcontent.php وأقوم بنسخ تعليمات الحلقة المناسبة لكل ملف على سبيل المثال ملف content.php سيبدو كالتالي: <h2><a href='<?php the_permalink() ?>'><?php the_title() ?></a></h2> <div class="content"> <?php the_excerpt() ?> </div> غطينا في هذا الدرس ما يكفي لعمل قالب بسيط، وهذا سيمكّنك من عرض مقالاتك بالطريقة التي تعجبك بتنسيقاتك الخاصة. ترجمة -وبتصرّف- للمقال WordPress Development for Beginners: Building Themes لصاحبه Daniel Pataki
  5. ما هي JSON؟ كلمة JSON و تلفظ جيسون هي اختصار ل JavaScript Object Notation. سميت بهذا الاسم لأن لغة جافا سكربت(javascript) كانت أول لغة تستفيد من هذه الصيغة. JSON هي طريقة لتخزين المصفوفات (arrays) و الكائنات (objects) بقيم نصية (string)، و تستخدم بشكل أساسي في نقل البيانات وأقل عرضة للخطر و أسهل من طرق أخرى كطريقة xml. تستخدم عادةً عندما يطلب جزء من تطبيق الويب بعض المعلومات من الخادم (server) من دون إعادة تحميل الصفحة. عادة تتم هذه العملية عن طريق جافا سكربت وطلبات AJAX. منذ النسخة 5.2.0، لغة PHP أصبحت قادرة على تحويل الكائنات والمصفوفات إلى JSON. وقد كانت إضافة رائعة لهذه اللغة. إذا كنت تعمل مع PHP لفترة من الزمن ففي الغالب أنك قمت باستعمال دالة ()serialize لعرض كائنات PHP كنصوص، و تستخدم لتحويل كائنات PHP إلى نصوص، و يمكنك فيما بعد استخدام دالة ()unserialize لتحويل هذا النص إلى الحالة السابقة بالقيم الأصلية. وليس فقط لغة PHP التي يمكن أن تتعامل مع JSON بل معظم لغات البرمجة يمكنها التعامل مع JSON وتحويل بياناتها إلى JSON. صيغة JSON {"name":"Lushui","species":"Panda","diet":"Green Things","age":7,"colours":["red","brown","white"]} افتراضيًا يتم تخزين JSON بلا أي فراغات (white space) مما يجعل قراءة JSON صعبة قليلًا، من أجل توفير الذاكرة عند نقل البيانات، لكن يمكنك أن تضع مهما كان من فراغات أو أسطر لجعلها مقروءة بالنسبة لك. لكن هل من المعقول أن نقوم بوضع فراغات في هذ الملف يدويًا إذا كان لدينا العديد من الأسطر، هناك العديد من الأدوات التي تتوفر على الإنترنت التي تقوم بتجميل ملف JSON ليصبح أكثر قابلية للقراءة. لنقم بإضافة بعض الفراغات: { "name": "Lushui", "species": "Panda", "diet": "Green Things", "age": 7, "colours": ["red", "brown", "white"] } كما ترى في هذا المثال أنه لدينا عدد من المفاتيح والقيم. كل مفتاح يجب أن تكون له قيمة مقابلة، إذا كنت قد تعاملت مع جافا سكربت من قبل فسوف ترى أن JSON لا تختلف كثيرًا عن جافا سكربت. var lushui = { name: 'Lushui', species: 'Panda', diet: 'Green Things', age: 7, colours: ['red', 'brown', 'white'] }; في جافا سكربت يتم تعيين هذا الكائن لمتغير كالتالي: var lushui = { .. }; لكن JSON هي صيغة لنقل البيانات، وليست لغة برمجة، لا تملك أي مفاهيم برمجية لذلك لا نحتاج إلى المتغيرات أو ما شابه في JSON. في جافا سكربت وفي JSON الكائنات يتم احتوائها داخل { } وكل مفتاح له قيمة، في جافا سكربت المفاتيح لا تتطلب وضعها بين إشارتي " " لأنها تمثل متغيرات. في جافا سكربت و JSON المفتاح و قيمته يفصل بينهما بـ ":" و كل مفتاح و قيمته مفصولان عن المفاتيح و القيم الآخرى بـ "," . JSON تدعم أنواع القيم التالية: Double Float String Boolean Array Object Null القيم العددية تمثل بلا إشارتي " " ، القيم المنطقية تمثل بـ true أو false و بلا إشارتي " " كما PHP ، و يجب التشديد مرة أخرى أن النصوص تمثل بإشارتي " " . القيمة null تعمل كعملها في php وتمثل في JSON بوضع الكلمة فقط غير محاطة بأي شيء. المصفوفات في JSON وجافا سكربت هي نفسها. // JavaScript ['red', 'brown', 'white'] ["red", "brown", "white"] لاحظ أنني لم أضع تعليق قبل المصفوفة الثانية، لأن JSON لا تدعم التعليق بسبب أنها تستخدم لنقل البيانات وليس هناك حاجة للتعليق لأنك لا تكتب أوامر برمجية لأنك لو عدت لملف JSON لاحقًا فكل ما فيه بيانات سوف تعرفها عند قراءتها مباشرةً. JSON تدعم المصفوفات و الكائنات المتداخلة. { "an_object": { "an_array_of_objects": [ { "The": "secret" }, { "is": "that" }, { "I": "still" }, { "love": "shoes!" } ] } } لدينا في المثال السابق كائن JSON يحتوي كائن آخر يحتوي مصفوفة من الكائنات. JSON و PHP كما ذكرت سابقًا، منذ النسخة 5.2.0 وفرت الدعم لتحويل البيانات إلى JSON والآن سوف نلقي نظرة على هذه الميزة في PHP عن قرب. لتحويل قيمة في PHP إلى JSON فقط نحتاج إلى دالة ()json_encode كما التالي: <?php $truth = array('panda' => 'Awesome!'); echo json_encode($truth); نتيجة تنفيذ التعليمات السابقة. {"panda":"Awesome!"} رائع هذا بالضبط ما كما نريده، لنقم الآن بتحويل هذه البيانات إلى مرة آخرى إلى صيغة مفهومة من قبل PHP. <?php $truth = json_decode('{"panda":"Awesome!"}'); echo $truth['panda']; لنلقي نظرة على النتيجة؟ Fatal error: Cannot use object of type stdClass as array in ... كما ترى، دالة ()json_decode لا تتحول إلى مصفوفة PHP. بدلًا من ذلك تستخدم كائن stdClass لتمثيل بياناتنا، لنصل إلى بياناتنا بشكل صحيح سندخل إلى خصائص هذا الكائن بهذه الطريقة. <?php $truth = json_decode('{"panda":"Awesome!"}'); echo $truth->panda; // Awesome! لكن إذا ما زلت ترغب في الحصول على هذه البيانات كمصفوفة فقط أضف وسيط آخر إلى هذه الدالة وهو true. <?php $truth = json_decode('{"panda":"Awesome!"}', true); echo $truth['panda']; // Awesome! ترجمة –وبتصرّف- للمقال Laravel 4 Primer: JSON لصاحبه Dayle Rees
  6. Lighttpd هو خادوم ويب خفيف مفتوح المصدر، وهو الأمثل للبيئات عالية السرعة مع الحفاظ على استخدام أقل للموارد. وهو بديل ممتاز لخوادم الويب شائعة الاستخدام Nginx و Apache. في هذا المقال سيتم تثبيت وإعداد Lighttpd على خادوم يعمل بنظام FreeBSD 11.0. يمكنك أيضا إضافة MySQL و PHP إلى خادوم الويب Lighttpd الجديد الخاص بك حتى تتمكن من تشغيل خدمات الويب فضلا عن محتويات ثابتة. المتطلبات الأساسية لإكمال هذا البرنامج التعليمي ستحتاج إلى: خادوم بنظام تشغيل FreeBSD 11.0. حساب مستخدم تم إعداده لتشغيل الأوامر مع sudo . إن حساب freebsd الافتراضي الذي يأتي مع Digital Ocean FreeBSD Droplet كاف لهذا البرنامج التعليمي. لمعرفة المزيد حول إعداد FreeBSD اقرأ سلسلة المقالات حول FreeBSD. الخطوة 1 - تثبيت Lighttpd هناك عدة خيارات لتثبيت Lighttpd، ولكن في هذا الدرس سوف نستخدم حزم التثبيت. هذه الطريقة أسرع من التثبيت من المصدر أو عبر المنافذ (Ports)، والبرمجيات المثبتة مع هذه الطريقة أسهل تحديثًا. لتثبيت Lighttpd مع الحزمة الخاصة به، أولًا حدّث معلومات المستودع للتأكد من أن لديك أحدث قائمة من الحزم المتاحة: sudo pkg update بعد ذلك حمّل وثبت الحزمة lighttpd: sudo pkg install lighttpd أكّد التثبيت عن طريق كتابة y . سيتم تثبيت Lighttpd. باستخدام هذا الإعداد الافتراضي سيظهر لك هذا الخطأ عند بدء تشغيل الخادوم: (network.c.260) warning: please use server.use-ipv6 only for hostnames, not without server.bind / empty address; your config will break if the kernel default for IPV6_V6ONLY changes وذلك لأن إعدادات Lighttpd الافتراضية لم يتم تهيئتها لدعم IPv6. لتجنب المفاجآت في وقت لاحق حرر ملف إعدادات Lighttpd ثم عطل دعم IPv6، لأنك لن تحتاج إليها لإكمال هذا الدرس. يمكنك تمكينه في المستقبل إذا قررت استخدامه: sudo ee /usr/local/etc/lighttpd/lighttpd.conf ابحث عن هذا الجزء: ... ## ## Use IPv6? ## server.use-ipv6 = "enable" ... وغير enable إلى disable ... ... server.use-ipv6 = "disable" ... بعد ذلك حدد موقع هذا السطر في نهاية ملف الإعداد: ... ... $SERVER["socket"] == "0.0.0.0:80" { } ألغه بإضافة الرمز # في أوله، لأنه لا لزوم له إذ كنا لا نستخدم IPv6: #$SERVER["socket"] == "0.0.0.0:80" { } ثم احفظ الملف وأغلق المحرر. بعد هذا سوف نقوم بإعداد MySQL الخطوة 2 - تركيب وإعداد MySQL MySQL هو نظام إدارة قواعد بيانات من شأنها أن تسمح بإنشاء قواعد بيانات لتطبيقات PHP التي تخطط لاستضافتها على خادوم الويب الخاص بك Lighttpd. سوف تقوم بتثبيت MySQL عبر الحزم، تماما كما فعلت مع Lighttpd. ثم عليك إعداد كلمة مرور للمستخدم الجذر MySQL وتعطيل بعض خيارات الاختبار الأخرى. وهذا يضمن أنه سيكون لديك إعداد آمن لــ MySQL. بما أنك قمت بتحديث معلومات مستودع pkg في الخطوة 1، يمكنك الآن تحميل وتثبيت حزمة خادوم MySQL بسرعة: sudo pkg install mysql57-server أكد التثبيت عن طريق الضغط على: y. بعد اكتمال التثبيت، مكّن MySQL لكي يبدأ عند تشغيل النظام: sudo sysrc mysql_enable=yes ثم شغل خدمة mysql-server : sudo service mysql-server start بعد بدء تشغيل الخدمة أمّن تثبيت MySQL باستخدام السكريبت mysql_secure_installation . سيؤدي هذا إلى إزالة بعض الإعدادات الافتراضية الخطرة وإغلاق الوصول إلى نظام قاعدة البيانات قليلا. شغل السكريبت بالأمر: sudo mysql_secure_installation سترى الرسالة التالية: Securing the MySQL server deployment. Connecting to MySQL server using password in '/root/.mysql_secret' بعد ذلك سيتم سؤالك عما إذا كنت تريد إعداد إضافة للتحقق من صحة كلمات المرور: VALIDATE PASSWORD PLUGIN can be used to test passwords and improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD plugin? تحذير: تمكين هذه الميزة لهو شيء من الحكمة. إذا تم التمكين فسيتم رفض كلمات المرور التي لا تتطابق مع المعايير المحددة من قبل MySQL مع إظهار رسالة خطأ. وهذا سوف يسبب مشاكل إذا كنت تستخدم كلمة مرور ضعيفة أو كان لك برنامج يقوم تلقائيا بإعداد بيانات اعتماد مستخدم MySQL. لذلك يعد من الآمن أن تترك التحقق معطلًا، ولكن يجب عليك دائمًا استخدام كلمات مرور قوية وفريدة من نوعها لبيانات اعتماد قاعدة البيانات. أجب بنعم أو أيّ شيء آخر للمتابعة دون تمكين. إذا اخترت تمكين هذه الميزة فسيطلب منك تحديد مستوى التحقق من صحة كلمة المرور. ضع في اعتبارك أنه إذا قمت بإدخال 2 –وهو أقوى مستوى- فسوف تتلقى أخطاء عند محاولة تعيين أي كلمة المرور لا تحتوي على أرقام وحروف كبيرة وصغيرة ورموزا خاصة أو أي كلمة المرور هي موجودة في قواميس كلمات السر الشائعة. There are three levels of password validation policy: LOW Length >= 8 MEDIUM Length >= 8, numeric, mixed case, and special characters STRONG Length >= 8, numeric, mixed case, special characters and dictionary file Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: بعد ذلك سيتم سؤالك عما إذا كنت ترغب في تغيير كلمة المرور للمستخدم الجذر: Change the password for root ? ((Press y|Y for Yes, any other key for No): اضغط على Y لتغيير كلمة المرور هذه. إذا مكنت التحقق من صحة كلمة المرور فستظهر لك قوة كلمة المرور للجذر الحالية، وستسأل إذا كنت تريد تغيير كلمة المرور هذه. New password: Re-enter new password: Estimated strength of the password: 100 Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No): اضغط Y للمتابعة مع كلمة المرور الجديدة. بالنسبة لبقية الأسئلة اضغط على Y ثم على مفتاح الإدخال في كل مرة. سيؤدي ذلك إلى إزالة بعض المستخدمين المجهولين وقاعدة بيانات الاختبار وتعطيل تسجيلات الجذر عن بعد وتحميل هذه القواعد الجديدة بحيث تجعل MySQL يعمل بالتغييرات التي أجريناها فورا. ثم قم بإعادة تشغيل خدمة mysql-server للتأكد من أن المثيل (Instance) الخاص بك نفَّذ على الفور التغييرات الأمنية: sudo service mysql-server restart بعد تثبيت وتشغيل MySQL يمكننا تثبيت وإعداد PHP. الخطوة 3 - تثبيت وإعداد PHP PHP هو المكون الذي يتكفل بعرض المحتوى الديناميكي. فإنه يمكنه أن يشغل السكريبتات، والاتصال بقواعد بيانات MySQL للحصول على المعلومات، وتسليم المحتوى إلى خادوم الويب لمعالجته ثم عرضه. مرة أخرى استخدم نظام الحزم لتثبيت PHP مع إضافة PHP المسماة mysqli لكي تضيف دعما MySQL: sudo pkg install php71 php71-mysqli Lighttpd لا يحتوي على معالجة للــ PHP مثل بعض خوادم الويب الأخرى، لذلك سوف نستخدم PHP-FPM الذي سيعمل في ” إدارة عمليات FastCGI “. سنقوم بإعداد Lighttpd لاستخدام هذه الوحدة لمعالجة طلبات PHP. قبل أن نفعل ذلك نحن بحاجة إلى إعداد PHP-FPM نفسها. ابدأ بتعديل ملف إعدادات PHP-FPM: sudo ee /usr/local/etc/php-fpm.d/www.conf سنقوم بإعداد PHP-FPM لاستخدام مقبس (socket) يونكس بدلا من منفذ شبكة للاتصال. هذا أكثر أمنا لخدمات التواصل داخل خادوم واحد. ابحث عن هذا السطر في ملف التهيئة: /usr/local/etc/php-fpm.d/www.conf listen = 127.0.0.1:9000 غيّر هذا السطر لكي يستخدم مقبس php-fpm : listen = /var/run/php-fpm.sock الآن عيّن المالك والمجموعة والأذونات للمقبس الذي سيتم إنشاؤه. ابحث عن هذا الجزء من ملف الإعداد: ... ;listen.owner = www ;listen.group = www ;listen.mode = 0660 ... قم بإلغاء علامة التعليق من أول السطر (;) بحيث يبدو كالتالي: ... listen.owner = www listen.group = www listen.mode = 0660 ... احفظ الملف وأغلقه بعد الانتهاء. بعد ذلك قم بإنشاء ملف php.ini ، هذا الملف سيقوم بإعداد السلوك العام لـ PHP. هناك نوعان من نماذج الملفات: php.ini-production و php.ini-development . سيكون php.ini-production أقرب إلى ما تريده لخادومك، لذا انسخه إلى المسار : /usr/local/etc/ وهو الموضع الذي تتوقع PHP العثور عليه في إعداداتها: sudo cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini افتح الملف php.ini الجديد باستخدام محرر النصوص: sudo ee /usr/local/etc/php.ini داخل ملف الإعداد حدّد موقع الجزء الخاص بسلوك cgi.fix_pathinfo . ستراه مَلغِيّا ومعينا إلى القيمة 1 افتراضيا: ... ;cgi.fix_pathinfo=1 ... قم بإزالة الفاصلة المنقوطة لتمكين السطر وتعيين القيمة إلى 0. هذا سيمنع PHP من محاولة تنفيذ أجزاء من المسار إذا لم يتم العثور على الملف الذي تم تمريره إلى العملية. هذا يمكن أن يستخدم من قبل المهاجم لتنفيذ الشيفرات الخبيثة. ... cgi.fix_pathinfo=0 ... احفظ الملف وأغلق المحرر. ثم مكّن خدمة php-fpm لتبدأ مع بدء تشغيل النظام: sudo sysrc php_fpm_enable=yes ثم شغّل الخدمة: sudo service php-fpm start بعد ذلك لنقم بإعداد Lighttpd لمعالجة تطبيقات PHP. الخطوة 4 - إعداد Lighttpd لخدمة تطبيقات PHP في هذه الخطوة سوف نقوم بإعداد Lighttpd لاستخدام FastCGI و PHP-FPM. هذا سيمكّن الــ PHP على Lighttpd ويقدم دعما من PHP سريعا وفعّالا. أولاً مكّن وحدة FastCGI. افتح ملف إعداد وحدات Lighttpd: sudo ee /usr/local/etc/lighttpd/modules.conf حدد موقع القسم التالي: ... ## ## FastCGI (mod_fastcgi) ## #include "conf.d/fastcgi.conf" ... أزل الإلغاء عن طريق إزالة الرمز # . إذا لم تجد هذا السطر، فأضفه إلى نهاية الملف، سيصبح هكذا: ... ## ## FastCGI (mod_fastcgi) ## include "conf.d/fastcgi.conf" ... احفظ الملف وأغلق المحرر. بعد ذلك قم بتحرير ملف إعداد FastCGI: sudo ee /usr/local/etc/lighttpd/conf.d/fastcgi.conf يحتوي هذا الملف على عدة أمثلة ملغاة. أضف أسطر الإعداد التالية إلى نهاية الملف الذي سيقوم بإعداد Lighttpd لمعالجة ملفات PHP مع FastCGI و PHP-FPM: .. fastcgi.server += ( ".php" => (( "socket" => "/var/run/php-fpm.sock", "broken-scriptfilename" => "enable" )) )... بعد ذلك مكّن Lighttpd لكي يشتغل مع بداية تشغيل النظام. بهذه الطريقة سوف تبدأ Lighttpd تلقائيا كلما تم إعادة تشغيل خادوم الويب: sudo sysrc lighttpd_enable=yes ثم شغّل خدمة lighttpd : sudo service lighttpd start الآن بعد أن صار PHP على استعداد للاشتغال، دعونا نتأكد من أن كل شيء يعمل. الخطوة 5 - اختبار إعداد الخادوم لاختبار Lighttpd المعدّ حديثا أنشئ أولا المجلد /usr/local/www/data، هذا المجلد هو الذي سيبحث فيه Lighttpd عن صفحات الويب. sudo ee /usr/local/www/data/info.php ثم أنشئ info.php في المجلد /usr/local/www/data/ . سيختبر هذا الملف أن PHP يعمل ويتيح لك مراجعة المعلومات حول إعداد خادوم الويب في متصفح الويب: sudo ee /usr/local/www/data/info.php أضف هذا الكود إلى الملف: <?php phpinfo(); ?> احفظ الملف وأغلق المحرر. قم بزيارة الرابط http://your_server_ip/info.php من متصفحك سوف ترى مظهر الصفحة مثل هذا: تعرض هذه الصفحة معلومات حول نظام التشغيل وخادوم الويب وكيفية معالجة خادوم الويب لملفات PHP. كما تتحقق من أن خادوم الويب الخاص بك يمكنه أن يعالج ملفات PHP بشكل صحيح. إذا لم تشاهد هذه الصفحة ، وبدلا من ذلك شاهدت ” Error 503 Service Not Available ” فتأكد من أن خدمة php-fpm اشتغلت بشكل صحيح في الخطوة السابقة. بعد التحقق من أن الأمور تعمل قم بإزالة الصفحة info.php إذ أنها تعرض معلومات حول الخادوم الخاص بك يجب أن تبقى خاصة: sudo rm /usr/local/www/data/info.php تم الآن إعداد خادوم الويب بالكامل وهو على استعداد للعمل. ما عليك الآن سوى أن تضع ملفاتك في /usr/local/www/data لكي تتم معالجتها. الخلاصة الآن بعد أن صار خادوم الويب Lighttpd في الخدمة يمكنك استضافة صفحات الويب والمستندات والملفات الأخرى عليه. لجعل خادوم الويب أكثر أمانا من خلال إضافة إعدادات SSL وغيرها من ميزات الأمان ولمزيد من المعلومات حول Lighttpd قم بزيارة منتديات Lighttpd . ترجمة -وبتصرّف- للمقال How to Install Lighttpd with MySQL and PHP on FreeBSD 11.0 لصاحبه Brian Hogan
  7. إذا أردت أن تصبح مطوّر ووردبريس فهذا يتطلب أيضًا تعلم لغة البرمجة الشهيرة PHP، والتي بنيت من خلالها منصة ووردبريس. طورت بشكل أساسي في عام 1994، PHP لغة برمجة قوية ومفتوحة المصدر لإنشاء مواقع ويب ديناميكية وتفاعلية. سوف تتعلم القواعد الأساسية للغة PHP وكيفية كتابتها، وكيفية عملها، والاطلاع على بعض الأمثلة. ما هي PHP؟ PHP هي لغة برمجة نصية من طرف الخادم (server). لفهم ما يعني هذا، لنقارنها مع Html. عندما تزور صفحة Html بسيطة، يقوم متصفحك بإرسال طلب للخادم الذي يحتوي هذه الصفحة التي تحاول الوصول إليها. الخادم يكتشف أي ملف تريد الوصول إليه ويقوم بإرساله لك. متصفحك يترجم شيفرة Html المرسلة ويعرضها لك. بالمقارنة، عندما تزور صفحة PHP هناك خطوة إضافية متصفحك يقوم بإرسال طلب والخادم يجد الملف الذي تريده. قبل إرساله لمتصفحك، الخادم يعالج الملف، منتجًا مخرجات Html نهائية (Html output) ثم يقوم بإرسال هذه المخرجات لمتصفحك الذي يقوم بعرضها كالمعتاد. لهذا السبب عندما تنظر إلى الشيفرة المصدرية لأي موقع لا ترى أبدًا أي شيفرات PHP، فقط Html، حتى لو كان الموقع مكتوبًا بلغة PHP. إذا لماذا يحتاج الخادم إلى عملية المعالجة؟ ما المغزى من ذلك؟ لأنه يمكننا من عمل مواقع ديناميكية وكتابة شيفرات بفعالية كبيرة. لنستعرض مثالين بسيطين. في Html كل شيء ثابت (static). يمكنك إنشاء صفحة تعرض كلمة “Good morning” أو “Good evening” لكنك لا تستطيع إظهار واحدة وإخفاء الأخرى اعتمادًا على التوقيت الحقيقي لليوم. في PHP تستطيع عمل ذلك لأن الخادم يمكنه معالجة التعليمات البرمجية آخذًا التوقيت الحقيقي لليوم بعين الاعتبار. والمنطق لهذا المثال يكون كالتالي: if it is before 10am { <h1>Good Morning</h1> } if it is after 6pm { <h1>Good Evening</h1> } otherwise { <h1>Good Day</h1> } طبعًا هذه ليست التعليمات البرمجية الحقيقية، لكنها تتبع منطق PHP. الخادم سيحدد أي حالة هي الحالة المحققة للشرط وسيعرض واحدة فقط من العناوين. مثال آخر هو موقع تويتر أو أي موقع آخر الذي يقدم المحتوى المكتوب من قبل المستخدمين. إذا كان تويتر يستخدم Html فقط، أحد ما يجب عليه أن يقوم بوضع تغريدتك في ملف Html في كل مرة تقوم بتغريدة جديدة وهذا طبعًا ليس استغلالاً جيدًا للوقت. يوجد حوالي 1 مليار حساب على موقع تويتر لذلك الشركة ستحتاج إلى 1 مليار ملف Html، ملف لكل مستخدم. مع PHP، مشكلة إعادة توليد ما ينشره المستخدم يمكن أن يحل بعدة ملفات. سنعود إلى هذا المثال لاحقًا في هذه المقالة. البداية قبل أن نبدأ، أود التنبيه على أنه في المراحل الأولى من تعلم PHP ربما لن تكون على قادرًا على إنشاء موقع ويب. هذه ردة فعل طبيعية وهذا أيضًا ما شعرت به عند بداية تعلم PHP. الخطوات الأولى تجريدية قليلاً، لكن في نهاية هذا المقال سترى النور. من أجل اختبار وممارسة ما سوف تتعلم في هذه المقالة، سوف تحتاج إلى خادم أباتشي (Apache server). يمكن أن يكون هذا موقع اختبار عبر الإنترنت ولكن يمكن أيضًا أن يكون خادم محلي. أوصي بإنشاء خادم محلي (local server). وإليك كيفية القيام بذلك: أولاً، عليك تحميل وتثبيت Virtualbox وVagrant. إنشاء مسار في أي مكان على كمبيوترك لتخزين ملفات المشروع. لدي مجلد “websites” في مسار المستخدم الخاص بي، قمت بإنشاء مسار “PHPtutorial”. وسوف أشير إلى هذا باسم “مجلد المشروع الرئيسي” طوال بقية هذا المقال. بمجرد إنشاء المسار، افتح terminal على linux أو osx، أو cmd على windows، وانتقل إلى المجلد. إذا قمت بإنشاء بنية المجلد نفسه كما لدي، على linux أو osx يمكنك كتابة cd ~/websites/PHPtutorial على windows cd %HOMEPATH%/websites/PHPtutorial عندما تكون في المسار الصحيح، ألصق الأمر التالي: curl -L -o 'install.sh' http://bit.ly/1hBfq57 && curl -L -o 'Vagrantfile' http://bit.ly/1mE3Qt9 && vagrant up وبمجرد تنفيذ الأمر، سوف تكون قادرًا على الوصول إلى الموقع الخاص بك على http://192.168.33.21. إذا قمت بإعادة تشغيل جهاز الكمبيوتر الخاص بك، سوف تحتاج أيضًا إلى إعادة تشغيل الخادم الخاص بك، والتي يمكنك القيام به عن طريق الانتقال إلى مجلد المشروع الرئيسي في سطر الأوامر وكتابة vagrant up. ملف المشروع الرئيسي هو الآن المجلد الجذر الخاص بك. قم بإنشاء ملف index.html هناك مع أي محتوى، وينبغي أن يتم عرضه بشكل صحيح عند زيارة موقع الويب الخاص بك على http://192.168.33.21. الخطوات الأولى في البداية، لنلقِ نظرة على الوسوم(tags)، المتغيرات(variables)، القيم (values)، والإظهار (echoing). أنشئ ملف اسمه index.php في ملف المشروع الرئيسي واكتب”Hello HTML” بداخله. للتأكد بأنه يعمل قم بزيارة http://192.168.33.21، ويجب رؤية النص الذي قمت بكتابته على شاشة المتصفح. قاعدة مهمة جدًا وهي أن ما يكتب داخل وسوم php يعتبر شيفرة PHP، وأي شيء آخر يعتبر Html. لذلك ظهر نص Hello HTML. وسوم php تبدأ ب<?php وتنتهي ب ?>. أي شيء بين هذين الوسمين يعتبر PHP. Hello HTML <?PHP echo "Hello PHP"; ?> التعليمات البرمجية السابقة أظهرت كيف يتم استخدام وسوم php وكيفية إظهار القيم على الشاشة. عندما تُظهر قيمة أنت تخبر PHP لعرض هذه القيمة على الشاشة. نتيجة تنفيذ التعليمات البرمجية السابقة سيكون ” Hello Html Hello PHP” . الجزء الأول يعتبر Html لأنه لم يكن داخل وسوم PHP بينما الجزء الثاني قد تم إظهاره بواسطة شيفرة PHP. لاحظ أنه يجب إحاطة النص بإشاراتي اقتباس. المتغيرات(variables) تسمح لك بتخزين القيم بدون عرضها. المتغيرات يتم استخدامها بكثرة لتخزين العديد من الأشياء. لنلقي نظرة على مثال بسيط: <?PHP $name = "Daniel"; echo $name; ?> في التعليمات البرمجية السابقة قمت بتخزين قيمة “Daniel” في متغير يدعى name$. بدلاً من إظهار “Daniel” بشكل مباشر، الآن أنا أظهر قيمة name$ مهما كانت. من الوهلة الأولى تبدو لك كزيادة في التعليمات البرمجية بدون فائدة لكن إذا كنا نستعمل هذا المتغير في أكثر من مكان يمكننا تغيير كل شيء بتغيير قيمة هذا المتغير في مكان واحد، بدلاً من تغيير تلك القيم في كل مكان وُضِعت فيه. لاحظ أن الفصل بين أسطر الشيفرات يكون بوضع فاصلة منقوطة (;). إذا أنتجت شيفرتك خطأ فهناك احتمال أنك نسيت وضع فاصلة منقوطة في مكان ما، خطأ شائع ومحبط لكثير من المبرمجين في كل مكان. القيم(values) يمكن أن تكون عدة أنواع. لحد الآن تعرفنا على واحد من هذه الآنواع وهو النوع النصي. النص هو سلسلة من المحارف ويجب إحاطته بإشارتيَ اقتباس (“). نوع آخر وهو النوع الرقمي. الرقم هو أي عدد كامل ولا يجب وضعه ضمن اشارتي اقتباس وإلا سيعتبر نصًا. واحدة من أهم أنواع القيم المصفوفات(array). المصفوفات تخزن عدة قيم، والتي من الممكن أن تكون قيمًا من أنواع مختلفة. <?PHP $name = 'Daniel'; $age = 30; $interests = array( 'guitar', 'singing', 'squash', 'running', 'board games' ); ?> كما ترى يمكن تعريف المصفوفة على الشكل التالي (array(value1 , value2 , value3. يجب كتابة القيم دائمًا في المصفوفة كما تكتب خارج المصفوفة. النص يجب أن يكون محاطًا بإشارتيَ اقتباس (“)، الرقم غير محاط بشيء وهكذا. مثال بسيط إذا بماذا يمكن استخدام ما تعلمناه للآن، ما تعلمناه للآن لا يمكنه إنشاء موقع بعد ولكن حتمًا نحتاج لمثال عملي الآن. لنلقِ نظرة على شيفرة لتطبيق توقعات الطقس: <?PHP $unit = "C"; $temp = 29; if( $unit == 'F' ) { $temp = $temp * 9 / 5 + 32; } $forecast = "The weather today will be great, a Sunny " . $temp . $unit; echo $forecast; ?> هناك بعض الأشياء الجديدة في هذه التعليمات البرمجية، لكن أعتقد أن المثال يشرح نفسه بوضوح. لنراجعه سطرًا بسطر. في البداية، نقوم بإنشاء متغيرين: أول متغير عبارة عن نص يحمل القيمة “C” للمئوية، والمتغير التالي هو عدد صحيح، 29، والذي يهدف إلى تخزين درجة الحرارة الفعلية. الأهداف هنا بسيطة: عرض النص الذي يخبرنا درجة الحرارة الحالية باستخدام القيمة من متغير درجة الحرارة لدينا في وحدة قياس حسب الاختيار، مئوية أو فهرنهايت. السطر التالي هو عبارة if، التي يتم تنفيذ ما بداخلها فقط إذا كانت القيمة داخل الأقواس صحيحة. الشرط هو: $unit == 'F' الذي يترجم منطقيًا كالتالي: إذا كانت قيمة واحدة القياس هي F و هي ليست كذلك و بالتالي سيتم تخطي كتلة هذا الشرط و ما بداخله بدون تنفيذ. في السطر الأخير متغير forecast$ الذي يحوي عبارة “The weather today will be great, a Sunny “ . اعتمادًا على قيمة متغيري unit$ و temp$ ستكون النهاية مختلفة، النقاط بين النصوص والمتغيرات تجمع المتغيرات مع النصوص أو تدمجها. لذا ببساطة سيتم استبدال قيمة temp$ بـ 29 و unit$ بـ C والمخرجات النهائية ستكون: The weather today will be great, a Sunny 29C الآن، ماذا يحدث إذا غيرنا قيمة unit$ إلى F، في البداية سوف يتم تنفيذ التعليمات البرمجية داخل if لأن شرطها تحقق وأصبحت صحيحة، وهذا يعني أن كل شيء بين الأقواس المجعدة سيتم تنفيذه أيضًا. في المثال، اسندت قيمة جديدة لمتغير temp$. أخذت القيمة الأصلية، وتم ضربها في 9، وتقسيمها من على 5 وإضافة 32 وهذه هي المعادلة لتحويل مئوية إلى فهرنهايت. يجب أن تكون القيمة الجديدة لـ temp$ هي 84.2، والقيمة الجديدة unit$ هي F الآن سيتم استبدال المتغيرات بقيمها في الجملة النهائية فتصبح: The weather today will be great, a Sunny 84.2F هذا المثال لا يزال غير مجدٍ بعض الشيء بالنسبة لنا، لكنه يبدأ في إظهار قوة PHP. لاحظ كيف وصلنا إلى الناتج النهائي عن طريق استبدال المتغيرات ببساطة مع القيم. فهو يساعد على الوصول إلى عقلية “replacing placeholder” لأنه هو أساسًا ما تدور حوله لغة PHP. في مثال حقيقي، سنقوم باستخدام القيم الجوية الحالية وبدلًا من كتابة جملة The weather today will be great, a Sunny سوف نستخدم الظروف الفعلية. وقد نرغب أيضًا في التنبؤ غدًا أو في اليوم التالي، مما سيؤدي إلى استبدال “today” بنص آخر. وبالإضافة إلى ذلك، من الواضح أن درجة الحرارة الحالية من الصعب أن تكون مكتوبة يدويًا في الشيفرة البرمجية، فإنه سيكون من الضروري أن يتم استرجاعها من مكان ما. على الرغم من أن هذا يضيف بضع طبقات من التعقيد، لكن المبدأ سيكون نفسه وهو أن نجلب البيانات من مكان ما ونضعها في مخرجاتنا. عبارة if والحلقات الشرطية loops لقد رأينا بالفعل عبارة if في مثال حقيقي. تقوم عبارة if بالتأكد من الشرط داخل الاقواس. إذا كانت النتيجة صحيحة تتم معالجة التعليمات البرمجية داخل الأقواس المجعدة وإلا فأنه لن يتم تنفيذ التعليمات. عبارة if أيضًا ذات صلة مع else if و else. عبارة else if تكتب دائمًا بعد عبارة if. إذا كانت عبارة if غير محققة سيتم التأكد تاليًا إذا كانت عبارة else if محققة، و يمكن أن يكون لدينا عدد غير محدد من عبارات else if بناءً على نفس المنطق. و أخيرًا لدينا عبارة else التي سيتم تنفيذها عندما تكون جميع الشروط التي تسبقها غير محققة، و ليس من الضروري أن يسبق عبارة else عبارة else if يمكنك فقط استعمال عبارة if و else مع بعضهما. لنلقِ نظرة على الأمثلة التالية للتوضيح: // Simple if Statement if( $speed > 50 ) { echo "You are over the speed limit"; } // If and else statement if( $age < 21 ) { echo "You may not buy alcohol"; } else { echo "You may buy alcohol"; } // If, else if and else statement if( $speed < 25 ) { echo "You are too slow"; } elseif( $speed > 120 ) { echo "You are too fast"; } else { echo "Your speed is just right!"; } شيء آخر هنا علينا أن نلاحظه وهو الأسطر التي تبدأ مع مائلة مزدوجة “//”. المائلة المزدوجة تسمح لك بإضافة تعليق سطر واحد في أي مكان في التعليمات البرمجية. يمكنك إضافة تعليقات متعددة الاسطر من خلال البدء مع / * writing whatever you’d like and ending it with * /. الحلقات (loops) تأتي بالعديد من الأشكال والأحجام، أربعة على وجه الدقة. تسمح لك الحلقات بتشغيل نفس التعليمات البرمجية عدة مرات بناءً على استمرار الشرط الذي بدأت به الحلقة. قد تكره الحلقات الآن، لكنها سوف تصبح أقرب حلفائك عندما تصبح أكثر احترافية في كتابة التعليمات البرمجية. لنبدأ مع حلقة foreach. حلقة foreach تمر من كل عناصر المصفوفة وتنفذ تعليمات برمجية معينة. فيما يلي مثال سريع يظهر قائمة Html: <?PHP $names = array( "Daniel Pataki", "Raelene Morey", "James Farmer" ); echo "<ul>"; foreach( $names as $name ) { echo "<li>" . $name . "</li>"; } echo "</ul>"; ?> المفتاح هنا هو فهم العبارة داخل الأقواس، وهي $names as $name، الجزء الأول هو اسم المصفوفة التي ترغب في المرور من خلالها. والثاني هو اسم المتغير الذي يمكن الرجوع إليه من أجل الحصول على قيمة عنصر في هذه المصفوفة الذي تمر عليه حاليًا من خلال الحلقة ولك الحرية في تسمية هذا المتغير أي أنه ليس من الضروري أن تسميه name$ هنا بل يمكن تسميته أي اسم تريده. في مثالنا، سيتم تنفيذ الحلقة ثلاث مرات. عندما تمر الحلقة بالمصفوفة للمرة الأولى ستكون قيمة المتغير name$ هي “Daniel Pataki”، وفي المرة الثانية ستكون “Raelene Morey,” وفي المرة الثالثة ستكون “James Farmer.” يعرض المثال التالي تفاصيل في قائمة، من مصفوفة مترابطة: <?PHP $details = array( "name" => "Daniel Pataki", "Age" => "30", "Twitter" => "http://twitter.com/danielpataki" ); echo "<ul>"; foreach( $details as $label => $value ) { echo "<li><strong>" . $label . "</strong>: " . $value . "</li>"; } echo "</ul>"; ?> الأقواس تحتوي الآن على ثلاثة متغيرات: $details as $label => $value ، ستمر الحلقة الآن من المصفوفة details$. عند كل مرور للحلقة على المصفوفة سيتم مناداة المفتاح label$ والقيمة المرتبطة بهذا المفتاح value$ ، عند المرور الثاني ستكون قيمة label$ هي Age و قيمة value$ هي 30 و ستكون نتيجة تنفيذ التعلمية هي: • Name: Daniel Pataki • Age: 30 • Twitter: http://twitter.com/danielpataki كيف تعمل قوائم مقالات ووردبريس: لنلقِ نظرة الآن على مثال أكثر ارتباطًا بووردبريس: كيف تعمل قوائم مقالات ووردبريس. لا تحاكي التعليمات البرمجية أدناه ووردبريس بالضبط، ولكن جوهر العملية موجود. تخيل أن المنشورات أو المقالات جزء من مصفوفة ارتباطية كبيرة. التعليمات البرمجية الخاصة بصفحتك الرئيسية ببساطة تمر على المصفوفة وتضع البيانات المناسبة في المكان المناسب في بعض وسوم Html: $posts = array( 0 => array( "post_title" => "My First Post", "post_excerpt" => "This is a short snippet of text from the first post", "post_date" => "2015 December 1", "post_author" => "Daniel Pataki" ), 1 => array( "post_title" => "Second Post", "post_excerpt" => "Short exceprt for post number 2", "post_date" => "2015 December 4", "post_author" => "Raelene Morey" ) ); foreach( $posts as $post ) { echo "<div class='post'>"; echo "<h1>" . $post['post_title'] . "</h1>"; echo "<p>" . $post['post_excerpt'] . "</p>"; echo "<div class='post-meta'>Published on " . $post['post_date'] . " by " . $post['post_author'] . "</div>"; echo "</div>"; } الدوال (Functions) بطريقة ما، الدوال تخدم نفس الغرض كما المتغيرات - وسيلة لاستبدال التعليمات البرمجية. يمكن أن تأخذ الدوال كتلة من التعليمات البرمجية وتخزّنها لوقت لاحق وتستخدمها عدة مرات. دعونا ننظر إلى مثال بسيط جدًا باستخدام حلقة المقالات بالمثال السابق. حيث أنه من المحتمل أن يتم استخدام الجزء الذي نظهر فيه عناصر المنشورات في عدة صفحات من موقع الويب - كالصفحة الرئيسية، وصفحات الأرشيف، وصفحات المؤلفين، وما إلى ذلك. سنستخدم نفس التعليمات البرمجية مرارًا وتكرارًا. هذا هو بالضبط الوقت الذي نحتاج فيه إلى الدوال. <?PHP function display_post( $postdata ) { echo "<div class='post'>"; echo "<h1>" . $postdata['post_title'] . "</h1>"; echo "<p>" . $postdata['post_excerpt'] . "</p>"; echo "<div class='post-meta'>Published on " . $postdata['post_date'] . " by " . $postdata['post_author'] . "</div>"; echo "</div>"; } $posts = array( 0 => array( "post_title" => "My First Post", "post_excerpt" => "This is a short snippet of text from the first post", "post_date" => "2015 December 1", "post_author" => "Daniel Pataki" ), 1 => array( "post_title" => "Second Post", "post_excerpt" => "Short exceprt for post number 2", "post_date" => "2015 December 4", "post_author" => "Raelene Morey" ) ); foreach( $posts as $post ) { display_post( $post ); } التعليمة البرمجية أعلاه ليست أقصر، ولكن في أي وقت نريد عرض منشورات في المستقبل يمكننا فقط أن نكتب display_post( $post ); مما يجعلها أكثر كفاءة في المستقبل. كيف يعمل كل هذا؟ دعونا نفهم ذلك من خلال النظر إلى الدالة في الجزء العلوي من التعليمات البرمجية. قمت بتسمية هذه الدالة بـ display_post(); و في القوسين نلاحظ أن هذه الدالة تتوقع وسيط واحد. و نحن نعلم أن هذا الوسيط يجب أن يحتوي معلومات المنشور لذا سيكون هذا الوسيط عبارة عن مصفوفة مترابطة تحتوي معلومات منشور واحد أسميته postdata$. ضمن الأقواس المجعدة ندرج كل التعليمات البرمجية التي نريد تنفيذها عند استدعاء الدالة. هذه هي نفس التعليمات البرمجية التي كانت لدينا من قبل، أنا فقط بحاجة إلى إعادة تسمية كافة المتغيرات إلى postdata$، اسم الوسيط الذي تتوقعه الدالة، والتي يمكننا استخدامها في أي مكان داخل الدالة. في الجزء السفلي من التعليمة البرمجية، يمكنك أن ترى أن عرض المقال الآن أصبح أكثر تنظيمًا للتعليمات البرمجية، لقد استخدمنا للتو display_post($post). أنا متأكد أنك تشعر ببعض الضياع الآن حول التسمية، لماذا استخدمنا post$ في مكان و postdata$ في مكان آخر؟ لنراجع التعليمات البرمجية يتم تشغيل الدوال فقط عندما يتم استدعاؤها، لذا أكثر ما يهمنا في تعليماتنا البرمجية هو مصفوفة $posts، بعد ذلك نقوم بإنشاء الحلقة، كما فعلنا سابقًا. بداخل الحلقة المتغير الذي يحوي بيانات المقال الواحد post$، لحد الآن لم يتغير شيء من مثال الدالة. الآن، بدلًا من وجود كتلة من التعليمات البرمجية هناك نحن ببساطة سنقوم بإسناد هذه التعليمات البرمجية لدالة. نستدعي دالة ()display_post، نعلم أننا نحتاج لتمرير بيانات لهذه الدالة و هذه البيانات هي بيانات مقال واحد. أي متغير يحوي هذه البيانات الآن؟ المتغير post$ ، هذا يأتي من تعريف الحلقة. بعد ذلك، انتقل للأعلى إلى الدالة. سيتم الآن تنفيذها. في هذه الدالة تم تسمية الوسيط postdata$ هذا يعني ببساطة أنه ضمن هذه الدالة سيتم الإشارة إلى البيانات التي يتم تمريرها إلى هذه الدالة كوسيط بـ.postdata$ إنشاء مقتطفات يمكن أن تحتوي الدوال على وسائط متعددة وقيم افتراضية لهذه الوسائط. دعونا ننشئ دالة يمكن أن تحول أي نص إلى مقتطف عن طريق قطعه إلى قطع نصية. نريد دالة لتكون مرنة قدر الإمكان، وقادرة على السيطرة على طول المقتطف، وإلحاق السلسلة إلى النهاية. سنجعل الوسيط الأول النص الذي نريد تقصيره، الوسيط الثاني سيكون لتحديد مقدار المحارف التي نريد اقتطاعها، والثالث النص المُلحق. دعونا نبدأ بإعطاء الدالة إطار للعمل ضمنه: function make_excerpt( $text, $length = 200, $append = '...' ) { } لاحظ أنني أعطيت قيمًا افتراضية لهذه الوسائط. هذا يعني أنه يمكنك استدعاء الدالة دون تمرير الوسيطين الثاني والثالث. إذا قمت بذلك سوف تفترض الدالة أنك تريد إنشاء مقتطف طويل من 200 حرف وإلحاق ثلاث نقاط بعد ذلك. دعونا نكتب محتوى هذه الدالة: function get_excerpt( $text, $length = 200, $append = '...' ) { if( strlen( $text ) < $length ) { return $text; } else { $excerpt = substr( $text, 0, $length ); $excerpt .= $append; return $excerpt; } } لقد أضفت الكثير من الأشياء الجديدة في هذه الدالة، لذلك دعونا نشرح كل إضافة جديدة بالتفصيل. يبدأ كل هذا بعبارة if، الذي تتحقق مما إذا كان النص المعطى أطول من طول معين. وذلك باستخدام دالة مبنية مسبقًا في لغة PHP تدعى ()substr. تأخذ هذه الدالة سلسلة حرفية كوسيط وتعيد طولها. إذا كان طول text$ أقل من length$ يتم إرجاع النص ببساطة - سنتحدث عما يعني الإرجاع خلال لحظات. وإلا، فإننا ننشئ مقتطفًا باستخدام الدالة ()substr. هذه الدالة تقطع سلسلة حرفية وتتطلب ثلاثة وسائط: النص الذي سنقتطع منه، ومن أين تبدأ بالاقتطاع، وطول النص الذي نرد اقتطاعه. نريد أن نبدأ من بداية النص وقطع أحرف length$، وهذا هو السبب لإضافتي رقم 0 كي يقتطع من بداية السلسلة الحرفية. وأخيرًا، نضيف النص الملحق إلى النهاية. لقد استخدمت .= للقيام بذلك. هذه هي نفس كتابة $excerpt = $excerpt. $append في السطر الأخير، قمت بإعادة متغير excerpt$. ما هو الإرجاع؟ حتى الآن كنا في معظم الأحيان نظهر المخرجات، ولكن في كثير من الحالات نحن لا نريد عرض نتيجة حساباتنا. الدالة ()strlen هي مثال جيد على ذلك. أنت لا تريد فعلاً عرض طول متغير text$ أنت ترغب فقط في استخدامه في التعليمات البرمجية لتحقيق شيء ما. ()strlenترجع هذه القيمة، مما يسمح لك باستخدامها في مكان آخر. عند إرجاع قيمة باستخدام دالة، يمكنك إما استخدامها مباشرة مثل دالة ()strlen، أو تعيينها لمتغير $short_text = get_excerpt( $content ) يمكنك بعد ذلك إظهار short_text$ في وقت لاحق عند الحاجة. لمزيد من القراءة والدراسة PHP هي الأساس لجميع قوالب و إضافات WordPress لذلك سوف تحتاج إلى الاعتماد بشكل كبير جدًا على هذه اللغة. عند العمل في بيئة ووردبريس، ستستخدم دوال PHP (مثل strlen و substr)، ولكن هناك أيضًا مئات من الدوال التي تم إنشاؤها خصيصًا لووردبريس من قبل فريق التطوير الأساسي لمساعدتك. ستكتشف بعض هذه الوظائف في الدروس القادمة من هذه السلسلة. لقد غطينا الأساسيات التي تحتاج إلى معرفتها للبدء بتطوير ووردبريس، ولكن الحقيقة هي أننا فقط خدشنا السطح! من المهم أن تقرأ وتستكشف كل المواضيع المتعلقة بووردبرس وPHP لمزيد من العمق والممارسة. ترجمة -وبتصرّف- للمقال WordPress Development for Beginners: Learning PHP لصاحبه Daniel Pataki
  8. قد يبدو مفهوم البرمجة غرضية التوجه (object-oriented programming)، صعبًا ومعقدًا في البداية لكنه مفهوم مهم يجب تعلمه، إذا أردت زيادة مهاراتك وقدراتك في تطوير إضافات ووردبريس.سوف نشرح طريقتين مفيدتين تمكنك من جعل إضافاتك غرضية التوجه، الأمر الذي سيقلل من فرص تعقيد التعليمات البرمجية وتضاربها مع بعضها البعض، وتمكنك من كتابة تعليمات برمجية مرتبة وقوية وتشكل وحدات منفصلة. ملاحظة: هذه المقالة حول البرمجة غرضية التوجه، لم يتم التطرق فيها إلى طرق الكتابة المتقدمة للتعليمات البرمجية أو تم تبسيط بعضها لتصبح مفهومة بشكل أكبر للمبتدئين، الغرض من هذه المقالة تعليمك المبادئ الأساسية للبرمجة غرضية التوجه، وليس جعلك محترفًا في ليلة وضحاها، لكن إذا واصلت شغفك على التعلم والتجربة فستصبح محترفًا في وقت قصير. ما هي البرمجة غرضية التوجه؟ البرمجة غرضية التوجه بأبسط مفهوم هي طبقة أخرى من التجريد(abstraction)، إذا كتبت تعليمات php عند عملك في ووردبريس من قبل ففي الغالب أنك مررت بمرحلة التجريد، بدلًا من كتابة أسطر من التعليمات البرمجية سطرًا تلو سطر، البرمجة الغرضية تستخدم بواني (constructs) كالدوال (functions). الدوال يمكن ان تجعل التعليمات البرمجية أكثر مركزية ووحدة. لنأخذ هذا المثال: <div class='post' id='post-23'> <h2><?php the_title() ?></h2> <div class='excerpt'> <?php $content = get_the_content(); if( strlen($content) < 250 ) { echo $content; } else { $content = substr( $content, 0, 250 ); echo $content . '...'; } ?> </div> </div> قمت يدويًا بإنشاء مقتطف عند جلب البيانات مباشرة، لكن تخيل أن أفعل ذلك في كل مرة أعرض منشور ووردبريس، ليست هذه بداية المشكلة حتى، لكن ماذا لو أردت بعد فترة تغيير طول محارف المقتطف. الآن هي معدة لتقتطع 250 محرفًا و إذا أردت تغيير هذا العدد عليك أن تمر على جميع الأماكن التي كتبت هذه التعليمات فيها و تغييرها واحدًا تلو الآخر، لهذا استخدام الدوال مفيد جدًا، ووردبريس أوجدت حلًا لهذه المشكلة عن طريق استخدام دالة ()the_excerpt. <div class='post' id='post-23'> <h2><?php the_title() ?></h2> <div class='excerpt'> <?php the_excerpt() ?> </div> </div> البرمجة غرضية التوجه هي طبقة أخرى من التجريد(abstraction)، مشابهة كثيرًا للدوال. في هذه المقالة، سنقوم بإنشاء صنف(class)، الذي يمكن تشبيهه بوعاء حاوي للدوال. كتابة صنفك الأول لنقم بإنشاء صنف باسم “Post”. سيكون الهدف منه هو التلاعب بمنشورات ووردبريس: class Post { function get_excerpt( $content ) { if( strlen($content) < 250 ) { return $content; } else { $excerpt = substr( $content, 0, 250 ); return $excerpt . '...'; } } function the_excerpt( $content ) { echo get_excerpt( $content ); } function the_title( $title ) { echo $title; } } صنفنا الآن يحتوي على 3 دوال بسيطة، واحدة لجلب المقتطف والثانية من أجل عرض المقتطف، الثالثة لعرض عنوان المقال. في الوقت الحالي الصنف يحتوي الآن فقط دوال، لكن هذا ليس كل شيء يمكن للصنف أن يفعله. لنرى القوة الحقيقية للأصناف سنلقي نظرة على دالة خاصة في الأصناف تدعي الباني __construct() ، ومتغير خاص يدعى this$، والمتغيرات داخل الأصناف. عندما ننشأ صنف، يكون الهدف منه معظم الأحيان هو إنشاء كائنات متعددة، يمكنك إنشاء عدة منشورات، لنرى كيف سنقوم بها من خلال هذا المثال: class Post { var $title; var $content; function __construct( $data ) { $this->title = $data['title']; $this->title = $data['content']; } function get_excerpt() { if( strlen($this->content) < 250 ) { return $this->content; } else { $excerpt = substr( $content, 0, 250 ); return $excerpt . '...'; } } function the_excerpt() { echo $this->get_excerpt(); } function the_title() { echo $this->title; } } $postdata = array( 'title' => 'Post 1 Title', 'content' => 'Content of Post 1' ); $post = new Post( $postdata ); $post->the_excerpt(); هناك الكثير من الأشياء غير المفهومة بالنسبة لك في هذا المثال، لكن سيتم شرح كل شيء خلال لحظات، عندما تريد إنشاء كائن من صنف تستعمل هذه التعليمات كما في المثال $post = new Post ($postdata)، عندما تقوم بإنشاء الكائن ستنفذ الدالة البانية بشكل مباشر. الوسيط postdata$ الذي تم تمريره للكائن عند إنشائها سيصبح متاحًا لدالة الباني التي تم تعريفها في الصنف. لتعطي قيم للمتغيرين اللذين تم تعريفهما داخل الصنف. تم إسناد قيمة للمتغير title$ عن طريق this->$title وللمتغير content$ عن طريق this->$content . المتغير this$ هو متغير خاص يشير إلى الصنف نفسه، في أي وقت تريد الإشارة فيه إلى متغير تم تعريفه داخل الصنف بـ this->$property_name أو إلى دالة ()this->$function_name تم تعريفها داخل الصنف. ملاحظة: الدوال داخل الصنف تدعى طرائق(methods)، والمتغيرات تدعى خصائص(properties) وسيتم من الآن الإشارة إليهم بهذه الأسماء بهذا المقال. إن أفضل طريقة لفهم كيفية عمل الأصناف هو تتبع التعليمات البرمجية، بعد أن قمنا بإنشاء الكائن قمنا بتشغيل الدالة ()post->the_excerpt$ لكن الآن نستعمل متغير post$ للإشارة إلى الدالة بدلًا من this$ لأننا نستعمل هذه الدالة خارج الصنف. الآن لنعرف بماذا تقوم هذه الدالة يمكننا التوجه إلى تعريف الصنف لأننا نعلم أن التعريف الأصلي والتعليمات البرمجية لهذه الدالة هي في الصنف الذي تم تعريفها فيه. كما نرى أن دالة get_excerpt لا تحتاج لتمرير أي محتوى لأنها تأخذ المحتوى من المتغير content$ مراجعة ما تعلمناه لنراجع ما تعلمناه عن الأصناف قبل أن نرى كيف نستعملها في برمجة إضافات ووردبريس. الصنف هو وعاء حاوي للدوال يمكن تعريف الصنف بكتابة كلمة class وبعدها اسم الصنف، الدوال داخل الصنف تدعى طرائق، والمتغيرات تدعى خصائص. إذا كنا نكتب التعليمات البرمجية داخل الصنف فيمكن الإشارة إلى الخصائص والدوال بالمتغير this$. يمكن إنشاء كائن من صنف باستخدام الصيغة $object = new class( $params ) . الدالة البانية يتم تنفيذها مباشرة عند إنشاء الكائن. استخدام الكائنات في إضافات ووردبريس بما أن الأصناف تقوم بتغليف التعليمات البرمجية ضمن وعاء أو وحدة واحدة فهي تمنع التضارب مع التعليمات البرمجية المتواجدة خارج هذا الصنف يمكنني تعريف الدالة get_excerpt في إضافة ووردبريس التي أعمل عليها على الرغم أن هذه الدالة متواجدة بنفس الاسم في التعليمات البرمجية الأساسية لووردبريس. البرمجية غرضية التوجه تعتبر ميزة رائعة لأنها تجبرك استخدام معايير برمجية جيدة بالإضافة أنها تجعلك مبرمجًا أفضل. عندما تكون البرمجة غرضية التوجه مكتوبة بشكل جيد، فإنها دائمًا تكون الحل الأمثل لتتمكن من معرفة مزاياها بشكل جيد نحن نحتاج إلى أكثر من عدة أسطر برمجية، برمجة إضافة ووردبريس ستكون مثالًا رائعًا. هذا مثال هو عبارة عن إضافة تضيف نصًا إلى نهاية كل مقال يتم نشره بشكل تلقائي: <?php /* Plugin Name: Written By Awesome Description: Adds a nice author tagline Version: 1.0.0 Author: Daniel Pataki Author URI: http://danielpataki.com */ class Written_By_Awesome { function __construct() { add_filter( 'the_content', array( $this, 'add_author_line_to_content' ) ); } function add_author_line_to_content( $content ) { return $content . '<br> Written by someone awesome'; } } $written_by_awesome = new Written_By_Awesome(); عندما تفهم كيف تعمل الأصناف يمكنك تخطي الكثير من العوائق والتفكير بتعليماتك البرمجية كوحدات منفصلة، على سبيل المثال يمكنك إنشاء أصناف لتتولى التعليمات البرمجية الخاصة بالتفاعل مع المستخدم وإظهار النتائج، وأصناف آخرى للتعامل مع الخادم (server). لنلقي نظرة على هذه الإضافة، التي ترتب المنشورات بناء عدد التعليقات: <?php class PostsByCommentBackend { function construct() { add_action( 'pre_get_posts', array( $this, 'backend_query' ) ); } function backend_query( $query ) { if ( ! $query->is_admin() ) { $query->set( 'orderby', 'comment_count' ); $query->set( 'order', 'DESC' ); } } } class PostsByCommentFrontend { function construct() { add_action( 'pre_get_posts', array( $this, 'frontend_query' ) ); } function frontend_query( $query ) { if ( $query->is_admin() ) { $query->set( 'orderby', 'comment_count' ); $query->set( 'order', 'DESC' ); } } } $backend = new PostsByCommentBackend(); $frontend = new PostsByCommentFrontend(); ربما تجد هذه التعليمات بالغة الصعوبة، لكن النقطة التي أحاول الوصول إليها أن فصل تعليماتك البرمجية إلى وحدات منفصلة، يسهل عملية تطوير هذه الوحدات والبناء عليها. مثال كامل إذا كنت مهتمًا بمزيد من الأمثلة التوضيحية يمكنك الاطلاع على مشروع WordPress Plugin Boilerplate وهو عبارة عن قاعدة لبناء إضافات ووردبريس عن طريق البرمجة غرضية التوجه. لقد استخدمتها في العديد من مشاريعي وأنصح بها بشدة، خاصة للإضافات التي تتطلب درجة عالية من التعقيد. الخاتمة منصة ووردبريس تحتاج إلى إضافات مكتوبة بشكل أفضل، والحل الوحيد هو استخدام البرمجة غرضية التوجه، إنها تجعل التعليمات البرمجية أكثر قابلية للقراءة، مرتبة بشكل أفضل وذات جودة عالية وسهلة التطوير مستقبلًا. ترجمة -وبتصرّف- للمقال An Introduction to Object-Oriented Code for WordPress Plugins لصاحبه Daniel Pataki
  9. في هذا الدرس ستحتاج بعض الأمثلة للتعديل بما يتوافق مع حالتك لتعمل بشكل صحيح (مثل كلمات السّر)، أمّا الباقي فمعظمه سيكون قابلاً للنسخ واللصق. حول دالّة mail() في لغة PHP تَستخدِم دالّة mail() البرنامج الموجود في مسار sendmail_path لإرسال رسائل البريد الإلكتروني. وهذا معدٌّ كـَsendmail بشكلٍ افتراضي. ومع أن معظم تنصيبات نظام Linux تملك sendmail مثبتة بشكل مسبق، فإنّك ستواجه بعض الصعوبات في إعداد تسجيلات SPF/PTR وتوليد مفاتيح DKIM وبعض الأمور الأخرى حتى تتأكد بأن رسالة البريد المرسلة بواسطة سكربت الـPHP لن يتم تعليمه كرسالة بريدٍ ضارة (spam). يمكن استخدام بروتوكول MSMTP - وهو أحد عملاء SMTP - لإرسال رسائل البريد باستخدام خوادم SMTP من طرف ثالث، ويمكن استخدام ذلك في دالّة mail() عوضاً عن sendmail. التثبيت لتثبيت برتوكول MSMTP على نظام Fedora Linux استخدم yum كالاتي: yum install msmtp وبما أن مستودع CentOs لا يحتوي على حزمة RPM لـMSMTP ، فإننا سنحتاج الى تنصيبها من المصدر: yum install make gcc pkgconfig wget http://sourceforge.net/projects/msmtp/files/msmtp/1.4.31/msmtp-1.4.31.tar.bz2/download tar -xvf msmtp-1.4.31.tar.bz2 cd msmtp-1.4.31 ./configure make make install في وقت كتابة هذا المقال فإن آخر إصدار متوفر هو 1.4.31، ولكن قد تتوفر إصدارات أخرى في المستقبل، وللحصول عليها قم بزيارة هذه الصفحة. على توزيعة Ubuntu/Debian استخدم apt-get : apt-get install msmtp ولمستخدمي Arch Linux : sudo pacman -S msmtp إعداد بروتوكول MSMTP إن ملف الإعدادات الخاص ببروتوكول MSMTP محفوظ في ~/.msmtprc لكل مستخدم، وملف الإعدادات الشامل للنظام هو /etc/msmtprc. قم الآن بفتح ملف الإعدادات في دليلك (directory): vi ~/.msmtprc قم بإضافة هذه الأسطر إلى حساب Yahoo: account yahoo tls on tls_starttls off tls_certcheck off auth on host smtp.mail.yahoo.com user user1 from user1@yahoo.com password yourYahooPa5sw0rd وبالنسبة للـGmail استخدم الإعدادات التالية: account gmail tls on tls_certcheck off auth on host smtp.gmail.com port 587 user user1@gmail.com from user1@gmail.com password yourgmailPassw0rd يمكن أن يحتوي هذا الملف على أكثر من حساب، فقط تأكد بأن تكون قيمة account لكل قسم مختلفة عن الأخرى. قم بحفظ الملف واستعمل chmod لجعل هذا الملف قابلاً للقراءة فقط من قبل المالك لأنه يحتوي على كلمات مرور. الخطوة التالية تعد إجبارية لأن بروتوكول msmtp لن يعمل إذا كانت الصلاحيات أكثر من 600. chmod 600 ~/.msmtprc قبل تنفيذ ذلك في PHP، تحقق باستخدام سطر الأوامر لتتأكد أن كل شيء يعمل بشكل سليم. للقيام بذلك، قم بإنشاء ملفٍ نصيٍّ عادي وضع فيه النص الآتي (النص عبارة عن رسالة بريد قصيرة): echo -e "From: Alice <alice@example.com> \n\ To: Bob <bob@domain.com> \n\ Subject: Hello World \n\ \n\ This email was sent using MSMTP via Gmail/Yahoo." >> sample_email.txt قم الآن بإرسال البريد: cat sample_email.txt | msmtp --debug -a gmail bob@domain.com استبدل كلمة gmail بكلمة yahoo أو ما قمت بإدخاله مسبقاً في خيار account. سوف ترى العديد من الرسائل بسبب المعطى --debug. يُستخدَم هذا لجعل اكتشاف وتصحيح الأخطاء أمراً سهلاً إذا لم تعمل الأمور كما يجب. إذا تلقّى bob@domain.com هذا البريد فإن كل شيء قد تم تنصيبه بشكل صحيح. لذلك قم بنسخ هذا الملف إلى مُجلّد /etc باستخدام السطر التالي: cp -p ~/.msmtprc /etc/.msmtp_php قم بتغيير الملكية إلى اسم المستخدم الذي يعمل الخادوم تحته. قد يكون ذلك apache، www-data أو nobody اعتماداً على توزيعة الـLinux الموجودة في الخادوم الإفتراضي الخاص بك (VPS) وعلى خادوم الويب المثبت: chown www-data:www-data /etc/.msmtp_php إعداد وتهيئة PHP افتح ملف php.ini والذي قد يختلف مكان وجوده باختلاف نظام التشغيل (OS) ونوع PHP المثبت (مثل PHP CGI، mod_php، PHP-FPM …الخ): vi /etc/php5/php.ini ابحث عن السطر الاتي: sendmail_path = وعندما تجده قم بتعديله عن طريق إضافة المسار الخاص بأمر msmtp ليصبح كما يلي: sendmail_path = "/usr/bin/msmtp -C /etc/.msmtp_php --logfile /var/log/msmtp.log -a gmail -t" يدوياً، أنشىء ملف سجل (log file) وقم بتغيير ملكيته (ownership) الى اسم المستخدم الذي يعمل به خادوم الويب: touch /var/log/msmtp.log chown www-data:www-data /var/log/msmtp.log أعد تشغيل خادوم الويب لتطبيق التغييرات: service httpd restart في نظام Arch Linux يتم ذلك باستخدام الأمر systemctl: systemctl restart httpd اعتماداً على نظام التشغيل وخادوم الويب قم باستبدال httpd بالاسم المناسب. إذا كانت PHP تعمل كعملية منفصلة (مثل PHP-FPM) قم بإعادة تشغيله عوضاً عن ذلك: service php5-fpm restart ولإختبار هذه التنصيبة، قم بإنشاء سكربت PHP مع دالّة mail() بسيطة: <?php if(mail("receipient@domain.com","A Subject Here","Hi there,\nThis email was sent using PHP's mail function.")) print "Email successfully sent"; else print "An error occured"; ?> قم بالدخول إلى هذا الملف باستخدام إحدى المتصفحات: http://www.example.com/file.php اذا لم يتم إرسال البريد فيمكنك التحقق من وجود أي أخطاء عبر سجل msmtp: tail /var/log/msmtp.log أخطاء شائعة اذا لم يتم إرسال البريد عند استخدام سكربت PHP، فعليك التحقق مما يلي: تحقق من أنك قد قمت بالتعديل على ملف php.ini الصحيح. يمكن التأكد والتحقق من ذلك عن طريق إنشاء ملف phpinfo(); والتأكد من قسم Loaded Configuration File. قد يكون المسار الى ملف إعدادات msmtp خاطئًا أو أن الخادوم لا يملك الصلاحية لقراءة هذا الملف. تحقق اذا ما تم إرسال أي بريد وذلك عن طريق تشغيل السكربت باستخدام سطر أوامر PHP: php /var/www/html/file.php ترجمة -وبتصرّف- للمقال How To Use Gmail or Yahoo with PHP mail() Function لصاحبه Jesin A
  10. هل أنت من محاربي PHP القدامى وتريد معرفة ما الذي استجد منذ عدِّة سنوات؟ أم أنت منتقلٌ حديثًا إلى PHP من لغةٍ أخرى وتود معرفة الأمور المثيرة في PHP، ها قد وصلت إلى المكان الصحيح. لننفض الغبار عن معلوماتك، وتهيّأ أن تتعلم ميزاتٍ أضيفت حديثًا إلى PHP. معايير PHP-FIG أعداد مشاريع ومكتبات وأطر عمل PHP الموجودة حاليًا مهولة، إذ هنالك العديد من أطر عمل PHP المتوفرة للاستعمال، لكن من الصعب استعمالها معًا، فماذا لو استطاع أحد أطر العمل الاستفادة من مكتبة ما خارجية، بدلًا من كتابتها يدويًا، أو الاستفادة من مكتبة من إطار Laravel مثلًا؟ لهذا الغرض أُنشِئت PHP-FIG (اختصار للعبارة Framework Interoperability Group) في مؤتمر php|tek في 2009ـ التي وضعت عدِّة معايير يُرمَز لها بالاختصار PSR (أي PHP Standards Recommendations) سنورد ذكرها هنا باختصار. PSR-1: معيار كتابة الشيفرات يوضح هذا المعيار الأمور الأساسية التي يجب أخذها بعين الاعتبار عند كتابة الشيفرات لتحقيق أكبر قدر من المحمولية وإمكانية التشغيل مع بقية المكتبات والبرمجيات. يجب استعمال وسوم ‎<?php ?>‎ الاعتيادية، ووسم echo المختصر ‎<?= ?>‎ فقط. يجب أن يكون ترميز ملفات الشيفرات UTF-8 دون BOM. يجب على الملف أن يُنشِئ بنى برمجية جديدة مثل الأصناف (classes) والدوال …إلخ. دون أن يُحدِث أي "تأثير جانبي"، أو يجب أن ينفِّذ الخطوات المنطقية التي تؤدي إلى "تأثيرات جانبية" ولكن لا يُسمَح أن يقوم بكلا الأمرين. نستطيع تعريف "التأثيرات الجانبية" بالأمور غير المتعلقة بتعريف الأصناف أو الدوال، وهي تشمل: توليد المخرجات، أو تضمين الملفات (عبر include أو require)، أو الاتصال إلى الخدمات الخارجية، أو تعديل ضبط ini، أو تعديل المتغيرات العامة أو الكتابة إلى ملفات، وهلم جرًا. يجب أن تكون مجالات الأسماء (namespaces) وأسماء الأصناف متوافقة مع معيار PSR-4 (سنأتي على ذكره بعد قليل)، وهذا يعني أن كل ملف سيحتوي على صنف وحيد باسمه، وفي مجال أسماء من مرحلة (level) واحدة على الأقل. يجب أن تكون أسماء الأصناف على الشكل StudlyCaps (أي الحرف الأول من كل كلمة كبير). يجب أن تكون الثوابت المُعرَّفة في الأصناف بأحرف كبيرة وتفصل الشرطة السفلية بين الكلمات. يجب أن تكون أسماء الدوال على الشكل camelCase (أي الحرف الأول من كل كلمة كبير، عدا أول كلمة). PSR-2: معيار تنسيق الشيفرات يساعد هذا المعيار في تسهيل التعامل مع الملفات التي كتبها مبرمجون آخرون عبر تحديد قواعد مشتركة لكيفية تنسيق شيفرات PHP. يعتمد هذا المعيار على المعيار PSR-1، أي على المبرمج تطبيق قواعد PSR-1 أولًا. يجب أن تُستعمل أربعة فراغات (مسافات) لمحاذاة الشيفرات، وليست مسافات الجدولة (tabs)، ولا يجوز أن تدمج بين الطريقتين، وذلك لتفادي حدوث مشاكل في ملفات الفروقات (diff) وغيرها. ليس هنالك حدٌ أقصى لعدد المحارف في السطر، لكن يستحسن أن يكون بطول 80 محرف أو أقل، ويمكن إضافة أسطر فارغة لتحسين مقروئية النص. ولا يجوز وضع أكثر من تعبير برمجي في السطر الواحد. يجب أن تكون الكلمات المفتاحية (keywords) في PHP بأحرفٍ صغيرة، وكذلك الأمر للثوابت true و false و null. يجب وجود سطر فارغ وحيد بعد تعريف مجال الأسماء (namespace)، وكذلك الأمر بعد use. يجب أن يكون قوس البداية لصنف أو دالة في سطرٍ منفصل، وكذلك قوس النهاية؛ ولا يجوز وضع فراغ بين اسم الدالة وقوس المعاملات، ويجب وضع فراغ وحيد بعد الفاصلة "," في حال وجود أكثر من معامل. يجب تعيين مُحدِّد وصول مثل public أو private أو protected، وعدم استخدام var. يجب وضع فراغ وحيد بعد الكلمة المحجوزة لبنى التحكم (مثل if و for وغيرهما). PSR-3: معيار السجلات يُعرِّف هذا المعيار واجهةً (interface) للتسجيل (logging). PSR-4: معيار التحميل التلقائي شرحنا التحميل التلقائي في درس توزيع شيفرات PHP على عدة ملفات، يمكنك العودة إليه لمزيدٍ من المعلومات. الحزم البرمجية تخيل معي الوضع التالي: أنت مُطور PHP، لديك مشروع تود تطويره، قد تختار إطار عمل مُعين لهذه المهمة، لكنك ستحتاج إلى بضعة مكتبات إضافية للقيام بذلك، تخيل بأنك تود أن يقوم تطبيقك بنشر تحديثات مُعينة على حساب المُستخدم على تويتر، وجدت المكتبة التي ترغب في استخدامها لكنها مكتبة تعتمد على مكتبة أخرى. مُطور PHP من العصر الحجري سيقوم بالتالي: سيقوم بتحميل نُسخة من إطار العمل، ومن ثم يقوم بإنشاء مُجلد يضع فيه المكتبات الإضافية التي يحتاجها ومن ثم يُحاول فهم آلية عملها ليربطها ببعضها البعض. قد تؤتي هذه الطريقة أكلها، وقد تسمح لك بتطوير مشروعك "من دون أية مشاكل"، لكن ماذا يحدث مثلا لو تم إطلاق تحديث لأي من المكتبات التي تعتمد عليها؟ هل ستقوم بإعادة تحميلها من جديد واستبدال الإصدار القديم بالجديد؟ هل يُمكن أن تفعل ذلك لو كنت تستخدم أكثر من مكتبة يعتمد بعضها على بعض؟ لست متأكدا من ذلك. لكن ما هو البديل؟ هل عرفت فائدة أدوات إدارة الحزم؟ ما رأيك أن تكمل قراءة مقال ما هو Composer ولماذا يجب على كل مطور PHP استخدامه وتتعرف على composer وتتعلم طريقة استخدامه. كلمات المرور توجد قابلية تسجيل مستخدمين جدد في أغلبية المواقع، وهذا يعني أنَّ على المستخدم توفير كلمة مرور لكي يدخل على حسابه، لكن هل تساءلت من قبل عن أكثر الطرق أمانًا في تخزين كلمات مرور المستخدمين؟ سأنصحك بعض النصائح في هذا الصدد. لا يجدر بك معرفة كلمات مرور مستخدميك هذا يعني أنَّك ستخزِّن كلمة المرور على شكل نص بسيط في مكانٍ ما في قاعدة بياناتك، افترض مثلًا أنَّ موقعك قد تعرض للاختراق، واستطاع المُخترَق الوصول إلى قاعدة بيانات موقعك واستطاع رؤية جميع كلمات مرور مستخدميك! أنت تعرض سلامة حسابات مستخدميك الأخرى (وسمعة موقعك) للخطر. لا ترسل كلمات المرور الجديدة عبر البريد الإلكتروني هذا خطأٌ كبيرٌ لأنه يعني أنَّ الموقع يعلم كلمة مرور المستخدم، ولقد أرسلها عبر خدمة البريد (قد لا يكون الاتصال مشفرًا!)؛ وإنما عليك إرسال رابط سيسمح للمستخدم بكتابة كلمة مرور جديدة. لا تشفر (encrypt) كلمات المرور قد تظن أنَّ التشفير فكرةٌ جيدةٌ لكن تذكر أنَّ العملية قابلة للعكس، فأي شخص يملك وصولًا إلى شيفرات موقعك البرمجية سيقدر على تحويل كلمات المرور المُشفَّرة إلى أصلها. لا تستخدم MD5 من الجيد أن تستعمل طريقة تحويل غير قابلة للعكس، فهذه الطرق -مثل MD5- غير قابلة للعكس، مما يُصعِّب مهمة معرفة كلمة المرور الأصلية؛ وإذا أردت التأكد أنَّ كلمة المرور التي أدخلها المستخدم مطابقة لكلمة المرور المخزنة في قاعدة البيانات، فعليك أولًا تحويل كلمة المرور التي أدخلها بإحدى الطرق ثم مقارنتها مع الكلمة المخزنة في قاعدة البيانات. لكن يَسهُل كثيرًا توليد جداول بالقيم الأصلية والقيم المحوَّلة تسمى "جداول rainbow"، وسيتم البحث عن القيم المحولة إلى أن يُعثَر على تطابق (ينطبق المثل على SHA-1). أتت PHP 5.5 بدوال بسيطة لتحويل كلمات المرور بأمان وهي password_hash()‎ و password_verify()‎. تُستعمل الدالة الأولى لتحويل كلمة المرور إلى عبارة غير قابلة للعكس التي تستطيع تخزينها بأمان في قاعدة بياناتك. $hash = password_hash($password, PASSWORD_DEFAULT); هذا كل ما في الأمر: أول وسيط هو كلمة المرور التي تريد تحويلها، والوسيط الثاني هو الخوارزمية التي تريد استخدامها للتحويل. الخوارزمية الافتراضية هي bcrypt، ويجب أن تُخزِّن القيم الناتجة في حقل أكبر من 60 محرف في قاعدة البيانات (ربما تستعمل 255). يمكنك أيضًا تمرير PASSWORD_BCRYPT كوسيط في حال أردت أن يكون الناتج بطول 60 محرف دومًا. أما دالة password_verify()‎ فهي تقارن كلمة المرور التي أدخلها المستخدم (الوسيط الأول) بكلمة المرور المحوَّلة والمخزنة في قاعدة البيانات (الوسيط الثاني). <?php if (password_verify($password, $hash)) { // كلمة المرور صحيحة } else { // كلمة المرور غير مطابقة } الأخطاء في PHP أكثر ما يواجهه المبرمج في حياته هو الأخطاء! نحاول -نحن معشر المبرمجين- أن نتلافى حدوث الأخطاء، لكن ذلك ليس ممكنًا في الحياة العملية. علينا أن نعي أنَّ هنالك تصنيفين: الأول هو الأخطاء (errors) التي رأيتها سابقًا خلال هذه السلسلة، التي تُظهِرها الدوال المُضمَّنة في اللغة؛ والثاني هو الاستثناءات (exceptions) التي تظهر في البرامج التي تعتمد على البرمجة غرضية التوجه. تُصنَّف PHP على أنها لا تعتمد كثيرًا على الاستثناءات، وإنما تعتمد على الأخطاء. فلو حاولت مثلًا أن تطبع قيمة متغير غير معرف، فستظهر تنبيهًا لكن PHP ستكمل تفسير السكربت: $ php -a php > echo $foo; Notice: Undefined variable: foo in php shell code on line 1 أما في اللغات الأخرى التي تعتمد اعتمادًا كاملًا على الاستثناء -مثل بايثون- فستختلف النتيجة: $ python print foo Traceback (most recent call last): File “”, line 1, in NameError: name ‘foo’ is not defined التبليغ عن الأخطاء في PHP هنالك مستويات مختلفة من التبليغ عن الأخطاء في PHP، أشهر ثلاثة مستويات هي الأخطاء (errors) والتنبيهات (notices) والتحذيرات (warning). الأخطاء (errors) هي المشاكل التي تظهر في وقت التشغيل (run-time) التي يكون سببها مشاكل في الشيفرة وستسبب توقف التنفيذ. أما التنبيهات فهي رسائل إرشادية التي قد تسبب مشاكل أثناء تنفيذ السكربت، لكن التنفيذ لن يتوقف. أما التحذيرات فهي شبيهة بالأخطاء لكنها لن توقف عمل السكربت. تستطيع تغيير السلوك الافتراضي للتبليغ عن الأخطاء عبر الدالة error_reporting()‎ التي تستطيع تستطيع ضبط مستوى التبليغ عن الأخطاء أثناء التنفيذ بتمرير ثابت من الثوابت المُعرَّفة مسبقًا لمستويات الأخطاء (E_ERRORللأخطاء، E_NOTICE للتنبيهات، E_WARNING للتحذيرات). فلو كنت تريد مشاهدة الأخطاء والتحذيرات لكنك لا تريد التنبيهات، فيمكنك ضبط ذلك كالآتي: <?php error_reporting(E_ERROR | E_WARNING); تستطيع أن تخبر PHP أن تتجاهل الأخطاء في عبارة برمجية معيّنة باستخدام معامل التحكم بالأخطاء @. يمكنك وضع هذا المعامل قبل تعبير برمجي، وسيتم تجاهل أيّة أخطاء يُسبِّبها هذا التعبير. <?php echo @$foo['bar']; المثال السابق سيطبع قيمة ‎$foo['bar']‎ إن كانت موجودةً، لكنه لن يطبع شيئًا إن لم يكن المتغير ‎$foo أو المفتاح 'bar' موجودًا؛ فدون وجود معامل التحكم بالأخطاء، كان سيظهر أحد التنبيهين: PHP Notice: Undefined variable: foo أو PHP Notice: Undefined index: bar. بالطبع يمكنك استخدام العبارة الآتية لتنجب وضع معامل تجاهل الأخطاء: <?php echo isset($foo['bar']) ? $foo['bar'] : ''; الاستثناءات تمثِّل الاستثناءات جزءًا مهمًا من العديد من لغات البرمجة مثل ruby أو java، فأي شيء يحدث بشكل خاطئ في تلك اللغات -مثل فشل طلبية HTTP أو فشل الاتصال بقاعدة البيانات- فسيُرمَى (throw) استثناء يعني أنَّ هنالك خطأٌ ما. لكن PHP نفسها متساهلة جدًا بهذا الأمر، فلو فشل استدعاء الدالة file_get_contents()‎ فستحصل على FALSE وربما رسالة تحذيرية (أي من المستوى E_WARNING)؛ أما أطر العمل الحديثة، فتستعمل الاستثناءات. تبنى آلية معالجة الأخطاء في PHP على وضع التعبيرات البرمجية في كتلة try التي تريد مراقبتها من أجل الأخطاء، فلو حدث استثناءٌ ما داخل كتلة try (تحدث الاستثناءات عند "رميها" [throw]) فسيُلتَقَط باستخدام catch التي تلي كتلة try التي رمت الاستثناء. أنا متأكدٌ أنَّك تتساءل عن معنى ما سبق. ما رأيك أن نأخذ مثالًا توضيحيًا يساعد على الفهم: <?php try { $num = 10; if ($num < 20) { throw new Exception("Exception here!"); } $foo = "bar"; } catch(Exception $exception) { print "Exception!\n"; } ?> دخل مُفسِّر PHP إلى كتلة try وبدأ تنفيذ الشيفرة، وعند وصوله إلى السطر throw new Exception توقف عن تنفيذ كتلة try وانتقل إلى كتلة catch؛ لاحظ أنَّه عندما "يغادر" مُفسِّر PHP كتلة try فلن يعود إليها مطلقًا، أي أنَّ السطر ‎$foo = "bar"‎ لن يُنفَّذ. قد ترى أنَّ كتلة catch معقدة في بادئ الأمر، لكنني سأريك مثلًا يعتمد على أنَّ مفسر PHP سينتقل إلى كتلة catch المناسبة، لكن علي أولًا شرح التعبير (catch(Exception $exception. نُحدِّد في كتلة catch أنَّ الصنف هو Exception لأنَّ على PHP أن تُحدِّد أي كتلة من كتل catch يجب تنفيذها بالبحث عن الصنف الموافق للصنف الذي رُميَ. أو بالأحرى، تُجري PHP عملية instanceof (هل تذكرها من درس البرمجة كائنية التوجه؟) وهذا يعني أنَّ على الاستثناء الذي رُميَ أن يكون من الصنف المُحدَّد أو من صنف مشتق منه (أعلم تمامًا العلم أنَّ ما سبق يبدو معقدًا، لكنه أبسط بكثير مما تظن). لاحظ أنَّ جميع الاستثناءات مشتقة من الصنف Exception الذي يوفِّر وظائف أساسية، وأغلبية الدوال الموجودة في الصنف Exception هي final أي لا يمكن إعادة كتابتها في الأصناف المشتقة. يمكنك مثلًا استدعاء الدالة ‎$exception->getMessage()‎ لمعرفة رسالة الخطأ ("Exception here!‎" في المثال السابق)، أو يمكنك استدعاء getFile()‎ لمعرفة الملف الذي رمى الاستثناء. هذا المثال يوضِّح الشرح السابق: <?php class ExceptFoo extends Exception { } class ExceptBar extends ExceptFoo { } try { $foo = "bar"; throw new ExceptFoo("Baaaaad PHP!"); $bar = "baz"; } catch (ExceptFoo $exception) { echo "Caught ExceptFoo\n"; echo "Message: {$exception->getMessage()}\n"; } catch (ExceptBar $exception) { echo "Caught ExceptBar\n"; echo "Message: {$exception->getMessage()}\n"; } catch (Exception $exception) { echo "Caught Exception\n"; echo "Message: {$exception->getMessage()}\n"; } ?> ناتج السكربت السابق: Caught ExceptFoo Message: Baaaaad PHP! هذا منطقي لأننا رمينا استثناء من الصنف ExceptionFoo، ولهذا ستنتقل PHP إلى كتلة catch. جرب الآن هذه الشيفرة: <?php class ExceptFoo extends Exception { } class ExceptBar extends ExceptFoo { } try { $foo = "bar"; throw new ExceptBar("Baaaaad PHP!"); $bar = "baz"; } catch (ExceptFoo $exception) { echo "Caught ExceptFoo\n"; echo "Message: {$exception->getMessage()}\n"; } catch (ExceptBar $exception) { echo "Caught ExceptBar\n"; echo "Message: {$exception->getMessage()}\n"; } catch (Exception $exception) { echo "Caught Exception\n"; echo "Message: {$exception->getMessage()}\n"; } ?> لماذا ناتج الشيفرة السابقة مماثلة لما قبلها؟ لأنَّ PHP تنتقل إلى أول كتلة catch مُطابِقة لصنف الاستثناء أو أيّة أصناف أب له؛ ولما كان ExceptionBar مشتقٌ من ExceptionFoo، وكانت كتلة catch التابع للصنف ExceptionFoo تأتي قبل ExceptionBar، فستنفَّذ كتلة ExceptionFoo. يمكنك إعادة كتابة الشيفرة كالآتي لتفادي هذه الإشكالية: <?php class ExceptFoo extends Exception { } class ExceptBar extends ExceptFoo { } try { $foo = "bar"; throw new ExceptBar("Baaaaad PHP!"); $bar = "baz"; } catch (ExceptBar $exception) { echo "Caught ExceptBar\n"; echo "Message: {$exception->getMessage()}\n"; } catch (ExceptFoo $exception) { echo "Caught ExceptFoo\n"; echo "Message: {$exception->getMessage()}\n"; } catch (Exception $exception) { echo "Caught Exception\n"; echo "Message: {$exception->getMessage()}\n"; } ?> بقي أمرٌ بسيطٌ تجدر الإشارة إليه ألا وهو كتلة finally الموجودة في إصدار PHP 5.5 وما بعده، التي تضمن لك تنفيذ الشيفرات البرمجية الموجودة فيها دائمًا حتى لو حدث استثناءٌ ما. <?php try { complicatedCode(); } catch (NastyException $e) { handleError($e); } finally { importantCleanup(); } ?> المولدات Generators هذه ميزةٌ جديدةٌ في PHP منذ الإصدار 5.5، وهي تسمح لك باستعمال حلقة foreach للمرور على مجموعة من البيانات دون الحاجة إلى إنشاء مصفوفة في الذاكرة، الأمر الذي قد يؤدي إلى تجاوز حد استهلاك الذاكرة المسموح، أو إلى وقت معالجة كبير… إذ تستطيع كتابة دالة مولدة (generator function) التي تشبه الدوال العادية، إلا أنها بدلًا من إعادة قيمة ما، فهي "تُنتِج" (yield) قيمًا لكي يتم المرور عليها باستعمال الحلقات. مثالٌ بسيطٌ عنها هو دالة range(0, 1000000)‎ التي تولد مصفوفة فيها قيم عددية من الصفر إلى المليون، وستستهلك 100 ميغابايت من الذاكرة العشوائية. ونستطيع بدلًا من ذلك أن نكتب مولدة اسمها xrange()‎ -على سبيل المثال- وستستهلك أقل من 1 كيلوبايت! <?php function xrange($start, $limit) { for ($i = $start; $i <= $limit; $i++) { // استعملنا yield بدلًا من return yield $i; } } // استعملنا المصفوفة المُعادة من استدعاء الدالة range في foreach كالمعتاد foreach (range(1, 9) as $number) { echo "$number "; } echo "\n"; // وكذلك استعملنا نواتج المولدة xrange foreach (xrange(1, 9) as $number) { echo "$number "; } ?> الفرق بين الطريقتين في استهلاك الذاكرة فقط، ولا تأثير لها على سرعة التنفيذ. المصادر راجع صفحة Basic Coding Standard و Coding Style Guide و Logger Interface و Autoloading Standard، وتابع الجديد عبر موقع PHP-FIG. راجع مقالة ما هو Composer ولماذا يجب على كل مطور PHP استخدامه لصاحبها يوغرطة بن علي. لمزيد من المعلومات حول تحويل كلمات المرور، راجع صفحة password_hash و password_verify في دليل PHP، وهذا السؤال على stack overflow. انظر إلى قسم الاستثناءات في PHP: The Right Way، ومقالة Exception handling، وصفحة Exceptions في دليل PHP. تعلم المزيد عن المولدات عبر دليل PHP بصفحتيه Generators overview و Generator syntax.
  11. يعتبر Ansible حلًا مناسبًا لأتمتة الأعمال التقنية البسيطة، فإن وجدت نفسك تقوم بتثبيت ووردبريس بشكل متكرر ومُمل، فقد يوفّر عليك Ansible الكثير من الوقت، وباستخدام بعض الأسطر بلغة YAML (وهي لغة توصيف واضحة ومباشرة) سنقوم بأتمتة عملية تثبيت ووردبريس على خادوم يعمل بنظام تشغيل Ubuntu 14.04، وفق الخطوات بصورة أوتوماتيكية. سنستخدم خادومين: أحدهما الخادوم الباني ويتم تشغيل Ansible عليه، والآخر الذي سنقوم بتثبيت ووردبريس عليه باستخدام Ansible. المتطلبات الأولية قبل المتابعة في المقال، سنحتاج للأمور التالية: خادوم يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت Ansible على هذا الخادوم (ونشير إليه في المقال بـ الخادوم الباني). سنقوم بتسجيل الدخول إلى هذا الخادوم وجميع الأوامر والملفّات المذكورة في المقال على هذا الخادوم، خادوم آخر يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت ووردبريس عليه باستخدام Ansible (وسنشير إليه في المقال بـ خادوم ووردبريس)، حساب مستخدم عادي -على كِلا الخادومين- لا يملك صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ الأمر sudo، إضافة مفتاح SSH الخاص بالمستخدم -الذي أنشأناه على الخادوم الباني- إلى المفاتيح المصادقة authorized_keys للمستخدم الذي أنشأناه على خادوم ووردبريس، وينبغي تنفيذ هذه العملية على الخادوم الباني ورفع المفاتيح إلى خادوم ووردبريس. تنفيذ أوامر sudo بدون تأكيد باستخدام كلمة مرور إنّ من الأسرع -ولكن أقل أمانًا- تنفيذ أوامر sudo على خادوم ووردبريس بدون الحاجة لإدخال كلمة مرور تأكيد في كل مرّة. لإعطاء المستخدم على خادوم ووردبريس هذه الإمكانية، سنقوم بتعديل ملف sudoers باستخدام الأمر visudo على سطر الأوامر: $ visudo ومن ثم سنضيف السطر التالي في نهاية الملف: sammy ALL=(ALL) NOPASSWD: ALL ملاحظة: لا تنس استبدال اسم المستخدم (sammy في هذه الحالة) باسم المستخدم الموجود لديك، وتأكد من وضع السطر في نهاية الملف حتى لا يتم تجاوزه بالصلاحيات الافتراضية الموجودة في الملف. نصيحة: قم دومًا باستخدام الأمر visudo عند تعديل ملف sudoers، لأن الأمر سيقوم بالتحقق من التعديلات قبل حفظ الملف ويحميك بالتالي من ارتكاب أخطاء في الملف قد تؤدي إلى منعك من الدخول. حالما تنتهي من تنفيذ العملية السابقة سيغدو بإمكانك تنفيذ الأمر التالي على خادوم ووردبريس بدون إدخال كلمة مرور لتأكيده: $ sudo echo "Hello" وفي بقية المقال، تستطيع تنفيذ الأمر ansible-playbook بدون المُعامل K- كي تتجنب الحاجة لإدخال كلمة المرور للتأكيد بشكل يدوي: $ ansible-playbook playbook.yml -i hosts -u sammy الخطوة الأولى: تثبيت Ansible سنقوم الآن بتثبيت Ansible على الخادوم الباني، ونبدأ بتسجيل الدخول عبر SSH إلى الخادوم وتنفيذ الأمر التالي: $ sudo apt-get install ansible -y وتستطيع التأكد من تثبيت Ansible بتنفيذ الأمر: $ ansible --version حيث ينبغي أن يكون الخرج مشابهًا (وليس بالضرورة مطابقًا) لما يلي: ansible 1.5.4 الخطوة الثانية: إعداد بنية الملفات الآن وبعد أن انتهينا من تثبيت Ansible، دعونا نقوم بإعداد بنية الملفات من أجل Ansible playbook. سنقوم بإنشاء مجلّد على النحو التالي: $ cd ~ $ mkdir wordpress-ansible && cd wordpress-ansible سنقوم الآن بإنشاء ملفّين: الأول يدعى playbook.yml (حيث سنقوم بكتابة الأوامر الخاصة بتثبيت ووردبريس فيه) والثاني يدعى hosts (وهذا يُخبر Ansible عن الخواديم التي سيتم تنفيذ الأوامر عليها): $ touch playbook.yml $ touch hosts إنّ من الأفضل فصل الأوامر بحسب الأدوار، ومن الممكن اعتبار الأدوار كأجزاء من الممكن إعادة استخدامها، وسنقوم في هذا المشروع بإنشاء 4 أدوار: server php mysql wordpress سنقوم بإنشاء مجلد الأدوار في الجذر الرئيسي للمجلد الذي أنشأناه سابقًا wordpress-ansible/~ بتنفيذ الأمر التالي: $ mkdir roles && cd roles والآن سنقوم بتجهيز الأدوار باستخدام أداة من أدوات Ansible تدعى ansible-galaxy، حيث سنقوم من أجل كل دور بتنفيذ الأمر ansible-galaxy init كالتالي: $ ansible-galaxy init server $ ansible-galaxy init php $ ansible-galaxy init mysql $ ansible-galaxy init wordpress ستلاحظ بأن هذا الأمر سيقوم بإنشاء هيكل ملفات متكامل لكل دور من الأدوار، وهذه الخطوة هي إحدى الأمور التي ينصح بها في توثيق Ansible. ما يهمّنا غالبًا هو التعامل مع محتوى ملف tasks/main.yml لكل دور. عند الوصول إلى هذه المرحلة سيكون لدينا الهيكل التالي: [.] |_ playbook.yml |_ hosts |_ [roles] |_ [server] |_ ... |_ [php] |_ ... |_ [mysql] |_ ... |_ [wordpress] |_ ... الخطوة الثالثة: إنشاء الـ Playbook سنقوم الآن بكتابة الأوامر التي ستقوم بتثبيت ووردبريس على خادوم ووردبريس. ملف المخزون hosts يُخبر هذا الملف Ansible بالخواديم التي نرغب بتثبيت ووردبريس عليها، ومن الممكن تنفيذ الأوامر للخواديم أو مجموعة الخواديم المعرّفة في ملف المخزون hosts. سنقوم بتحرير ملف hosts باستخدام محرر nano أو أي محرر آخر تفضّله وكتابة التالي: [wordpress] wordpress_server_ip ملاحظة: من الممكن وضع أي عدد نرغب به من العناوين الرقمية IPs تحت مجموعة [wordpress]. سيؤدي هذا إلى تنفيذ الأوامر على جميع الخواديم المذكورة على افتراض أننا نملك صلاحية استخدام هذه الخواديم. سيمكّننا هذا من تثبيت ووردبريس على أي عدد من الخواديم دفعة واحدة. ملف Playbook يمكن اعتبار هذا الملف كتعريف لتطبيق ووردبريس الذي سنقوم بتثبيته. سيحتوي الملف على جميع الأدوار التي قمنا بإنشائها بغرض تجهيز تطبيق مفيد (ووردبريس في حالتنا). سنقوم بداية بتحرير الملف باستخدام محرر nano أو أي محرر آخر ترغب به: $ nano ~/wordpress-ansible/playbook.yml ومن ثم سنضيف المحتويات التالية إلى الملف، والتي ستُخبر Ansible أية أدوار سيتم تنفيذها على أية خواديم (سيتم تنفيذ الأدوار المذكورة في حالتنا على مجموعة العناوين الرقمية المدرجة في مجموعة wordpress المسجّلة في ملف hosts الذي أنشأناه سابقًا): - hosts: wordpress roles: - server - php - mysql - wordpress والآن لنعد إلى الجذر الرئيسي: $ cd ~/wordpress-ansible/ سنتأكد الآن من أنه من الممكن إجراء اتصال ما بين الخادوم الباني وخادوم ووردبريس من خلال تنفيذ ملف playbook الذي لن يقوم بأي شيء سوى التحقق من الاتصال: $ ansible-playbook playbook.yml -i hosts -u sammy -K ستُطالب بإدخال كلمة المرور لتأكيد الأمر، ولا تنس أن تقوم باستبدال اسم المستخدم بالموجود لديك. سيظهر لنا خرج يشبه التالي عند تنفيذ الأمر: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] PLAY RECAP ******************************************************************** 188.166.68.134 : ok=1 changed=0 unreachable=0 failed=0 والذي سيؤكد لنا بأن الاتصال قد تم بنجاح، دون أن يتم تنفيذ أي تعديلات لأننا لم نقم بتحديد أي أوامر لتنفيذها حتى الآن. إن فشل تنفيذ الأمر فتأكّد من أن باستطاعتك تسجيل الدخول إلى خادوم ووردبريس من الخادوم الباني باستخدام مفتاح SSH الذي قمت بنسخه في البداية. الخطوة الثالثة: إنشاء الأدوار دور Server سنقوم بداية بتعريف الأوامر التي سيتم تنفيذها على الخادوم ولهذا الغرض سنقوم بتحرير أوامر دور server. ستقوم الأوامر التي سنصرّح عنها بتثبيت جميع البرمجيات التي سنحتاجها على السيرفر الهدف. نبدأ بتنفيذ الأمر التالي: $ nano roles/server/tasks/main.yml قم بإضافة المحتويات التالية وتأكد من وجود سطر واحد فقط يحتوي على --- (حيث يوجد هذا السطر سلفًا بشكل افتراضي): --- - name: Update apt cache apt: update_cache=yes cache_valid_time=3600 sudo: yes - name: Install required software apt: name={{ item }} state=present sudo: yes with_items: - apache2 - mysql-server - php5-mysql - php5 - libapache2-mod-php5 - php5-mcrypt - python-mysqldb سيقوم المحتوى السابق بما يلي: تحديث خبء apt-cache (تنفيذ الأمر apt-get update)، تثبيت Apache ،MySQL ،PHP وبرمجيات أخرى مرتبطة باستخدام apt-get install. وإن كنت مهتمًّا بمعرفة تفاصيل ما نقوم بتثبيته، فيمكنك الاطلاع على هذا المقال حول تثبيت LAMP على Ubuntu 14.04 بشكل يدوي. سنقوم الآن بتنفيذ ansible-playbook مرة أخرى على النحو التالي: $ ansible-playbook playbook.yml -i hosts -u sammy -K ويفترض هذه المرة أن يكون الخرج بما يشبه التالي: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] TASK: [server | Update apt cache] ********************************************* ok: [188.166.68.134] TASK: [server | Install required software] ************************************ changed: [188.166.68.134] => (item=apache2,mysql-server,php5-mysql,php5,libapache2-mod-php5,php5-mcrypt,python-mysqldb) PLAY RECAP ******************************************************************** 188.166.68.134 : ok=3 changed=1 unreachable=0 failed=0 وبعد التنفيذ، ينبغي أن تكون قادرًا على استعراض الصفحة الافتراضية لـ Apache عبر فتح العنوان http://wordpress_server_ip في المتصفح. ملاحظة: إن توقّف تنفيذ الأمر بشكل نهائي عند سطر [TASK: [server | Update apt cache فمن المحتمل أن يكون هناك نقص في الصلاحيات المطلوبة على الخادوم الهدف، لذا تأكّد من أن الوصول باستخدام sudo تم إعداده بشكل صحيح على خادوم ووردبريس. دور PHP سنقوم الآن بتجهيز الأوامر التي تستهدف PHP، ولهذا الغرض سنقوم بتحرير الملف الخاص بهذا الدور: $ nano roles/php/tasks/main.yml ومن ثم سنضيف المحتوى التالي (تأكّد من وجود سطر واحد فقط يحتوي على --- في بداية الملف): --- - name: Install php extensions apt: name={{ item }} state=present sudo: yes with_items: - php5-gd - libssh2-php سيقوم المحتوى السابق بتثبيت الملحقات extensions الضرورية لـ PHP وهي: php5-gd و libssh2-php. دور MySQL سنقوم الآن بإعداد قاعدة بيانات MySQL لموقع ووردبريس، وذلك في دور mysql. سنحتاج من أجل القيام بذلك إلى بعض المتغيّرات، والتي من الممكن تخزينها في ملف المتغيرات الافتراضية defaults/main.yml: $ nano roles/mysql/defaults/main.yml سنضيف في الملف اسم قاعدة البيانات، اسم المستخدم الخاص بالقاعدة، كلمة المرور الخاصة بالمستخدم وبنفس الترتيب، ولا تنس أن تستخدم كلمة مرور معقّدة لأغراض أمنية: --- wp_mysql_db: wordpress wp_mysql_user: wordpress wp_mysql_password: wp_db_password والآن نستخدم nano لتحرير ملف المهام: $ nano roles/mysql/tasks/main.yml ونضيف المحتوى التالي: --- - name: Create mysql database mysql_db: name={{ wp_mysql_db }} state=present - name: Create mysql user mysql_user: name={{ wp_mysql_user }} password={{ wp_mysql_password }} priv=*.*:ALL يقوم المحتوى السابق بـ: إنشاء قاعدة بيانات MySQL، إنشاء مستخدم MySQL، إعطاء المستخدم صلاحية الوصول إلى قاعدة البيانات. وكما ترى فسيتم استخدام قيم المتغيرات بشكل تلقائي من ملف defaults/main.yml عند تنفيذ الأوامر. ملاحظة: توفّر أدوات Ansible أداة ansible-vault والتي تسمح بتخزين كلمات المرور بصورة مشفّرة حتى لا تكون قابلة للقراءة في الملف، ولكن الحديث عن هذا خارج إطار حديثنا الآن. دور WordPress والآن نأتي للحظة التي كنا ننتظرها.. تثبيت ووردبريس. نبدأ بتحرير ملف المهام كالمعتاد: $ nano roles/wordpress/tasks/main.yml وسنقوم بنسخ المحتوى التالي إليه: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no sudo: yes سيقوم المحتوى السابق بتحميل ووردبريس إلى مجلد tmp/ (ويمكن للحذرين أن ينتبهوا إلى أننا قمنا بتعطيل التحقق من الشهادة الأمنية، لأنه سيمنع عملية التحميل). بعد اكتمال التحميل سنقوم بفك ضغط الملف إلى var/www/، وهو المسار الذي يستخدمه Apache لتخزين محتوى الويب، وبالتالي سنضيف الجزء التالي لمحتوى الملف أيضًا: - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes وبعد أن يتم فك ضغط الملفات، سنقوم بتحديث مسار الجذر الافتراضي DocumentRoot في ملف إعدادات Apache كي يشير إلى موقع ووردبريس: - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache sudo: yes لاحظ أننا استخدمنا الكتلة notify، والتي نحتاجها عند الرغبة بإعادة تشغيل خدمات بعد أن يتم تنفيذ مهمّة بنجاح، ولا يتم تنفيذ معالجات notify إلا عندما يحصل تغيير على حالة المهمّة. سنقوم بإضافة المعالج الخاص بنا لإعادة تشغيل Apache باستخدام restart apache ويتم ذلك في الملف roles/wordpress/handlers/main.yml: $ nano roles/wordpress/handlers/main.yml نضيف المحتوى التالي: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ويتم تنفيذ هذه المهمّة عندما تتغير حالة المهمّة التي تحتوي على الكتلة notify: restart apache، مما يؤدي إلى إعادة تشغيل الخدمة. إعداد ووردبريس بالعودة إلى roles/wordpress/tasks/main.yml، سنقوم الآن بتجهيز إعدادات موقع ووردبريس، فنقوم أولًا بنسخ ملف الإعدادات config الافتراضي: - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes ومن ثم نقوم بتغيير بعض الثوابت في الملف لتتطابق مع معلومات الاتصال بقاعدة البيانات: - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes حيث ستقوم المهمّة بجلب معلومات الاتصال بالقاعدة من ملف المتغيّرات الافتراضية الذي قمنا بتحريره سابقًا. بعد الانتهاء من الخطوات السابقة بنجاح، سيكون قد أصبح لدينا ملفّين لدور wordpress، وفيما يلي النسخة الكاملة لمحتوى الملفّين.. ملف roles/wordpress/tasks/main.yml: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes ملف roles/wordpress/handlers/main.yml: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ونكون قد انتهينا. لنقم الآن بتشغيل ansible-playbook لآخر مرة لإعداد موقع ووردبريس: $ ansible-playbook playbook.yml -i hosts -u sammy -K وبعد تنفيذ الأمر ينبغي أن نكون قادرين على تصفّح الموقع عبر طلب عنوانه http://your_server_ip في المتصفح ويمكن الآن متابعة إعداد موقع ووردبريس بشكل يدوي عند هذه المرحلة. الخلاصة تهانينا! ستتمكن الآن من تثبيت مواقع ووردبريس على أي عدد من الخواديم التي تعمل بنظام تشغيل Ubuntu باستخدام أمر واحد: $ ansible-playbook playbook.yml -i hosts -u sammy -K وكل ما تحتاج للقيام به هو إضافة العنوان الرقمي IP إلى قائمة الخواديم المستهدفة في ملف hosts والتأكّد من أن الصلاحيات قد تم إعدادها مسبقًا على الخادوم الهدف. تناولنا في المقال بصورة سريعة كيفية استخدام Ansible لتثبيت مواقع ووردبريس بشكل اوتوماتيكي، وقد تكون مهتمًّا ببعض التحسينات الإضافية الممكنة: تعلّم كيفية استضافة أدوارك الخاصة في الـ Ansible Galaxy. أتمتة عملية الإعداد النهائية لموقع ووردبريس حتى لا يكون هناك حاجة للقيام بأي إعداد يدوي للموقع المطلوب إطلاقًا. ترجمة -وبتصرّف- للمقال How To Automate Installing WordPress on Ubuntu 14.04 Using Ansible لصاحبه Christo Crampton.
  12. حمل عام 2015 حدثًا مهمًا لمجتمع PHP، فبعد أحد عشر عامًا بعد إصدار PHP 5.0 تم إطلاق الإصدار الرئيسي الجديد ألا وهو PHP 7. وسنتحدث في هذا الدرس عمّا حمله هذا الإصدار من تغييرات وإضافات. لكن أين اختفى إصدار PHP 6؟ إذا لم تعمل منذ فترة على PHP، فربما تتساءل ما الذي حدث لإصدار PHP 6، لماذا قفزوا مباشرةً من PHP 5 إلى PHP 7؟ الجواب باختصار هو الفشل الذريع في PHP 6. فالميزة الأساسية للإصدار 6 هي الدعم المُضمّن لمحارف يونيكود وذلك لأنَّ PHP تُستخدَم بشكل رئيسي في تطوير الويب، وسنحتاج إلى استخدام محارف يونيكود في الويب، ولهذا كان التوجه الأساسي هو جلب دعم محارف يونيكود إلى PHP. للأسف، واجهت تلك الخطة الطموحة مشاكل أكبر من تلك المتوقعة، فكان من المفترض تحويل جزء كبير من الشيفرة البرمجية لكي تدعم محارف يونيكود في أساس اللغة وفي الإضافات (extensions) المهمة، لكن تلك المهمة كانت مملة وصعبة؛ وهذا ما أبطأ من تطوير الميزات الأخرى في اللغة، مما أزعج الكثير من مطوري PHP. وبعد فترة ظهرت عقباتٌ أخرى أدّت إلى تقليل الاهتمام بتطوير دعم مُضمّن (أي مدمج في اللغة) لمحارف يونيكود؛ مما أدى في النهاية إلى إيقاف العمل على المشروع. لكن كُتِبَت مقالات وكتب عن PHP 6 ودعمها لمحارف يونيكود قبل إيقاف المشروع، لهذا سُمِّي الإصدار الجديد PHP 7 لرفع الالتباس. حسنًا، لنترك الماضي الحزين وراء ظهورنا ولننظر ما الذي أتت به PHP 7. تحسينات في الأداء أحد أكبر الأسباب التي تجعلك تستعمل PHP 7 في خودايمك هو تحسينات الأداء التي أتت PHP 7 بها، حيث أشارت الإحصائيات الرسمية إلى أنَّ أغلبية التطبيقات العملية التي تستعمل PHP 5.6 ستعمل أسرع بضعفين على الأقل فيما لو استخدمت PHP 7. يمكنك إلقاء نظرة على العرض الذي قدمه Rasmus Lerdorf لتفاصيل أكثر عن الإحصائيات حول الأداء، هذه صورة مأخوذة من ذاك العرض التي تُظهِر نتائج تشغيل ووردبريس على مختلف إصدارات PHP: تستطيع PHP 7 معالجة ضعف الطلبيات في الثانية تقريبًا، الذي يُمثِّل عمليًا تحسينًا قدره 100% في الأداء في المواقع التي تستعمل ووردبريس. هنالك تحسينات أيضًا في مقدار استهلاك PHP 7 للذاكرة، حيث أنَّ تحسين البنى الداخلية للغة كان أحد الأسباب التي أدت إلى تحسين الأداء وتقليل استخدام الذاكرة لتفسير الشيفرات. المشاكل في التوافقية مع الإصدارات السابقة حدثت عدِّة تغييرات في بنية PHP في الإصدار السابع، التي يؤدي بعضها إلى عدم توافقية مع ما سبقها من الإصدارات. أهم تلك التغييرات هي حذف الدوال والعناصر المهملة (deprecated) خصيصًا وسوم البداية والنهاية التي تشبه ASP (أي ‎<%‎ و ‎<%=‎ و ‎%>‎) حيث حُذِفَت بالإضافة إلى وسم <script language="php"‎>، تأكد أنَّك تستعمل الوسم ‎<?php بدلًا عنهما. الدوال التي أُهمِلَت في الإصدارات السابقة تم حذفها في PHP 7 مثل الدالة split، والدوال التي تتبع للإضافة ereg (أي جميع الدوال التي تبدأ بالسابقة ereg_‎). يجب استخدام الدوال التي تتبع للإضافة PCRE بدلًا عنها (أي الدوال التي تبدأ بالسابقة preg_‎) والتي توفر ميزات أكثر. وحُذِفَت جميع دوال الإضافة mysql أيضًا (أي الدوال التي تبدأ بالسابقة mysql_‎) والتي أهمِلَت منذ الإصدار 5.5؛ عليك استخدام دوال إضافة mysqli التي تبدأ بالسابقة mysqli_‎ بدلًا منها. طُبِّقَت أيضًا السياسة الموحدة لتفسير المتغيرات، التي حلّت العديد من المشاكل التي تتعلق بالتعابير التي تحتوي على متغيرات. الميزات الجديدة هذا هو الجزء المسلي هنا، لنتحدث عن أكثر الميزات إثارةً التي ستحصل عليها عند التحديث إلى PHP 7. معاملين جديدين يمكن استخدام معامل spaceship (<=> أو معامل المقارنة المدمج) لجعل تعبير المقارنة أقصر ما يمكن. انظر إلى هذا المثال: a<=>b ستكون نتيجة التعبير السابق 1- إن كان ‎a$ أصغر من ‎$b، و 0 إذا كان ‎$aيساوي ‎$b، و 1 إذا كان ‎$a أكبر من ‎$b. ويمكن اعتباره اختصارًا للتعبير الآتي: (a < b)? -1 : ((a > b) ? 1 : 0)) تحديد أنواع المعاملات والقيم المُعادة إحدى أهم الميزات الجديدة المنتظرة التي أتت بها PHP 7 هي تحديد أنواع معاملات (parameters) للدوال. التي تعني أنَّنا تستطيع تحديد ما هو نوع المعامل الذي ستقبله الدالة والذي سيكون إما int (للأعداد الصحيحة) أو float (للأعداد العشرية) أو string (للسلاسل النصية) أو bool (للقيم المنطقية true أو false أو ما يكافئها). لا يكون الالتزام بأنواع المعاملات المُحدَّدة إجباريًا افتراضيًا، أي non-strict، وهذا يعني لو مررت (int(1 إلى دالة تتطلب عددًا عشريًا (float) فستصبح قيمة الوسيط الممرر (float(1.0 تلقائيًا، أما لو مررت (float(1.5 إلى دالة تتطلب عددًا صحيحًا (int)، فعندها ستصبح القيمة (int(1. ميزات أخرى متفرقة أصبحت PHP 7 تدعم محرف تهريب (escaping) جديد هو ‎\u الذي يسمح لنا باستعمال محارف يونيكود (بالنظام الست عشري) داخل سلاسل PHP النصية، ويستعمل بالشكل {‎\u{CODE، المثال الآتي يُظهِر رمز القلب: echo “\u{1F49A}”; أضيفت أيضًا ميزة إنشاء أصناف مجهولة (Anonymous classes) التي تُفيد في حال أردنا إنشاء كائن وحيد من الصنف فقط: الإصدارات قبل PHP 7 class Logger { public function log(msg { echomsg; } } $util->setLogger(new Logger()); في الإصدار PHP 7 $util->setLogger(new class { public function log($msg) { echo $msg; } }); المصادر لمزيدٍ من المعلومات حول الإضافات التي حدثت في PHP 7، راجع التدوينة Getting Ready for PHP 7 لصاحبتها Erika Heidi. والتدوينة Introduction To PHP 7: What’s New And What’s Gone لصاحبها Vilson Duka، وصفحة New PHP 7 features في دليل PHP. إذا أردت شرحًا لما حُذِفَ في PHP 7، فانظر إلى صفحة Backward incompatible changes في دليل PHP هنالك مرجع كامل لتغيرات PHP موجودٌ في الصفحة الآتية على github، وانظر كذلك إلى PHP RFC.
  13. php 101

    ما هي PHP؟ PHP هي اختصارٌ للعبارة PHP: Hypertext Preprocessor؛ وهي معروفةٌ كلغة سكربتات (scripting language) مُفسَّرة (interpreter) من جهة الخادوم تُستعمَل لتطوير الويب؛ وهذا يعني أنَّ PHP تُستعمَل على الخادوم لتوليد صفحات الويب الديناميكية. ما يُقصَد بصفحات الويب الديناميكية هي تلك الصفحات التي تُنشَأ أو تُعدَّل من الخادوم قبل إرسالها إلى العميل. إن لم تكن تعرف ما هو الخادوم وما هو العميل، فافتح لسانًا جديدًا في متصفح الويب الخاص بك واكتب فيه academy.hsoub.com، وبهذا يُصبِح متصفحك "عميلًا" (client) والمكان الذي تأتي منه صفحة الويب المطلوبة هو "الخادوم" (خادوم الويب أو web server). يمكن تضمين سكربتات PHP في مستندات HTML، وهي لغةٌ سهلة التعلم، وتشبه بنيتها كثيرًا البنية القاعدية للغات C و Java و Perl. التثبيت يمكنك بسهولة تثبيت WAMP (على نظام ويندوز) أو LAMP (على لينُكس) أو حزمة البرمجيات XAMPP (التي تعمل على ويندوز، ولينُكس، وماك) وذلك تبعًا لنظام تشغيل حاسوبك، راجع مقال كيفية تنصيب ووردبريس محليا باستخدام MAMP لمزيدٍ من المعلومات عن MAMP. تجربة الأمثلة يمكنك تجربة سكربتات PHP عبر تثبيت خادم أباتشي مع دعم PHP يدويًا أو عبر تثبيت حزم جاهزة كالتي ذكرناها آنفًا، لكن توفِّر PHP لك طريقتين لتنفيذ الملفات: عبر سطر الأوامر، وعبر الخادوم المدمج مع PHP؛ وسنشرح كلا الطريقتين في هذا الدرس. استخدام الخادوم المدمج وفَّرت PHP من الإصدار 5.4.0 خادومًا مدمجًا معها يُسهِّل تجربة السكربتات دون عبء تثبيت خادوم ويب كامل مثل أباتشي وضبطه؛ لكن الغرض منه هو تجربة البرامج فقط وليس مصممًا للاستعمال كخادوم إنتاجي على الشبكة. ستُخدَّم الملفات الموجودة في مجلد العمل الحالي عبر ذاك الخادوم المدمج، الذي يُشغَّل كالآتي: cd ~/public_html php -S localhost:8000 PHP 5.5.9-1ubuntu4.5 Development Server started at Fri Jan 8 13:58:31 2016 Listening on http://localhost:8000 Document root is /home/user/public_html Press Ctrl-C to quit. الأمر php -S localhost:8000 سيشغِّل الخادوم في مجلد العمل الحالي (‎~/public_html) وسيكون متاحًا للوصول من الجهاز المحلي فقط، وسيعمل على المنفذ 8000؛ إن أردت أن يعمل على البطاقات الشبكية، فضع 0.0.0.0 بدلًا من localhost؛ اضغط على Ctrl+C لإيقاف الخادوم. أنشِئ الملف test.php وضع فيه المحتويات الآتية لتجربه: <?php // هذه تجربة لتنفيذ سكربتات PHP من الخادوم المدمج echo "test"; ?> افتح الآن المتصفح وأدخِل http://localhost:8000/test.php في شريط العنوان، وستحصل على نتيجة مشابهة لما يلي: يجدر بالذكر أنَّه بإمكانك تخديم صفحات HTML الثابتة عبر هذا الخادوم، وليس بالضرورة أن تكون الصفحة بلاحقة PHP. ملاحظة: اختر رقمًا أكبر من 1024 كرقم للمنفذ الذي سيستعمله الخادوم، كي لا تحتاج إلى امتيازات إدارية لتشغيله. استعمال سطر الأوامر من البدهي أن تستطيع تنفيذ شيفرات PHP (كغيرها من لغات السكربتات) من سطر الأوامر؛ كل ما عليك فعله هو استدعاء السكربت من الأمر PHP كالآتي: php ~/public_html/test.php أو يمكن تضمين ما يسمى shebang في الأنظمة الشبيهة بيونكس (كنظامَي لينُكس وماك) في بداية السكربت ليبدو كما يلي: #!/usr/bin/php <?php // هذه تجربة لتنفيذ سكربتات PHP من سطر الأوامر echo "test"; ?> وعندها تستطيع تنفيذ السكربت مباشرةً دون استدعاء مفسر PHP كما يلي: ~/public_html/test.php ملاحظة: لا تنسَ إعطاء الملف امتيازات التنفيذ قبل محاولة تنفيذه: chmod +x ~/public_html/test.php يمكن أيضًا تنفيذ الشيفرات تفاعليًا، عبر تنفيذ الأمر php -a ثم كتابة الأوامر تفاعليًا كما يظهر في الصورة الآتية (لاحظ أنه بإمكانك استعمال زر tab لإكمال أسماء الدوال والأصناف وغيرها): البنية القاعدية للغة لنأخذ مثالًا بسيطًا لنشرح فيه القواعد الأساسية للكتابة. <?php /* author: Abd Allatif Eymsh website: academy.hsoub.com version: 1.0 date: 22 12 2015 */ // هذا تعليقٌ ذو سطرٍ وحيد // يتم تجاهل التعليقات من المفسِّر $variable = 'variable'; // نستعمل عبارة echo لطباعة الجمل echo "string"; echo $variable; ?> انسخ ما سبق والصقه في ملفٍ باسم index.php في مجلد htdocs (في نظام ويندوز) أو www (في لينُكس) أو أي مكان تريده إن كنت تستعمل الخادوم المدمج، ثم افتح ذاك الملف في متصفح الويب (بعد أن تُشغِّل الخادوم) وستحصل على النتيجة "stringvariable"، لنُقسِّم الآن الملف ولنشرح بنيته. تُكتَب شيفرات PHP في ملفٍ بامتداد ‎.php تُكتَب شيفرات PHP بين وسمَيّ البداية ‎<?php والنهاية ‎?>‎ وكما في لغتَيّ C أو Perl، تتطلب PHP أن تنتهي التعليمات البرمجية بفاصلة منقوطة ";" يُشير الرمز $ إلى متغير (variable)، سنتحدث عن المتغيرات في هذا الدرس لاحقًا تكافئ علامات الاقتباس المفردة والمزدوجة بعضها (لكنها ليس لها نفس المعنى تمامًا، سنشرح الاختلاف البسيط لاحقًا) يُستعمَل الأمر echo لطباعة البيانات التعليقات التعليقات جزءٌ من البرنامج لا ينفِّذها مُفسِّر اللغة؛ وهي ملاحظاتٌ لكي يتذكر القارئ أو يفهم أمرًا برمجيًا ما لاحقًا. وهنالك نوعان من التعليقات: التعليقات ذات السطر الوحيد: وهذه التعليقات قصيرةٌ تمتد لسطرٍ وحيدٍ فقط، وتبدأ عادةً بالرمز "//"، ولا بأس أن يكون قبلها تعليماتٌ برمجية، لكن التعليق سينتهي مع نهاية السطر؛ ويستحق أن نذكر أننا نستطيع أن نبدأ التعليقات ذات السطر الوحيد برمز المربع (#) بدلًا من شرطتين مائلتين. التعليقات متعددة الأسطر: وهي تعليقاتٌ طويلة، قد تمتد لأكثر من سطر؛ وتوضع بين علامة البداية ‎/*‎ وعلامة النهاية ‎*/‎، ومن استعمالات هذا النوع من التعليقات أيضًا هي تعطيل جزء من الشيفرة ﻷغراض التجربة. يمكنك أن ترى نوعَيّ التعليقات السابقين في المثال أعلاه. المتغيرات تسمح لك المتغيرات بتخزين ومعالجة البيانات في السكربتات، ويمكنك اعتبارها شبيهةً بالمتغيرات التي تستعملها في الرياضيات؛ إذ أنَّ المتغير -ببساطة- هو حاويةٌ تحوي قيمةً معيّنة؛ أُطلِقَت تسمية "المتغيرات" عليها لأنها القيمة المُسنَدة إليها قد تتغير أثناء تنفيذ السكربت، وقابلية التغير تلك تجعل من المتغيرات أداةً مفيدةً جدًا. وكما ذكرنا سابقًا، يبدأ اسم المتغير بالإشارة $. هذه بعض الأمثلة عن أسماءٍ صحيحةٍ للمتغيرات: ‎$simple ‎$_start_with_underscore ‎$_includes_numbers_23 ‎$_includes_UPPERCASE_2 ‎$_23_it_is_valid ملاحظة: لا يمكنك بدء اسم المتغير برقمٍ كالاسم الآتي ‎$2_invalid_variable_name، ولا يمكن أيضًا أن تستعمل الشرطة "-" في اسمه. أنواع البيانات أنواع البيانات (data types) هي أنواع المتغيرات في PHP؛ وأنواعُ البياناتِ البسيطة في PHP هي: الأعداد الصحيحة (integers) الأعداد ذات الفاصلة (floats) السلاسل النصيّة (strings) القيم المنطقية البوليانية (صح [true] أو خطأ [false])؛ وهنالك أنواع بياناتٍ أخرى مثل الكائنات (objects) والمصفوفات (arrays) سنتحدث عنها لاحقًا في هذه السلسلة. ملاحظة: إن كانت لديك معلوماتٌ سابقة عن إحدى لغات البرمجة التي تُحدِّد نوع البيانات المُخزَّنة في المتغيرات (أي strongly typed)، فاعلم أنَّ PHP هي لغةٌ لا تتطلب منك تحديد النوع (أي أنها loosely typed)؛ فلا تحتاج إلى أن تخبر اللغة ما نوع البيانات التي ستُخزَّن في المتغير. الثوابت الثابت هو مُعرِّف (أي اسم) يحمل قيمةً معيّنة، وكما يوحي اسمه، لن تتغير قيمته أثناء تنفيذ السكربت بعد أن تُعرَّف لأول مرة، واسمه حساسٌ لحالة الأحرف، وتُستعمَل الأحرف الكبيرة فيه عادةً؛ وله نفس قواعد تسمية المتغيرات (لا يجوز أن يبدأ برقم، أو يحتوي على شرطة…)، لكن لا يوضع الرمز $ قبله. <?php /* author: Abd Allatif Eymsh website: academy.hsoub.com version: 1.0 date: 22 12 2015 */ // هذا تعليقٌ ذو سطرٍ وحيد $variable = 'variablename'; echo "string"; echo $variable; define( "MY_CONSTANT", "19" ); define('PI', 3.14); echo PI; echo MY_CONSTANT; ?> تكون PI و MY_CONSTANT ثوابت في المثال السابق. ملاحظة: يمكن استعمال الكلمة المحجوزة const لتعريف الثوابت بدلًا من الدالة define()‎ في إصدار PHP 5.3 وما بعده كما يلي: <?php // تعمل في إصدار PHP 5.3 const CONSTANT = 'Hello World'; echo CONSTANT; ?> لكن لا يمكن تعريف الثوابت باستخدام const داخل الدوال أو الحلقات، لأنها تُعرَّف في وقت التصريف (compile-time). المعاملات يأخذ المعامل قيمةً أو أكثر (أو "تعبيرًا" [expressions] كما نقول في الاصطلاحات البرمجية) ويُنتِج قيمةً أخرى. يمكن أن تُجمَّع المعاملات بناءً على عدد القيم التي تأخذها، فمثلًا المعاملات الأحادية (unary operators) تأخذ قيمةً واحدةً فقط (مثل معامل الزيادة الذي شرحناها أدناه)، والمعاملات الثنائية تأخذ قيمتين مثل المعاملات الحسابية البسيطة (الجمع والطرح والضرب…) وتُصنَّف أغلبية المعاملات في PHP ضمن هذا القسم؛ وهنالك معامل ثلاثي وحيد يأخذ ثلاث قيم سنشرحه في درسٍ لاحق. هنالك عددٌ كبيرٌ من المعاملات في لغة PHP، أهمها: المعاملات الحسابية الإسناد معاملات الأعداد الثنائية (Bitwise) معاملات المقارنة الزيادة أو الإنقاص معامل السلاسل النصية المعاملات الحسابية هي تلك المعاملات التي تستعملها في الحسابات الرياضية، مثل الجمع (+)، والطرح (-)، والضرب (*)، والقسمة (/)، وباقي القسمة (%)؛ مثال: $a = 4 + 5; // + هو معامل حسابي لاحظ الفرق بين المعاملين / و %، إذ أنَّ / هو معامل القسمة بينما % هو باقي القسمة؛ أي ‎8 /5‎ = 1.6 ‎‎، بينما ‎8 % 5 = 3 (إذ أنَّ ‎8 = 5 *1 +3، فإن باقي القسمة هو 3). أما معامل الإسناد، فيسند القيم إلى المتغيرات، وهو إشارة = كما في المثال الآتي: ‎$a = 4;‎. تجري المعاملات الثنائية العمليات الحسابية على البتات الموجودة في الأعداد الصحيحة، وهي & ‏(and)، و | ‏(or)، و >> (الإزاحة نحو اليسار)، و << (الإزاحة نحو اليمين)، و ^ ‏(XOR)، و ~ (NOR)؛ مثال على ذلك هو ‎14 & 3 = 2‎، لأنَّ ‎00001110 & 00000011 = 00000010‎. أما معاملات المقارنة، فهي -كما يدل اسمها- تقارن بين قيمتين؛ يُظهِر الجدول الآتي معاملات المقارنة الشائعة: المثال اسم المعامل النتيجة ‎$a == $b المساواة TRUE إن كان المتغير ‎$a مساويًا بالقيمة إلى المتغير ‎$b ‎$a === $b مطابقة TRUE إن كان المتغير ‎$a مساويًا المتغير ‎$b بالقيمة والنوع ‎$a != $b ‎$a <> $b عدم مساواة TRUE إن لم يكن المتغير ‎$a مساويًا للمتغير ‎$b ‎$a !== $b عدم مطابقة TRUE إن لم يكن المتغير ‎$a مساويًا للمتغير ‎$b بالقيمة أو بالنوع ‎$a < $b أصغر من TRUE إن كان المتغير ‎$a أصغر تمامًا من المتغير ‎$b ‎$a > $b أكبر من TRUE إن كان المتغير ‎$a أكبر تمامًا من المتغير ‎$b ‎$a <= $b أصغر من أو يساوي TRUE إن كان المتغير ‎$a أصغر أو يساوي المتغير ‎$b ‎$a >= $b أكبر من أو يساوي TRUE إن كان المتغير ‎$a أكبر أو يساوي المتغير ‎$b تستعمل معاملات الزيادة أو الإنقاص لزيادة أو إنقاص قيمة المتغير بقيمة 1. المثال شرحه ‎++$x;‎ إضافة القيمة 1 إلى المتغير ‎$x ثم إعادة القيمة النهائية ‎$x++;‎ إعادة قيمة المتغير ‎$x ثم إضافة 1 ‎–-$x;‎ إنقاص القيمة 1 من المتغير ‎$x ثم إعادة القيمة النهائية ‎$x–-;‎ إعادة قيمة المتغير ‎$x ثم إنقاص 1 <?php echo "Postincrement"; $a = 5; echo "Should be 5: " . $a++; echo "Should be 6: " . $a; echo "Preincrement"; $a = 5; echo "Should be 6: " . ++$a; echo "Should be 6: " . $a; echo "Postdecrement"; $a = 5; echo "Should be 5: " . $a--; echo "Should be 4: " . $a; echo "Predecrement"; $a = 5; echo "Should be 4: " . --$a; echo "Should be 4: " . $a; ?> معامل السلاسل النصية (.) يستعمل لجمع سلسلتين نصيتين أو متغيرين مع بعضهما بعضًا؛ انظر إلى الشيفرة الآتي: <?php $a = 4; $q = 5; $c = $a.$q; // المتغيران $a و $b أصبحا مدمجين مع بعضهما echo $c; $n = 'myname'; echo "string ".$n.' $n inserted'; // دمج ثلاث سلاسل نصيّة ?> حاول أن تتدَّرب على تعريف وطباعة قيمة المتغيرات الخاصة بك، وأن تستعمل مختلف المعاملات السابقة عليها. المصادر مقال Introduction to PHP لصاحبه Harish Kumar. صفحة Operators من دليل PHP، وغيرها.
  14. php 101

    سنشرح في هذا الدرس كيف نوزِّع شيفرات على عدِّة ملفات وكيف نُضمِّن شيفرات من ملفات أخرى. توفِّر PHP أربع دوال لتضمين الشيفرات من الملفات الأخرى: include include_once require require_once الدالة include تُستعمَل include لتضمين الملفات الخارجية إلى الملف الحالي، حيث تنسخ النص من الملف الخارجي وتلصقه مكان وجودها، وإن حدثت أيّة أخطاء فستتجاوز هذه الدالة عملية تضمين الملف وسيُستكمَل التنفيذ مع إظهار تحذير (warning) دون إظهار خطأ (error). على سبيل المثال، لدي ملفان هما tutorials.php و tutorials2.php في نفس المجلد. الملف tutorials2.php: <?php /** * this is another class in file tutorial2.php */ class Bird { function __construct() { echo "class Bird included"; } } ?> الملف tutorials.php: <?php include 'tutorial2.php'; // كما يُمكن أن نكتبه على النّحو التّالي include('tutorial2.php'); $obj = new Bird(); ?> الناتج: class Bird included الدالة include_once هذه الدالة شبيهة بالدالة include لكن الاختلاف أنها تُضمِّن الملف مرةً واحدةً فقط؛ مثلًا، إن كان لديك ملفُ آخرٌ يُضمِّن كلا الملفين السابقين باستخدام include فسيُضمَّن الصنف Bird مرتين وسينتج عن ذلك خطأ لأنه لا يُسمَح بإعادة تعريف الصنف مرةً أخرى. وهذا الأمر يحدث كثيرًا في المشاريع أو التطبيقات الكبيرة، لذا يكون البديل هو استخدام include_once التي ستُضمِّن tutorial2.php مرةً واحدةً فقط. الدالة require تعمل require كعمل include إلا أنها تعطي خطأً (بدلًا من تحذير) عندما يحدث خطأ في تضمين الملف، ويتوقّف البرنامج عن التّنفيذ. الدالة require_once وهي تعمل أيضًا بشكلٍ شبيهٍ بالدالة include_once إلا أنها تعطي خطأً بدلًا من تحذير كما في require، ويتوقّف البرنامج أيضًا. مسار التضمين كان لدينا في المثال السابق كلا الملفين في نفس المجلد ثم ضمَّنا الملف tutorial2.php مباشرةً، وهذا ما يدعى "بالمسار النسبي"؛ لكن كيف يمكننا أن نضمِّن ملفًا من مجلدٍ آخر؟ يمكننا تمثيل المسار إلى الملف بطريقتين: المسارات النسبية المسارات المطلقة المسارات المطلقة وهي مسار الملف بدءًا من مجلد الجذر؛ الذي يكون في لينكس (وغيره من الأنظمة الشبيهة بِيونكس) كالآتي: include_once( '/var/www/html/findalltogether/tutorial2.php' ); أما في ويندوز، فسيبدأ المسار المطلق بحرف القرص (مثل C:\www\html\tutorial2.php)، لاحظ أنَّ الشرطة المائلة الخلفية (\) هي التي تستعمل في المسارات في ويندوز. المسارات النسبية وهي مسار الملف نسبةً إلى الملف الحالي (أي الملف الذي يجري عملية التضمين)؛ حيث يمكن أن يكون الملف في ثلاثة أماكن نسبية: أن يكون في نفس مجلد الملف الذي يجري عملية التضمين أن يكون ضمن مجلد في نفس مجلد الملف الذي يجري عملية التضمين أن يكون المجلد الأب (parent) أو في مجلدٍ موجودٍ في المجلد الأب لنتناول شرح كل حالةٍ على حدة: لقد استعملنا مسبقًا الحالة الأولى، ولقد وضعنا اسم الملف مباشرةً إن كان في نفس المجلد 2. أما في الحالة الثانية، فعلينا أن نضيف اسم المجلد؛ فمثلًا إن كان الملف موجودًا في مجلدٍ باسم folder فسيكون سطر التضمين هو: ‎include('folder/tutorial2.php');‎ أما لو كان هنالك أكثر من مجلد فرعي، فسنحتاج إلى كتابة أسمائها أيضًا: ‎include('first/second/third/tutorial2.php');‎ 3. في الحالة الأخيرة، سنستعمل "‎../‎" (نقطتين ثم خط مائل) كي ننتقل إلى المجلد السابق؛ وبفرض أنَّ الملف الحالي موجودٌ في ‎/var/www/html/tutorials/include/tutorials.php ونريد تضمين الملف ‎/var/www/html/another/tutorial2.php، فسنستعمل: ‎include('../../another/tutorial2.php');‎ لتضمينه، إذ أنَّ ‎../‎ تعني أننا ننتقل إلى الخلف مجلدًا واحدًا فقط. مجالات الأسماء في المشاريع الكبيرة، من الممكن (وهذا يحدث عادةً) أن يكون لدينا دالتان أو صنفان لهما نفس الاسم في مكتبتين أو ملفين مختلفين؛ ونحتاج أحيانًا أن نضمن كلا الملفين في نفس الملف، مما يؤدي إلى حدوث خطأ لأنه لا يجوز أن نعيد تعريف دالة أو صنف أكثر من مرة واحدة؛ لذا جاءت مجالات الأسماء (namespaces) للمساعدة في تجنب تلك التضاربات. مجالات الأسماء كالمجلدات، حيث لا نستطيع أن نضع ملفين بنفس الاسم في نفس المجلد، وبالمثل لا نستطيع تعريف دالتين أو صنفين في نفس مجال الأسماء، لكن نستطيع فعل ذلك في مجال أسماءٍ مختلف. لنفترض مثلًا أننا نبرمج نظامًا للتسوق، ولدينا دالتَا عرض مختلفتين، واحدة في ملف car.php كي تُظهِر عربة التسوق والأخرى في checkout.php لتظهر معلومات الدفع؛ ونريد تضمين هاتين الدالتين في ملفٍ سينفِّذ الدالة ‎display()‎ من ملف checkout.php إن ضغط المستخدم على زر "checkout"، وسيستدعي الدالة display()‎ من ملف cart.php فيما عدا ذلك. علينا هاهنا أن نستعمل مجالًا للأسماء، حيث سنُعرِّف كل دالة بمجال أسماءٍ مختلف كي لا تظهر أيّة أخطاء عند تضمين كلا الملفين سويةً. ملف checkout.php: <?php namespace Checkout; function display() { // code for display function echo "dispay in checkout"; } ?> ملف cart.php: <?php namespace Cart; function display() { //code of dispay function in cart echo "display in cart"; } ?> ملف tutorials.php: <?php // including files in different namespace require 'checkout.php'; require 'cart.php'; // checking condition if ( $action == "checkout" ) { // calling from checkout namespace Checkout\display(); } else { // calling from cart namespace Cart\display(); } ?> لاحظ ما يلي في الأمثلة السابقة: تُنشَأ مجالات الأسماء بكتابة namespace NamespaceName;‎ بعد وسم ‎<?php نستطيع استدعاء الدوال والأصناف من مجالات أسماء معيّنة بكتابة NamespaceName\functionName()‎ و NamespaceName\classname‎ على التوالي وبالترتيب مجالات الأسماء الفرعية والكلمة المفتاحية use يمكننا تعريف مجال فرعي كما لو كنا ننشِئ مجلدًا فرعيًا، الشكل العام لتعريفه هو ‎namespace NamespaceName/subNamespaceName/anotherSubNamespace;‎ وطريقة استعمال مجالات الأسماء الفرعية مماثلة تمامًا لاستعمال مجالات الأسماء العادية؛ وعندما يكون المشروع كبيرًا ويحتوي الكثير من مجالات الأسماء الفرعية، فسيصبح من المزعج أن نكتب نفس الاسم مرارًا وتكرارًا، لذا توفِّر لغة PHP الكلمة المحجوزة «use» لهذا الغرض، إذ تُسنِد use اسم مجال الأسماء الفرعي بأكمله إلى اسمٍ ذي كلمةٍ وحيدة. use longNamespaceName as shortName; يمكنك بعد ذلك أن تستعمل الاسم القصير لمجال الأسماء بدلًا من كتابة كل الاسم، يدعى الاسم القصير بالاسم البديل (alias). <?php require "checkout.php"; // نعرف اسمًا أقصر للاسم الأطول use Namespace\SubNamespace\FrontEnd\Checkout as NewCheckout; NewCheckout\display(); ? > التحميل التلقائي للأصناف العديد من المبرمجين الذين يكتبون برامج كائنية التوجه يُنشئون ملفًا لكل صنف، ومن أكثر الأشياء التي تزعجهم هي كتابة قائمة طويلة من الملفات التي يجب تضمينها في بداية كل ملف. لم يعد ذلك ضروريًا في PHP 5، فأصبحت هنالك طريقة لتضيمن الأصناف تلقائيًا عند الحاجة إليها. يمكننا استعمال التحميل التلقائي للأصناف عبر الدالةspl_autoload_register()‎، وهذه الدالة مرنة جدًا، وتسمح باستخدام أكثر من محمل تلقائي (autoloader)، هذا مثالٌ عن استخدامها: <?php spl_autoload_register(function ($class_name) { include $class_name.'.php'; }); $obj = new MyClass1(); $obj2 = new MyClass2(); ?> تقبل دالة spl_autoload_register وسيطًا هو الدالة التي ستضمن ملفات الأصناف، فإما أن تُعرِّف الدالة ثم تمرر اسمها إلى دالة spl_autoload_register، أو أن تعرف دالة مجهولة مباشرةً داخل الدالة spl_autoload_register كما في المثال السابق. مثالٌ عن الحالة الأولى: <?php function my_autoloader($class_name) { include $class_name.'.php'; } spl_autoload_register('my_autoloader'); ?> في هذه الحالة ولدى محاولة استخدام صنف غير مُعرّف في نفس الملف مثل: $car = new Car; سيقوم PHP بمحاولة تحميل الملف Car.php (يبحث في المُجلّد الحالي) وإن وجده يقوم بإنشاء مُتغير جديد من صنف Car. التحميل التلقائي في Composer شاع استعمل Composer لإدارة حزم المكتبات البرمجية في PHP، إن أردت الاطلاع على المزيد من المعلومات حوله، فانظر إلى مقالة ما هو Composer ولماذا يجب على كل مطور PHP استخدامه. يُنشِئ Composer الملف vendors/autoloader.php الذي يتيح تضمين المكتبات الضرورية لعمل مشروعك تلقائيًا دون الحاجة إلى فعل ذلك يدويًا، وذلك عبر تضمين ذاك الملف في شيفرات PHP: <?php require_once "vendors/autoloader.php"; أسهل طريقة هي تحديد كل صنف على حدة، وسنُعرِّف لهذا الغرض مصفوفةً تحتوي على مسارات الملفات التي نريد تحميلها تلقائيًا في ملف composer.json، ربما تستفيد من هذه الطريقة في تضمين الملفات التي تحوي دوال PHP التي لا يمكن تحميلها تلقائيًا: { "autoload": { "files": ["src/MyLibrary/functions.php"] } } أو عبر PSR-4، التي تسمح لك بربط مجالات الأسماء إلى مسارات نسبية (relative paths) لجذر الحزمة، فعند التحميل التلقائي لصنف مثل Foo\\Bar\\Abz، فإن سابقة (prefix) مجال الأسماء Foo\\‎ التي تشير إلى المجلد src/‎ تعني أن آلية التحميل التلقائي ستبحث عن ملف باسم src/Bar/Baz.php وتضمِّنه إن كان موجودًا: { "autoload": { "psr-4": { "Monolog\\": "src/", "Vendor\\Namespace\\": "" } } } ولو أردت أن تبحث عن نفس السابقة في أكثر من مجلد، فعليك تحديد تلك المجلدات في مصفوفة كالآتي: { "autoload": { "psr-4": { "Monolog\\": ["src/", "lib/"] } } } وتستطيع توفير مجلد افتراضي إن لم يُعرَّف مجال الأسماء للصنف الذي يراد تحميله تلقائيًا، وذلك بترك مكان السابقة فارغًا: { "autoload": { "psr-4": { "": "src/" } } } المصادر مقال Distribute code in files in PHP لصاحبه Harish Kumar توثيق Composer صفحات include و require و Autoloading Classes و spl_autoload_register و ‎‎__autoload
  15. هل أنت مهتم بتعلم PHP وبناء قوالب وملحقات خاصة بك على ووردبريس؟ أو ربما أنت مُهتمّ بتعلّم القليل الذي يُمكنك من إدخال التّعديلات التي تحتاجها على مواقعك ومدوّناتك التي تعتمد على ووردبريس. أيّا كان وضعك، هناك أمور يجب عليك أن تعرفها قبل أن تغوص في مجال تطوير ووردبريس. سنحاول في هذا المقال إعطاءك فكرة واضحة عليها. كيف يعمل ووردبريس؟ لنفهم ماذا وكيف يمكننا التطوير في ووردبريس، سنلقي أولا نظرة سريعة على آلية عمل ووردبريس. يتكون ووردبريس من ثلاثة عناصر رئيسية: النواة الأساسية والقوالب والمُلحقات. تحتوي النواة على جميع الوظائف الأساسية التي تشكل نظام إدارة المحتوى لووردبريس، وهذه الشيفرات البرمجية تتضمن كل شيء من البنية التحتية (backend) للإدارة إلى دوال جدولة المشاركات والتأكد من قوة كلمة المرور والسماح بإنشاء مستخدمين وغيرها. في حين أن النواة الأساسية (core) مسؤولة عن البنية التحتية للموقع وكيفية التعامل معها، فإن القوالب مسؤولة عن الواجهة الأمامية للموقع وكيفية ظهوره. نستخدم إدارة ووردبريس (WordPress admin) لإنشاء المشاركات والصفحات وبقية محتوى الموقع، وأما بالنسبة لكيفية ظهور هذه الأشياء للزائر فهو أمر متروك للقالب theme، لذلك فإن هذا سيعطيك قوة كبيرة للتحكم في موقعك، فقد ترغب بتثبيت وتفعيل القوالب الموجودة أو حتى تطوير قوالبك المخصصة. أبسط طريقة لوصف المُلحقات plugins هي أنها توفر وظائف إضافية للووردبريس، ولفعل ذلك، قد تعدّل المُلحق الشيفرة البرمجية للواجهة الأمامية أو البنية التحتية للموقع، وأبسط مثال لذلك هي المُلحق الذي يضيف زر لتغريدة تويتر، وقد تُنشئ أيضا صفحة إعدادات جديدة في البنية التحتية لقائمة الإدارة والتي ستمكنك من إعداد بعض الخيارات الافتراضية لتغريدة المستخدم ويمكنها إضافة نفسها إلى الواجهة الأمامية للموقع، والتي سيكون موقعها في الغالب تحت التدوينة (post). مجالات التطوير بقدر تقدمك في تطوير ووردبريس، ستتمكن من تطوير أي واحدة من المكونات الرئيسية المذكورة أعلاه بالإضافة إلى تطبيقات مستقلة بمساعدة REST API الجديدة وسنذكر المزيد عن هذا الموضوع بعد قليل. مهما كان ما تريد فعله مع ووردبريس، أنصحك باتباع منهج في دراستك، هذه القائمة ستساعدك على التعرف على الأنظمة التي تحتاج إلى معرفتها قبل بدء تعلمك المزيد حول المجال الذي اخترته: القوالب المُلحقات REST API النواة القوالب إن تعلم كيفية عمل القوالب وتطويرها سيسمح لك باحتراف إنشاء المواقع بدءا من المواقع الصفحة الواحدة إلى مواقع المحتوي الحيوي الثقيل، وستسمح لك أيضا بالحصول على المزيد من العملاء (إذا كان هذا ما يهمك) أو حتى بيع القوالب تجاريا. يوجد العديد من مطوري القوالب الناجحين في أسواق مثل Themeforest و Mojo Marketplace وغيرها. ففي وقت كتابة هذا المقال، أشهر قالب على موقع Themeforest تم بيع 1377 نسخة منه في أسبوع أي أكثر من $81,000 في أسبوع واحد فقط! يمكنك الحصول على الكثير من الأموال إذا كنت تستطيع تطوير قالب مميزة. على الرغم من أن هذا المبلغ لا يحققه جميع مطوري القوالب، وربما لن تصبح مليونيرًا بين عشيّة وضحاها من إنشاء القوالب، لكن يمكنك الحصول على مبلغ مالي جيد من القوالب إذا كنت تقوم بالأمر بالشكل الصحيح. إذا أردت رؤية بعض الأمثلة عن القوالب الشهيرة، فألق نظرة على الأسواق التي ذكرناها أعلاه، أو على قسم قوالب ووردبربس حيث جميع القوالب مجانية، فالكثير من مطوري القوالب يصدرون أعمالهم الأولى في هذا القسم. يمكنك تعلم كيفية إنشاء قوالب ووردبريس في أكاديمية حسوب من خلال سلسلة الدروس مدخل إلى تطوير قوالب ووردبريس. الملحقات plugins بطريقة ما، تعتبر المُلحقات شريان حياة ووردبريس، فهي تحوله إلى كل شيء من منتدى إلى شبكة اجتماعية أو منصة للتجارة الإلكترونية وغيرها باستخدام ضغطة زر واحدة، فالمُلحقات تعطيك تحكمًا كاملًا بجميع جوانب نظام ووردبريس، وتسمح لك بتعديل ما تشاء، وسيساعدك هذا كثيرا عند إنشاء مواقع ووردبريس للعملاء. كما هي الحال مع القوالب، فالمُلحقات تملك أيضا أسواقا وفي العادة يتم إدارتها من نفس الشركات التي تدير أسواق القوالب. يعتبر سوق CodeCanyon على سبيل المثال أكبر سوق للملحقات حيث يملك أكثر من 4000 ملحق متاحة للشراء. على الرغم من أن المبيعات ستكون أقل من القوالب إلا أنه يمكنك ربح الكثير إذا أنشأت ملحقًا جيدًا. يملك موقع ووردبريس قسمًا للملحقات المجانية ويحتوي على أكثر من 40000 ملحق، وهو بذلك مصدر كبير للأدوات والإلهام والأمثلة على الشيفرات البرمجية المميزة (والشيفرات البرمجية السيئة للأسف). يمكنك تعلم كيفية إنشاء ملحقات وإضافات ووردبريس في أكاديمية حسوب من خلال سلسلة الدروس مدخل إلى برمجة إضافات ووردبريس. REST API ستستخدم REST API لاحقا عندما تحترف تطوير القوالب والمُلحقات، ونظريا ستكون قادرا على استخدامها إذا كانت لديك خبرة في البرمجة بلغة أخرى مثل جافا أو روبي. تعتبر REST API جديدة نسبيا وتسمح لك بإنشاء تطبيقات حقيقية بالاعتماد على ووردبريس، وهذا يتضمن تطبيقات أندرويد وأيفون وغيرها. أفضل طريقة لشرح هذه الميزة هي عن طريق مقارنتها بمواقع مثل تويتر أو انستغرام، لا شك أنك قد رأيت تغذية تويتر معروضة على موقع أحدهم، ولإضافة هذه الميزة إلى موقعك لن تحتاج إلى معرفة كيفية عمل نواة شيفرة البرمجية الخاصة بتويتر، كل ما تحتاجه هو القليل من الشيفرات البرمجية التي تقول: "من فضلك استرجع آخر خمسة من تغريداتي." وسيتعامل تويتر مع الباقي وسيرجع لك بيانات آخر خمسة تغريدات التي طلبتها، وبعد ذلك يمكنك استخدام HTML و CSS لعرضها. وهذا بالضبط ما يفعله REST API لووردبريس، يمكنك الاتصال بأي موقع وطلب منه آخر خمسة مشاركات فيها، ويمكنك أيضا القيام بأكثر من ذلك: يمكنك إنشاء/حذف المستخدمين وتعديل الفئات وغيرها (بالطبع، تحتاج إلى الاستيثاق قبل استخدامها)، هذا يعني أنه يمكنك استخدام ووردبريس كمستودع للمعلومات وبناء واجهة أمامية وبنية خلفية باستخدام نظام مختلف تماما. النواة ساهم في تطوير ووردبريس مجتمع من الآلاف المتطوعين حول العالم، حيث أنه يعمل 471 شخص على الإصدار 4.4 من ووردبريس، والعديد من الأشخاص الآخرين يعملون على جوانب مختلفة من ووردبريس، من الترجمة وتطبيقات الويب إلى الإتاحة (accessibility) والدعم. في الحقيقة، يمكنك الاشتراك معهم الآن، فبينما تحتاج إلى بعض الخبرة للمشاركة في برمجة نواة ووردبريس إلا أنه يمكنك المساهمة في تحديد المشاكل والأخطاء والتأكد منها وتقديم الأفكار في أي وقت باستخدام WordPress Trac، وهو المكان الذي يمكنك من متابعة تطوير شيفرة نواة ووردبريس. إذا وجدت علة (خطأ - bug) يمكنك إرفاقها بالشيفرة المناسبة للتخلص منها، وبعد عدة مراجعات وتدقيقات سيتم استخدام شيفرتك البرمجية إذا كانت مناسبة، وهذه هي أفضل طريقة للمشاركة في تطوير النواة. تطوير ووردبريس: ماذا تحتاج أن تتعلمه يجب أن تعتاد على العمل على مجموعة محددة من الأدوات حتى تتمكن من تطوير ووردبريس. إن عملية التعلم لا تنتهي بالنسبة إلى أي مطور جيد، سوف أعرض عليك هنا حزمة للبداية كما سأريك بعض الأدوات المتقدمة التي قد تحتاج إليها لاحقا عندما تريد أن تتعلم المزيد. الحد الأدنى من المتطلبات لتطوير الووردبريس هي HTML و CSS و PHP، بالإضافة إلى هذه اللغات ستحتاج إلى جافا سكربت و MySQL في مرحلة ما، عندما تتقن هذه اللغات يمكنك الانتقال إلى أشياء أخرى مثل LESS/SASS و Coffeescript و XML و JSON وغيرها، لكن هذه الأشياء لا تعتبر ضرورية لتطوير ووردبريس، لكن إذا عرفتها سيجعل حياتك أسهل كمطور وستوسع آفاقك. HTML و CSS أول لغتين يجب عليك تعلمهما هما HTML و CSS، مهما كانت الشيفرة البرمجية التي تكتبها ومهما كانت اللغة التي تستخدمها فستحتاج حتما إلى HTML عند إرسال صفحات الويب إلى المستخدم وإلى بعض CSS لتصميم وتزيين الصفحة. إن HTML مسؤولة عن إعطاء هيكل المواقع. على المستوى الأساسي، هذا يعني أنك ستقرر ما النص الذي يجب أن يكون عنوانًا وما يجب أن يكون قائمة وما الذي يجب أن يكون في رأس أو أسفل الصفحة. أما في المستوى الأعمق، ستقرر قرارات مهمة حول SEO والتحسين (optimization). يُستخدم CSS لتطبيق أنماط لهيكل HTML، أي أنك ستُعرّف لون النص والروابط والمسافة بين الفقرات ومحاذاة الصورة وألوان الحدود وسمكها وغيرها من العناصر عن طريق استخدام شيفرة CSS. إن CSS تتميز بسهولة تعلمها وبصعوبة إتقانها. PHP تحظى PHP بشعبية كبيرة كأشهر لغة سكربتات من جانب الخادوم server-side-، ووفقا للاستطلاع الذي قام به W3Techs، تستخدم PHP في 81.6% من المواقع وهي اللغة التي كُتب بها ووردبريس (وتقريبا أغلب أنظمة إدارة المحتوى الأخرى أيضا) ولذلك فإن معرفة PHP هو أمر ضروري لتطوير ووردبريس. إن معرفتك بـ PHP وحدها، سيجعلك تحصل على أكثر من معرفة بتطوير ووردبريس فقط. إن أهم فرق بين لغات جانب الخادوم عن لغات جانب العميل - مثل HTML - هو أنه يتم معالجتها في الخادوم أولا، ففي HTML، يمكنك كتابة شيفرة برمجية لـ Good Morning وسيرسلها HTML كما هي وسيعرضها على الزوار. أما في لغات جانب الخادوم، فستكتب شيء مشابه لهذا [good [time_of_day، وقبل أن يتم إرسال ذلك الأمر إلى المستخدم، سيعالج الخادوم هذه الأمر حتى يعرف ما يضعه في مكان [time_of_day] حسب الوقت الذي دخلت فيه إلى الموقع، فيمكنك أن ترى "Good day" أو "Good evening". لاحظ أن البيانات التي يستقبلها متصفحك تبقى HTML لكن تمت معالجتها في الخادوم مسبقا، ولاحظ أيضا أن الشيفرة السابقة لم تكن شيفرة PHP بل هي مثال فقط لأعطيك فكرة عن آلية عمل هذه اللغة. كما هو الحال مع جميع لغات البرمجة، فالممارسة والتمرين هي التي تجعلك تبرمج بشكل أفضل، فيمكنك تعلم PHP في غضون بضعة أيام لكنك ستجد نفسك أنك لا تملك أية فكرة عن ما الذي تقوم به، لذلك تحتاج إلى تجربة الأشياء وتخريبها وليس الوقوف دون معرفة ما يجري، وكما يقولون الممارسة تولد الإتقان. جافا سكربت ازداد دور جافا سكربت أهمية على الإنترنت، خاصة مع ظهور أدوات مبنية على جافا سكربت مثل Node و Angular. جافاسكربت تستخدم عادة لإضافة وظائف حيوية للمواقع وللتحميل غير المتزامن. سأعطيك مثال على كل واحد منها. فمثلا لو أردت أن يتم إخفاء نموذج بشكل كامل وأن يظهر ببطء داخل lightbox عندما يضغط المستخدم على زر معين، فيمكنك فعل ذلك باستخدام جافا سكربت بما أنه يمكنه التعامل مع تحريك الرسوم (animation) وربما الوظائف الأخرى، مثل التأكد من أنه تم ملئ النموذج بشكل صحيح قبل إرساله. أما التحميل غير المتزامن فيتم عمله عبر آلية تسمى بـ AJAX، فيمكنك استخدام AJAX للحصول على معلومات من الخادوم وعرضها دون إعادة تحميل الصفحة، وأبسط مثال لذلك هو التمرير اللانهائي (endless scrolling) فعندما يتم تحميل 10 مشاركات وتصل إلى نهاية الصفحة فسيتم عرض 10 مشاركات أخرى وتستمر هكذا. الكثير من المطورين تعلموا جافا سكربت من خلال إطار jQuery، فهو يُستخدم على نطاق واسع في ووردبريس وفي ملايين المشاريع على الإنترنت، وعلى الرغم من أن هذا الأمر جيد لكن ضع في اعتبارك أن جافا سكربت هو أكثر من مجرد jQuery وإن تعلم جافا سكربت كما هو هي فكرة جيدة. MySQL إن Mysql هي لغة تُستخدم للوصول والعمل مع البيانات المخزنة في قاعدة البيانات، يستخدم ووردبريس هذه اللغة كثيرا للتعامل مع البيانات، لكن كمطور، لا تحتاج إلى معرفة الكثير لأن ووردبريس يملك مجموعة من الدوال المساعدة. لكن في بعض الحالات الخاصة، قد تحتاج إلى كتابة استعلام قاعدة البيانات بنفسك أو ربما قد ترغب بتحسين شيء في موقعك، لذلك سيفيدك تعلم أساسيات MySQL. إن العمل مع قواعد البيانات واضح للغاية، فالجدول في قاعدة البيانات يشبه كثيرا جداول بيانات Microsoft Excel، فكل عمود يملك عنوانًا وبيانات مخزنة في الأسطر، ونستخدم MySQL لإضافة وحذف وتعديل واسترجاع البيانات، ربما ترغب بكتابة استعلام MySQL يرجع لك جميع المشاركات التي تحتوي على كلمة "awesome" ولديها أكثر من 8 تعليقات، أو قد ترغب أيضا بإيجاد جميع المستخدمين الذين يملكون اسم "Daniel". مرة أخرى، إن كتابة شيفرة MySQL خام في ووردبريس هو أمر نادر، لكنه يحدث في بعض الأحيان، لذلك فإن فهم كيفية عمل اللغة سيساعدك على كتابة شيفرات أفضل بشكل عام أدوات متقدمة بمجرد أن تتعود على الأقل على استخدام ثلاثة اللغات الأساسية - HTML و CSS و PHP - يمكنك البدء باكتشاف العديد من الأدوات المساعدة، واحدة من الأشياء الأولى التي يميل الناس إلى تعلمها هي LESS و/أو SASS، كلاهما "مجموعات موسّعة" (Superset) لـ CSS، أي أن أي شيفرة CSS صحيح تعتبر صحيحة في شيفرة LESS و SASS، وتكمن أهمية إضافة هاتين اللغتين هو إمكانية استخدام متغيرات ودوال و غيرها في CSS، والذي هو غير ممكن بشكل افتراضي. إن أدوات البناء (Build tools) هو شيء سترغب في اكتشافه عند مرحلة معينة، أفضلها Gulp و Grunt فهذان يمكنهما مراقبة تعديلات الملفات وتنفيذ مختلف المهام عند استيفاء المتطلبات، فعلى سبيل المثال، في أي وقت تعدل فيه ملف SASS يمكنك ترجمته تلقائيا إلى CSS وحفظه إلى ملف معين، أو يمكنك تحسين الصور أو دمج الملفات أو تحميل الحزم الخارجية فجميع المهام الأخرى يمكنك أن تفعلها باستخدام هذه الأدوات. سطر الأوامر أو الطرفية (terminal) هو شيء يجب أن تلقي نظرة عليه. نعم إن استخدام سطر الأوامر قد يبدو مخيفا لكنه ليس كذلك، فبمجرد كتابة بضعة أوامر يمكنك حفظ الكثير من الوقت، فسكربت/أداة مثل WP-CLI يمكنه تثبيت ووردبريس في بضعة ثواني، بما في ذلك تثبيت القوالب والمُلحقات والمحتويات للتجربة والتي لو قمت بها بشكل يدوي ستتطلب الكثير من الوقت والجهد. إن أنظمة االتّحكّم في الإصدارات (Version control) هي من الأدوات المفيدة للغاية فلن تعرف حاجتك إليها إلا لو استخدمتها، فعلى الرغم من أنها وُضعت أصلا للعمل على نفس الشيفرة البرمجية في مجموعات إلا أنه يمكنك استخدامها كحل لإدارة المشاريع والمشاكل والنسخ الاحتياطي في نفس الوقت. ويعتبر كل من SVN و Git الأشهر على الإطلاق، لكن بالنسبة لي، أعتبر أن Git أفضل نظرا لأنه يعمل بشكل أفضل وبسبب Github الذي يوفر خدمة استضافة مستودعات Git على الإنترنت. ووردبريس: بوابتك إلى عالم البرمجة إن أفضل شيء بالنسبة إلى ووردبريس أنه يمكن أن يكون مدخلا لتعلم مهارات تطوير ويب ولغات أخرى. ولقد خضت هذه التجربة شخصيا، فلقد تعلمت أولا البرمجة الموجهة في PHP ثم تعلمت إطار عمل Laravel وأدوات البناء ثم LESS/SASS وأدوات سطر الأوامر وغيرها الكثير. ولقد خضت أيضا في غمار native app باستخدام #C وغيرها من اللغات. بمجرد معرفتك بكيفية عمل كل شيء، ستتعلم المزيد عند إنشاء مشاريع جديدة وكبيرة وكل شيء سيصبح أسهل، فبعد البرمجة كائنية التّوجّه في PHP لن تبذل الكثير من الجهد في تعلم #C لأن دماغك سيتعود على منطقه بطريقة مشابه لتعلم قيادة الشاحنات بعد تعلمك قيادة السيارات، فعلى الرغم من وجود الكثير من الاختلافات لكن بمجرد أن يكون لديك بعض الأساسيات سيسهل عليك التّحكمّ فيه. خاتمة ها قد عرفت الآن ما الذي تحتاجه للبدء في تطوير موقع ووردبريس، وقد تشعر بالإرباك، لكن لا تقلق، فالجميع سيشعر بذلك في هذه المرحلة. تذكّر أمرًا: من المهم أن لا تثبط عزيمتك، فجميع المبرمجين بدؤوا من مكان ما، فالكثير منهم كان سيئا للغاية عندما بدأ، يصارع لفهم المفاهيم الجديدة وشعر بالإحباط، لكنهم لم يستسلموا وكانوا دائما يدفعون أنفسهم للتّعلّم وهذا ما يُميّز المبرمج الجيد من السيئ. ترجمة -وبتصرف- للمقال: WordPress Development for Beginners: Getting Started لصاحبه Daniel Pataki. حقوق الصورة البارزة: Designed by Freepik.
  16. رغم قيامك بكل شيء بالطريقة الصحيحة، قد تواجهك أحيانا بعض رسائل الخطأ (errors) على ووردبريس. لا تقلق فإلى جانب أنك قد لا تكون السبب في ذلك بتاتا فقد تجد حلّا سهلًا وبسيطًا له. يتوفر ووردبريس افتراضيا على قيمة قصوى محدودة لرفع الصور، مقاطع الفيديو والملفات الأخرى، نفس الأمر بالنسبة لمحدودية ذاكرة PHP التي تساعدك على تشغيل الملحقات والسكربتات (scripts). قد يصبح هذا الأمر مشكلة حقيقية خصوصا إن كنت تملك موقعا ضخما غنيا بالمحتوى، عند وصولك إلى هذه القيم القصوى فإنك تواجه رسالة خطأ كالتالي: The uploaded file exceeds the upload_max_filesize directive in php.ini عند وصولك إلى القيمة القصوى للذاكرة من المحتمل أن تواجه رسالة مشابهة لما يلي: Fatal error: Allowed memory size of 12345678 bytes exhausted (tried to allocate 2345678 bytes) in /home/your-username/public_html/wp-includes/plugin.php on line 1000 قد يكون إصلاح هذا المشكل أمرا صعبا بعض الشيء بناء على إعدادات الخادوم (server)، لذ سنخصص هذا المقال لتوضيح كيفية زيادة قيمة الرفع القصوى وفي سعة الذاكرة على خادومك حتى تستأنف عملك كالمعتاد. تحديث ملف php.ini إن كنت تستخدم cPanel، اذهب إلى قسم الملفات Files واضغط على زر File Manager. تأكد التأشير على خانة Show Hidden Files ثم اضغط على Go. قم بتحديد مجلد wp-admin، ابحث عن أحد الملفين php.ini أو php5.ini، إن لم تجد أيا منهما، أنشئ واحدا جديدًا بالنّقر على زر New File في الزاوية أعلى اليسار، اختر اسم php.ini للملف ثم اضغط على Create File في الشاشة المنبثقة. يمكنك اختيار Document Root من أجل ولوج أسرع، ستذهب مباشرة إلى ملفات موقعك بعد اختيارها من القائمة المنسدلة. إذا اتبعت هذه الخطوات ولم ينجح الأمر، جرب تغيير اسم الملف إلى php5.ini، بمجرد فتح الملف أضف أو قم بتعديل الأسطر التالية، احفظ التغييرات ثم غلق الملف. upload_max_filesize = 1000M post_max_size = 2000M memory_limit = 3000M file_uploads = On max_execution_time = 180 يدل حرف M على ميغابايت، قم بتغيير القيم القصوى 1000M ،2000M و 3000M إلى قيم أخرى من اختيارك والتي تراها مناسبة لك. يؤدي تغيير قيمة max_execution_time إلى الحد من الوقت المستغرق في تحميل السكربت (مقدّرًا بالثّواني). في العديد من الحالات تتصاعد القيم التي تدخلها أثناء نزولك في القائمة من السطر الأول إلى الثالث، يجب على قيمة upload_max_filesize أن تكون هي الصغرى في حين تكون قيمة memory_limitshould هي الكبرى أما قيمة post_max_size فتمثل الوسط بينهما. قبل التأكد من ذهاب رسالة الخطأ، تأكد من حذف التخزين المؤقت للمتصفح (browser’s cache). تعديل ملف htaccess. إن لم يفِ التعديل السابق بالغرض، جرب التعديل على ملف htaccess.، أضف أو عدّل على الكود التالي في أسفل الصفحة: php_value upload_max_filesize 1000M php_value post_max_size 2000M php_value memory_limit 3000M php_value max_execution_time 180 php_value max_input_time 180 يتم تعديل هذا الكود بنفس طريقة التعديل على ملف php.ini، قم بتغيير القيم إلى ما يناسب احتياجاتك، لا تنس حفظ التعديلات وحذف التخزين المؤقت لمتصفحك. تحسين ملف wp-config.php إن لم تفلح أي الطريقتين السابقتين، جرب التعديل على ملف wp-config.php من خلال إضافة ما يلي إلى أسفل الصفحة مباشرة قبل سطر "happy blogging": define('WP_MEMORY_LIMIT', '3000M'); احفظ التعديلات واحذف التخزين المؤقت للمتصفح (browser’s cache). تغيير القيم القصوى في WHM إن كنت تستضيف موقعك على خادوم مخصص (dedicated server) أو من نوع VPS، يمكنك أن تجرب تغيير القيم القصوى للتحميل والذاكرة في WHM الخاص بك. بعد تسجيل الدخول، اذهب إلى: Server Configuration > Tweak Settings > PHP استخدم نفس القيم التي استخدمتها أعلاه وذلك من أجل نتائج أفضل. أدخل القيم المناسبة لك ثم اضغط على Save أسفل الصفحة. بعد ذلك، اذهب إلى: Service Configuration > PHP Configuration Editor تصفح الصفحة نزولا حتى تجد الأقسام الرئيسية memory_limit و upload_max_filesize. يجب على القيم التي تدخلها هنا أن تكون مطابقة لتلك التي حاولت إدخالها سابقا في ملفي: php.ini و htaccess.. أدخل القيم المناسبة لإعدادك. أخيرًا في قسم Options & Information حدد مكان max_execution_time وقم بتحديثه إلى نفس القيم التي أدخلتها في ملفي: php.ini و htaccess.. اضغط على Save أسفل الصفحة واحذف التخزين المؤقت للمتصفح. خلاصة أنت الآن على أتم استعداد لحل مشكل رسائل الخطأ، استمتع برفع ملفات أكبر حجما واستمر في استخدام الملحقات كما تشاء على موقع ووردبريس الخاص بك. لن تأخذ هذه التغييرات أكثر من بضع دقائق ليظهر تأثيرها لتتمكن من استئناف عملك بسرعة. إذا احتجت إلى رفع ملفات بحجم أكبر مرة واحدة فقط، يمكنك أن تقوم أيضا برفعها من خلال FTP لتجنب هذا العناء. في حين لا يتم عادة عرض الملفات المرفوعة على /wp-content/uploads/ directory باستخدام FTP في مكتبة الميديا، يمكن للملحق Media from FTP أن يسجلها في المكتبة ببضع نقرات. يتم تحديث هذا الملحق بشكل دوري. إن لم تعمل أي من الخيارات المقترحة، لم تتمكن من الولوج إلى الأماكن المذكورة أو واجهت بعض المشاكل أثناء القيام بهذه التغييرات عليك بالاتصال بمزود الاستضافة الخاصة بك الذي يمتلك صلاحية الولوج من أجل القيام بالتغييرات المطلوبة، فمزودك هو الأنسب لهذه المهمة. هل استطعت تغيير القيم القصوى للرفع وذاكرة PHP باستخدام هذه الطرق؟ هل واجهت أي مشاكل في القيام بذلك سابقا؟ تفضل بمشاركتنا تجربتك في التعليقات أسفله. ترجمة بتصرف للمقال: How to Increase the Maximum Upload and PHP Memory Limit in WordPress لصاحبته: JENNI MCKINNON.
  17. من المعروف أن حزمة LEMP (والتي هي اختصار لـ Linux, Nginx, MySQL, PHP) توفر سرعة وموثوقية عالية لتشغيل مواقع PHP، إلّا أنها تملك مزايا أخرى غير مشهورة كالأمن والعزل. في هذا المثال، سنعرض لك مزايا أمن وعزل المواقع على LEMP مع مستخدمين مُختلفين، وهذا عن طريق إنشاء أحواض pools خاصّة بـ php-fpm لكل جزء من خادوم nginx (سواء كان موقعًا أو مستضيفًا افتراضيًا virtual host). المتطلبات الأساسية تمت تجربة هذا الدرس على أوبنتو 14.04 وعلى الرغم من ذلك فإن طريقة التثبيت والإعداد ستكون مشابهة لها على بقية الأنظمة والإصدارات، لكن قد تختلف الأوامر وأماكن ملفات الإعداد بين الأنظمة. كما أننا نفترض أنك قد ثبتت nginx و php-fpm، وبخلاف ذلك أنصحك بإتباع الخطوة الأولى والثالثة من هذا المقال: كيف تثبت حزم MySQL ،nginx ،Linux :LEMP وPHP على أوبنتو 14.04. يجب تنفيذ جميع الأوامر في هذا الدرس التعليمي بمستخدم غير الجذر (non-root)، وإن إحتجنا لصلاحياته فسنستخدم sudo، وإذا لم تُعدّ بعد هذا المستخدم فأنصحك بإتباع هذا الدرس: الإعداد الابتدائي لخادوم أوبنتو 14.04. ستحتاج أيضا إلى اسم نطاق مؤهل بالكامل (fully qualified domain name (fqdn الذي يربط على خادوم أو خادوم للتجربة بالإضافة إلى localhost الافتراضي، وإذا لم يكن لديك واحد، يمكنك استخدام site1.example.org، وذلك عن طريق تعديل ملف etc/hosts/ باستخدام محررك المفضل كهذا sudo vim /etc/hosts وأضف هذا السطر (استبدل site1.example.org بـ fqdn الخاص بك إذا كنت تستخدمه): ... 127.0.0.1 site1.example.org ... أسباب لزيادة تأمين LEMP عند إعداد LEMP مشترك سيكون هنالك حوض pool php-fpm واحد فقط والذي سيشغل جميع سكربتات PHP لجميع المواقع باستخدام نفس المستخدم، وهذا يطرح مشكلتين كبيرتين: إذا تعرض تطبيق ويب على أحد أجزاء خادوم nginx -على سبيل المثال عنوان فرعي أو موقع ما- إلى خطر أو هجوم فستتعرض جميع مواقع الموجودة على هذا الخادوم أيضا، فالمهاجم سيتمكن من قراءة ملفات الإعداد (configuration files) بما في ذلك تفاصيل قواعد بيانات لمواقع أخرى أو حتى تغيير ملفاتها. إذا أردت إعطاء مستخدم صلاحيات للدخول إلى الخادوم الخاص بك، فسوف تعطيه صلاحيات الوصول إلى جميع المواقع، فعلى سبيل المثال، إذا كان مطورك يحتاج إلى العمل على بيئة الإدراج (staging environment)، فحتى مع صلاحيات صارمة جدا على الملفات، فستبقى له إمكانية وصوله إلى جميع المواقع بما في ذلك موقعك الرئيسي على نفس الخادوم. المشاكل أعلاه تم حلها في php-fpm بإنشاء أحواض مختلفة والتي تشتغل تحت مستخدم مختلف لكل موقع. الخطوة الأولى - إعداد php-fpm إذا غطيت المتطلبات الأساسية فسيكون لديك في الوقت الحالي موقع ويب يعمل على خادوم. سننشئ الآن موقعًا ثانيًا (site1.example.org) مع حوض php-fpm ومستخدم لينكس مخصصين له. لنبدأ بإنشاء المستخدم الضروري، ولأفضل عملية فصل يجب أن يحصل المستخدم الجديد على مجموعته الخاصة لذلك سننشئ أولا مجموعة المستخدم site1: sudo groupadd site1 وبعد ذلك سننشئ مستخدم site1 ينتمي إلى هذه المجموعة: sudo useradd -g site1 site1 حتى الآن لا يملك هذا المستخدم الجديد كلمة مرور ولا يمكنك تسجيل دخوله في خادوم، إذا أردت توفير صلاحيات وصول إلى هذه الملفات من الموقع لشخص معين، فيجب عليك في هذه الحالة إنشاء كلمة مرور لهذا المستخدم عن طريق الأمر: sudo passwd site1 ومع تركيبة اسم المستخدم/كلمة المرور سيتمكن المستخدم من تسجيل دخوله عن بعد باستخدام ssh أو sftp. بعد ذلك، أنشئ حوض php-fpm جديد لـ site1، فالحوض مهم للغاية وهو عبارة عن عملية (process) لينكس عادية والتي تعمل تحت مستخدم/مجموعة محددة وتستمع لـ Linux socket وقد تستمع أيضا لتركيبة IP:Port لكن سيتطلب هذا إلى المزيد من موارد الخادوم وهذه الطريقة ليست جيدة. بشكل افتراضي في نظام أبنتو 14.04، كل حوض php-fpm يجب أن يتم إعداده في ملف داخل مجلد etc/php5/fpm/pool.d/. كل ملف مع امتداد conf. في هذا المجلد سيتم تحميله تلقائيا في الإعداد العام لـ php-fpm. لذلك سننشئ ملف etc/php5/fpm/pool.d/site1.conf/ لموقعنا، يمكنك فعل ذلك مع محررك المفضل كالتالي: sudo vim /etc/php5/fpm/pool.d/site1.conf يجب أن يحتوي هذا الملف على: [site1] user = site1 group = site1 listen = /var/run/php5-fpm-site1.sock listen.owner = www-data listen.group = www-data php_admin_value[disable_functions] = exec,passthru,shell_exec,system php_admin_flag[allow_url_fopen] = off pm = dynamic pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 chdir = / في الإعدادات أعلاه، لاحظ هذه الخيارات: إن [site1] هو اسم الحوض، فلكل حوض اسم خاص به. يشير كل من user و group إلى المستخدم المجموعة التي سيعمل عليها الحوض الجديد. ستشير listen إلى مكان خاص لكل حوض. إن كل من listen.owner و listen.group يعرّفان ملكية المستمع (listener) -على سبيل المثال socket الخاصة بحوض php-fpm الجديد- ويجب على Nginx أن يكون قادرا على قراءة هذا socket، وهذا هو سبب أن socket يُنشأ مع اسم المستخدم والمجموعة تحت nginx الذي يشغل www-data. يسمح لك php_admin_value بوضع قيم إعداد php مخصصة والتي سنستخدمها لتعطيل دوال التي تُشغّل أوامر لينكس مثل exec, passthru, shell_exec, system. إن php_admin_flag مشابه لـ php_admin_value لكنه مجرد مبدل لقيم المنطقية مثل on و off. سنعطل دالة PHP التي تدعى allow_url_fopen والتي تسمح لسكربت PHP بفتح ملفات عن بعد والتي يمكن أن تُستخدم بواسطة المهاجم. ملاحظة: إن قيم php_admin_value و php_admin_flag يمكن تطبيقها بشكل عام، وعلى الرغم من ذلك قد يحتاجهما الموقع وهذا هو سبب عدم إعدادهما بشكل افتراضي. إن من مميزات أحواض php-fpm أنها تسمح لك بتخصيص إعدادات أمن لكل موقع، وعلاوة على ذلك، فيمكنك استخدام هذه الخيارات لأي إعدادات php أخرى، خارج المجال الأمني، لتخصيص بيئة الموقع. لن نتحدث في درسنا حول الأمن عن خيارات pm، لكن يجب أن تعرف أنها تسمح لك بإعداد أداء الحوض. وبالنسبة إلى خيار chdir فيجب أن يكون / والذي يعبر عن جذر نظام الملفات، وهذا السطر لا يجب تغييره ما لم تكن تستخدم chroot. لم يتم تضمين خيار chroot في الإعدادات أعلاه لأنه سيسمح لك بتشغيل الحوض في بيئة مسجونة، مثل قفل المجلد، وهذا الأمر سيكون رائعًا لأغراض أمنية لأنه ستتمكن من قفل الحوض دخل مجلد الجذر للموقع، ولكن على الرغم من ذلك فإن هذا الخيار الأمني قد يتسبب بالعديد من المشاكل لأي تطبيق PHP يعتمد على تطبيقات النظام (system binaries) وتطبيقات مثل Imagemagick والتي لن تكون متوفرة. بمجرد انتهائك من الإعدادات أعلاه أعد تشغيل php-fpm لتفعيل الخيارات الجديدة وذلك عن طريق الأمر: sudo service php5-fpm restart تأكد من أن الحوض يعمل بشكل صحيح وذلك بواسطة البحث عن عملياته كالتالي: ps aux |grep site1 إذا اتبعت التعليمات بدقة فستحصل على مخرجات مشابهة لهذه: site1 14042 0.0 0.8 133620 4208 ? S 14:45 0:00 php-fpm: pool site1 site1 14043 0.0 1.1 133760 5892 ? S 14:45 0:00 php-fpm: pool site1 بالإضافة إلى ذلك، سنعطل التخزين المؤقت الذي يوفره opcache، فهذا الأخير قد يُحسّن الأداء لكنه قد يتسبب في مشاكل أمنية. لتعطيله، عدل ملف etc/php5/fpm/conf.d/05-opcache.ini/ باستخدام صلاحيات أعلى (super user) وأضف السطر التالي: opcache.enable=0 بعد ذلك أعد تشغيل php-fpm حتى تعمل الخيارات الجديدة: sudo service php5-fpm restart الخطوة الثانية - إعداد nginx بعد أن انتهينا من إعداد حوض php-fpm لموقعنا، سنقوم الآن بإعداد جزء الخادوم في nginx. ولذلك أنشئ ملفًا جديدًا وذلك باستخدام محررك المفضل كالتالي: sudo vim /etc/nginx/sites-available/site1 يجب أن يحتوي هذا الملف على: server { listen 80; root /usr/share/nginx/sites/site1; index index.php index.html index.htm; server_name site1.example.org; location / { try_files $uri $uri/ =404; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm-site1.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } الشيفرة أعلاه تظهر إعدادات مشتركة لجزء الخادوم في nginx، لاحظ هذه الأجزاء: جذر الويب (Web root) هو usr/share/nginx/sites/site1/. اسم الخادوم يستخدم site1.example.org التي ذكرناها في جزء المتطلبات الأساسية من هذا الدرس. يحدد fastcgi_pass المتعامل (handler) لملفات php، يجب استخدام unix socket مختلفة لكل موقع مثل var/run/php5-fpm-site1.sock/. بعد ذلك أنشئ مجلد جذر الويب: sudo mkdir /usr/share/nginx/sites sudo mkdir /usr/share/nginx/sites/site1 لتفعيل الموقع أعلاه تحتاج إلى إنشاء رابط رمزي (symlink) له في مجلد /etc/nginx/sites-enabled/. يمكنك فعل ذلك باستعمال الأمر التالي: sudo ln -s /etc/nginx/sites-available/site1 /etc/nginx/sites-enabled/site1 في النهاية، أعد تشغيل nginx لتعمل التغييرات الجديدة كالتالي: sudo service nginx restart الخطوة الثالثة - التجارب للتجارب، سنستخدم دالة phpinfo والتي توفر لنا معلومات تفصيلية حول بيئة php. أنشئ ملفًا جديدًا باسم info.php والذي يحتوي على سطر واحد فقط: <?php phpinfo(); ?> ستحتاج هذا الملف في الموقع الافتراضي لـ nginx وفي جذر الويب /usr/share/nginx/html/، ولهذا الغرض يمكنك استخدام محرر النّصوص كالتالي: sudo vim /usr/share/nginx/html/info.php ثم انسخ الملف إلى جذر الويب للموقع الآخر (site1.example.org) كالتالي: sudo cp /usr/share/nginx/html/info.php /usr/share/nginx/sites/site1/ أنت الآن مستعد لتشغيل أبسط اختبار للتأكد من مستخدم الخادوم، يمكنك إجراء الاختبار عن طريق متصفح أو من خلال طرفية خادوم و lynx (متصفح يعمل عبر الطرفية)، وإذا لم تثبت lynx سابقا في خادوم فيمكنك تثبيته بكل سهولة عن طريق الأمر: sudo apt-get install lynx تأكد أولا من وجود ملف info.php في الموقع الافتراضي، ينبغي أن تتمكن من الوصول إليه عبر localhost كالتالي: lynx --dump http://localhost/info.php |grep 'SERVER\["USER"\]' في الأمر السابق نرشح المخرجات باستخدام grep لمتغير ["SERVER["USER فقط والذي يشير إلى مستخدم الخادوم، بالنسبة إلى الموقع الافتراضي يفترض أن تكون المخرجات تعرض مستخدم www-data الافتراضي كالتالي: _SERVER["USER"] www-data ونفس الشيء سنفعله للتأكد من مستخدم خادوم site1.example.org: lynx --dump http://site1.example.org/info.php |grep 'SERVER\["USER"\]' يجب أن ترى هذه المرة site1 في المخرجات: _SERVER["USER"] site1 إذا قمت بعمل أية تخصيصات في إعدادات php في أحواض php-fpm الأساسية، فيمكنك أيضا التأكد من قيمهما بنفس الطريقة السابقة وذلك عن طريق ترشيح المخرجات التي تهمك. حتى الآن، عرفنا أن موقعينا يعملان تحت مستخدمين مختلفين، لكن لنرى الآن كيف يمكننا تأمين الاتصال، لتفسير المشكلة الأمنية التي نريد حلها في هذا المقال، سننشئ ملفًا يحتوي على معلومات حساسة، في العادة يحتوي هذا الملف معلومات الاتصال بقاعدة البيانات ويحتوي على تفاصيل اسم المستخدم وكلمة المرور لقاعدة بيانات المستخدم، فإذا وُجد أن أحدهم يستطيع الوصول إلى هذه المعلومات فسيتمكن من فعل أي شيء لموقعنا. أنشئ باستخدام محررك المفضل ملفًا جديدًا في موقعك الرئيسي يدعىusr/share/nginx/html/config.php/ ويحتوي على التالي: <?php $pass = 'secret'; ?> في الملف أعلاه عرّفنا متغيرًا يدعى pass والذي يحتوي على قيمة secret، وطبعا نريد تقييد الوصول إلى هذا الملف لذلك سنغير الصلاحيات إلى 400، والتي تعطي صلاحيات القراءة فقط لمالك الملف. لتغيير الصلاحيات إلى 400 نفذ الأمر التالي: sudo chmod 400 /usr/share/nginx/html/config.php بالإضافة إلى ذلك موقعنا الرئيسي يعمل تحت مستخدم www-data والذي يجب أن يكون قادرًا على قراءة هذا الملف، وبالتالي، غيّر ملكية الملف إلى ذاك المستخدم كالتالي: sudo chown www-data:www-data /usr/share/nginx/html/config.php في مثالنا سنستخدم ملفًا آخر يدعى usr/share/nginx/html/readfile.php/ لقراءة المعلومات السرية ومن ثم طباعتها، ويجب أن يحتوي هذا الملف على الشيفرة البرمجية التالية: <?php include('/usr/share/nginx/html/config.php'); print($pass); ?> بعد ذلك غيّر ملكية هذا الملف لمستخدم www-data كالتالي: sudo chown www-data:www-data /usr/share/nginx/html/readfile.php للتأكد من جميع الصلاحيات والملكيات في جذر ويب، نفّذ الأمر التالي: ls -l /usr/share/nginx/html/ يجب أن تكون المخرجات شبيهة بهذه: -r-------- 1 www-data www-data 27 Jun 19 05:35 config.php -rw-r--r-- 1 www-data www-data 68 Jun 21 16:31 readfile.php الآن جرب الوصول إلى الملف السّابق على موقعك الافتراضي باستخدام الأمر: lynx --dump http://localhost/readfile.php ستلاحظ أن secret مطبوعة على الشاشة والتي تعني أن الملف مع المعلومات الحساسة يمكن الوصول إليه من داخل نفس الموقع، وهذا السلوك متوقع. الآن جرب نسخ ملف usr/share/nginx/html/readfile.php/ إلى موقعك الثاني site1.example.org كالتالي: sudo cp /usr/share/nginx/html/readfile.php /usr/share/nginx/sites/site1/ للحفاظ على علاقات الموقع/المستخدم، تأكد من أن الملفات داخل كل موقع مملوكة من طرف المستخدم المعني وذلك عن طريق تغيير ملكية الملف المنسوخ إلى site1 باستخدام الأمر التالي: sudo chown site1:site1 /usr/share/nginx/sites/site1/readfile.php للتحقق من وضعك الصلاحيات والملكيات الصحيحة للملفات، اعرض قائمة محتويات جذر ويب site1 باستخدام الأمر: ls -l /usr/share/nginx/sites/site1/ يجب أن ترى كالتالي: -rw-r--r-- 1 site1 site1 80 Jun 21 16:44 readfile.php بعد ذلك حاول الوصول إلى نفس الملف من site1.example.com باستخدام الأمر: lynx --dump http://site1.example.org/readfile.php سترى أنه تم إرجاع مساحة فارغة، وبالإضافة إلى ذلك، إذا بحثت عن الأخطاء في سجل الأخطاء لـ nginx باستخدام الأمر grep التالي: sudo grep error /var/log/nginx/error.log فسترى شيئا مشابها لهذا: 2015/06/30 15:15:13 [error] 894#0: *242 FastCGI sent in stderr: "PHP message: PHP Warning: include(/usr/share/nginx/html/config.php): failed to open stream: Permission denied in /usr/share/nginx/sites/site1/readfile.php on line 2 ملاحظة: سترى أيضا خطأ مشابهًا في مخرجات lynx إذا فعّلت خيار display_errors في إعدادات php-fpm في ملف etc/php5/fpm/php.ini/ (بوضع On في ذلك الخيار). يظهر التحذير أن السكربت من موقع site1.example.org لا يمكنه قراءة الملف الحساس (config.php) من الموقع الرئيسي وبالتالي، المواقع التي تعمل تحت عدة مستخدمين لا يمكنها تعريض أمن بقية المواقع. إذا ذهبت إلى نهاية جزء الإعدادات من هذا المقال، سترى أننا عطلنا التخزين المؤقت التي يوفرها opcache بشكل افتراضي، وإذا رغبت بمعرفة السبب حاول تفعيله مجددا وذلك عن طريق وضع opcache.enable=1 في ملفetc/php5/fpm/conf.d/05-opcache.ini/ عن طريق مستخدم sudo ومن ثم إعادة تشغيل php5-fpm باستخدام الأمر sudo service php5-fpm restart. ستجد أنه إذا قمت بإعادة خطوات الاختبار بنفس الترتيب فإنك ستتمكن من قراءة الملف الحساس على الرغم من صلاحياته وملكياته، وهذه المشكلة في opcache قد تم الإبلاغ عنها منذ فترة طويلة لكن لم يتم إصلاحها حتى وقت كتابة هذا المقال. الخاتمة من الناحية الأمنية، يجب استخدام أحواض php-fpm مع مستخدم مختلف لكل موقع على نفس خادوم ويب nginx، فهذا الأمر حتى لو كان يضْعف الأداء قليلا، فإن ميزة عملية الفصل يمكنها منع خروق أمنية خطيرة. الفكرة التي شرحناها في هذا المقال ليست فريدة، وهي موجودة في تقنيات فصل PHP أخرى مثل SuPHP. وعلى الرغم من ذلك، أداء بقية البدائل أسوء من php-fpm. ترجمة -وبتصرف- للمقال: How To Host Multiple Websites Securely With Nginx And Php-fpm On Ubuntu 14.04 لصاحبه Anatoliy Dimitrov.
  18. التجريد – Abstraction نعلم أنَّ الصنف المُشتَق يأخذ خاصياته من الصنف الأب لكن الصنف المُشتَق مستقل تمامًا عن الصنف الأب؛ وقد يكون في بعض الأحيان من الجيد أن نرسم خطوطًا عريضة لآلية سلوك الصنف الابن، وهذه هي مهمة الأصناف والدوال المجردة. إذ أنَّ الصنف المجرد يحتوي على دوال غير مكتملة (أي مجردة) التي يجب أن يملأها الابن لكي يكون صنفًا وعدا ذلك سيكون صنفًا مجردًا أيضًا. بكلامٍ آخر، الصنف المُجرَّد (Abstract Class) هو صنف يحتوي على أسماء دوال دون كتابة الشيفرات المسؤولة عن عملها وتسمى تلك الدوال بالدوال المجردة، وقد يحتوي أيضًا على دوال كاملة اعتيادية تؤدي وظيفتها تمامًا. انظر إلى المثال الآتي لمزيدٍ من الإيضاح: <?php // تعريف صنف مجرد abstract class AbsClass { function __construct() { echo "this is an abstract class <br>"; } // دالة مجردة abstract public function abs_function(); function full_function() { echo "this is not an abstract function <br>"; } } class SubClass extends AbsClass { function __construct() { echo "this is child class <br>"; parent::full_function(); } // تعريف الدالة المجردة public function abs_function() { echo "this is completed abstract function <br>"; } } $obj = new SubClass(); $obj->abs_function(); ?> نستعمل الأصناف المجردة عندما يلزمنا إنشاء طريقة محددة للتعامل مع عدِّة أصناف مُشتقَّة، التي قد تتشارك ببعض الوظائف. ملاحظة: لا يمكن إنشاء كائن من صنف مجرد، حيث لا يمكن إلا اشتقاق تلك الأصناف. يستعمل الصنف المجرد لتقييد عمل الصنف الابن. الواجهات interfaces من بين الحالات التي نستعمل فيها الواجهات (interfaces) هي عندما نريد تطبيق التعددية الشكلية أي أن تكون طريقة تعاملنا متشابهة مع عدِّة أصناف. الواجهة هي مجموعة من الدوال المجردة أي أنك تعرف اسم الدالة مع المعاملات التي تقبلها لكن دون تحديد طريقة عمل الدالة، ويمكن للصنف أن يستعمل أكثر من واجهة، لكن يجب أن يعيد تعريف كل الدوال الموجودة في تلك الواجهة، انظر إلى المثال الآتي لأخذ فكرة عن الواجهات: <?php // تعريف واجهة interface MyInterface { // abstract functions // all must be public public function display(); public function another($argument); } // واجهة أخرى interface AnotherInterface { public function complete_it(); public function one_more(); } class Parent { function parent_fun() { echo "parent function"; } } // صنف يشتق صنفًا آخر ويستعمل واجهة class Demo extends Parent implements MyInterface, AnotherInterface { public function display() { echo "display complete"; } public function another($argument) { #code } public function complete_it() { #code } public function one_more() { #code } } ?> نستعمل الواجهات عندما نريد إنشاء طريقة موحدة للتعامل مع عدِّة أصناف، فمثلًا، نُنشِئ واجهة اسمها Database فيها دوال مجردة مثل select و insert وغيرها، ثم نستعمل تلك الواجهة في صنف MySQL وفي صنف SQLite، ونعيد تعريف الدوال الموجودة في الواجهة بما يلائم طريقة عمل كل نوع من أنواع قواعد البيانات. وبهذه الطريقة نستطيع أن نستعمل قواعد بيانات MySQL أو SQLite بنفس الآلية تمامًا. ملاحظة: يجب أن تكون جميع الدوال داخل الواجهة عامةً، يمكن أن يرث صنفٌ ما صنفًا آخر ويستعمل واجهة بنفس الوقت، لكن يجب أن يكون تعريف الاشتقاق قبل الواجهات. السمات Traits قدم الإصدار 5.4.0 من PHP ميزة السّمات Traits، وهي طريقة تسمح بإعادة استعمال الشيفرات في اللغات التي لا تسمح بالوراثة المتعددة، وهي تقلل من المحدوديات الناتجة عن عدم السماح بالوراثة المتعددة عن طريق إتاحة استعمال مجموعة من الدوال في عدة أصناف. أي لو كانت عندك مجموعة من الدوال العامة، وترغب في مشاركتها بين أكثر من صنف، فضعها في Trait ثم استعملها (use) في تلك الأصناف. يُعرف Trait عبر ذكر الكلمة المحجوزة trait متبوعةً باسمه، ثم تُعرَّف الدوال داخله. وتُستعمل الكلمة use عند تعريف صنف يستعمل Trait معين كما في المثال الآتي: <?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } class World { use HelloWorld; } $obj = new World(); $obj->sayHello(); // ستُطبع عبارة Hello World! ?> يمكن إعادة تعريف الدوال داخل الأصناف التي تستعمل Trait معيّن، كما في المثال الآتي: <?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } class World { use HelloWorld; } class NewWorld { use HelloWorld; public function sayHello() { echo 'Hello Universe!'; } } $obj1 = new World(); $obj1->sayHello(); // ستُطبع عبارة Hello World! $obj2 = new NewWorld(); $obj2->sayHello(); // ستُطبع عبارة Hello Universe! ?> يمكن استعمال أكثر من Trait في نفس الصنف عبر ذكر أسمائهم في عبارة use مفصولًا بينهم بفاصلة، لاحظ أنه إذا عُرِّفَت دالتين بنفس الاسم في أكثر من Trait، ثم استعملناها في صنف، فسيحدث تضارب وتظهر رسالة خطأ fetal error، ويمكنك حل مشكلة التضارب في الأسماء عبر استعمال المعامل insteadof أو عبر as كما في المثال الآتي: <?php trait A { public function smallTalk() { echo 'a'; } public function bigTalk() { echo 'A'; } } trait B { public function smallTalk() { echo 'b'; } public function bigTalk() { echo 'B'; } } class Talker { // لدينا في A و B دالتين اسمهما bigTalk و smallTalk // ما يلي سيجعل الصنف يستعمل الدالة smallTalk من B عوضًا عن مثيلتها في A // و bigTalk من A عوضًا عن B use A, B { B::smallTalk insteadof A; A::bigTalk insteadof B; } } class Aliased_Talker { use A, B { B::smallTalk insteadof A; A::bigTalk insteadof B; // لاحظ كيف استعملنا as لتغير اسم الدالة في الصنف B::bigTalk as talk; } } ?> مصادر مقالة Abstraction and Interface in PHP لصاحبها Harish Kumar فصل Objects في كتاب Practical PHP Programming فصل البرمجة غرضية التوجه في كتاب تعلم البرمجة بلغة PHP صفحات Object Interfaces و Traits في دليل PHP وغيرها.
  19. كان الغرض من البرمجة الكائنية (Object oriented programing اختصارًا OOP) هو السماح للمبرمجين بتسهيل تقسيم البرامج حسب وظيفتها؛ فالمبرمجون يُنشؤون "كائنات" ويضبطون بعض الخاصيات ثم يطلبون من تلك الكائنات أن تقوم بأشياءٍ معيّنة. مثلًا لدينا "الأكواب" عبارة عن كائنات، وتلك الأكواب لها خاصيات معيّنة مثل المادة المصنوعة منها (زجاج، أو بلاستيك، أو معدن) والسعة القصوى لها، كما يمكن إجراء عمليات عليها مثل ملء كوب. لكن عمومًا تنطوي كل تلك الأنواع تحت لواء "الأكواب" وإن اختلفت خاصياتها. أنُشِئت الأصناف (classes) في PHP لغرض التجريد (abstraction) والتغليف (encapsulation). والصنف هو مجموعة من المتغيرات والدوال التي تؤدي وظيفة مشابهة؛ وتساعد الأصناف في تجنب المشاكل الأمنية وذلك بفصل الواجهة (interface) عن طريقة التطبيق (implementation)، وتضيف الأصناف قيودًا إلى الوصول إلى المتغيرات والدوال. يُعرَّف الصنف بكتابة الكلمة المحجوزة class يليها اسم الصنف، ومن المستحسن اتباع طرق الكتابة التقليدية في أسماء الأصناف، حيث يبدأ اسم الصنف بحرفٍ كبير؛ هذا مثالٌ عن تعريف صنف بسيط: <?php class SimpleClass { // التعليمات البرمجية } ?> الشيفرة الموجودة ضمن الصنف لا تنفذ مباشرةً، إذ علينا أولًا أن قومة بإنشاء بإشاء كائن (object) من ذاك الصنف، الكائن هو نسخة من الصنف تكون جميع متغيرات ودوال ذاك الصنف جزءًا من خاصياتها (properties). يمكن إنشاء كائن من صنف كالآتي: object_name = new ClassName(); الخاصيات والدوال المتغيرات التي تكون عضوًا بالصنف تسمى خاصيات (properties)، وتُعرَّف عبر استخدام إحدى محددات الوصول public (عام) أو protected (محمي) أو private (خاص)، ويأتي بعدها التعريف الاعتيادي للمتغيرات، ويمكن أن تُسنَد القيم إليها مباشرةً، لكن يجب أن تكون تلك القيم ثابتة، أي لا تحتوي تعابير رياضية أو قيم معادة من دوال. أما الدوال الأعضاء في الأصناف، فتسمى توابع methods، وتُعرَّف كغيرها من الدوال، لكن مع الانتباه إلى ضرورة تحديد مجال الدالة (عامة أو محمية أو خاصة) كما في المثال الآتي: <?php class SimpleClass { // تعريف متغير أو خاصية public $var = 'a default value'; // تعريف دالة public function displayVar() { echo $this->var; } } ?> المتغير ‎$this متوفر داخل دوال الصنف تلقائيًا (أي ليس عليك إنشاؤه)، وهو يشير إلى الكائن الذي قام بإنشاء نسخة من الصنف، ويُستعمل للوصول إلى الخاصيات أو الدوال الموجودة في الصنف. لاحظ عدم وجود رمز الدولار ($) قبل اسم المتغير عند الوصول إليه عبر ‎$this. مثالٌ عن ما سبق: <?php class ClassName { // تعريف متغير public public $class_variable; // الدالة البانية function __construct() { $this->class_variable = 60 * 60; echo "this is the constructor <br>"; } // إعادة متغير في الصنف function get_global() { return $this->class_variable; } // تعديل متغير في الصنف function set_global($value) { $this->class_variable = $value; } // إظهار قيمة متغير في الصنف public function reset_display() { $this->private_function(); echo $this->get_global()." <br>"; } // دالة خاصة private function private_function() { $this->class_variable = 60 * 60; } } $object_name = new ClassName(); echo $object_name->get_global()."<br>"; $object_name->set_global(231); echo $object_name->get_global()."<br>"; $object_name->reset_display(); ?> لاحظ المفاهيم الآتية في المثال السابق التي شرحنا بعضها أعلاه: المتغير الذي يكون متاحًا للوصول في كل الصنف (‎$class_variable) يُعرَّف بالكلمة المحجوزة public؛ أما المتغيرات المحلية المُعرَّفة داخل دالة لا يمكن الوصول إليها إلا من تلك الدالة. يمكن الوصول إلى متغيرات أو دوال الصنف باستخدام ‎$this->variable_name;‎ و ‎$this->function_name();‎ على التوالي وبالترتيب. إذ أنَّ ‎$this يُشير إلى الصنف نفسه. الدالة البانية (constructor) هي دالة ذات معنى خاص في الأصناف؛ حيث تُشغَّل هذه الدالة عندما نُنشِئ كائنًا من ذاك الصنف، ويمكن أيضًا إرسال وسائط إلى الدالة البانية. سنشرح الدالة البانية والهادمة لاحقًا. ناتج السكربت السابق: it is constructor 3600 231 3600 ملاحظة: لا يُنصح بتعديل قيم خاصيات الفئات يدويًا، وإنما استعمل دوالًا خاصةً لهذا الغرض، فمثلًا لو كان عندك صنفٌ وظيفته حساب كمية الماء اللازمة لمدينة ما، ولديك خاصية اسمها population تُمثِّل عدد سكان المدينة، فلا تسمح بالوصول إليها مباشرةً، وإنما اكتب دالةً اسمها setPopulation مثلًا، واجعلها تُعدِّل قيمة عدد السكان وكل ما يتعلق بها من الحسابات تلقائيًا: $obj->setPopulation(200000); الوراثة نحاول دومًا عندما نبرمج ألّا نعيد كتابة الشيفرة مرارًا وتكرارًا، وأن نفصل بين تطبيق الشيفرة والواجهة (interface) لأسباب تتعلق بالحماية. الخيار الجديد المتاح أمامنا الآن هو استعمال الوراثة للقيام بالأمور السابقة بكفاءة. الوراثة في البرمجة كالوراثة في حياتنا، إذ يرث والدك بعض الخاصيات من جدك ويُعدِّلها أيضًا، وأنت أيضًا ترث بعض الخاصيات من والدك وتعدلها وتضيف غيرها. تسمى هذه العملية في البرمجة بالمصطلح inheritance. يمكن لأي صنف أن يوسِّع أو يشتق (extend) أصنافًا أخرى ويمكنه أن يصل إلى المتغيرات والدوال العامة والمحمية فيها فقط (أي لا يستطيع أن يصل إلى الدوال الخاصة private). <?php /** * الوراثة في PHP */ class Grandfather { // متغير عام public $global_variable; // الدالة البانية للصنف grandfather function __construct() { $this->global_variable = 56; echo "I am grandfather <br>"; } function default_function() { echo "this is default function in grandfather <br>"; } private function private_function() { echo "this is private function in grandfather <br>"; } protected function protected_function() { echo "this is protected function in grandfather <br>"; } public function public_function() { echo "this is public function in grandfather <br>"; } } /** * هذا صنف فرعي مشتق من الصنف Grandfather * وسيرث كل خاصياته عدا الخاصة (private) منها */ class Father extends Grandfather { // متغير عام public $father_var; function __construct() { // السطر الآتي مساوٌ للسطر => parent::__construct(); Grandfather::__construct(); $this->father_var = 256; echo "I am father <br>"; } public function display_all() { $this->default_function(); $this->protected_function(); $this->public_function(); echo "I am father's display_all <br>"; parent::public_function(); } } /** * هذا الصنف الابن يرث من الصنف الأب * ويرث أيضًا (بشكلٍ غير مباشر) من الصنف الجد */ class Child extends Father { // الدالة البانية في الصنف الابن function __construct() { Grandfather::__construct(); echo "I am child <br>"; } // يُعدِّل الابن في دالة موجودة في الأب // تسمى هذه العملية «إعادة تعريف الدوال» function display_all() { echo "function from father<br>"; // استدعاء دالة من الصنف الأب parent::display_all(); echo "new added in child<br>"; } } $obj = new Father(); $obj->display_all(); echo "<br><br><br>Child object call<br><br>"; $obj2 = new Child(); $obj2->display_all(); ?> الناتج: I am grandfather I am father this is default function in grandfather this is protected function in grandfather this is public function in grandfather I am father's display_all this is public function in grandfather Child object call I am grandfather I am child function from father this is default function in grandfather this is protected function in grandfather this is public function in grandfather I am father's display_all this is public function in grandfather new added in child يعطي المثال السابق صورةً كاملةً عن الوراثة، لنحاول فهمه: الصنف Child يرِث من الصنف Father، الذي بدوره يرث الصنف Grandfather؛ وهذا يُسمى الوراثة متعددة المستويات. الصنف الفرعي (subclass أي الصنف الذي يقوم بالوراثة) يمكنه الوصول إلى جميع الخاصيات غير الخاصة (private) للصنف الموروث (يسمى أيضًا superclass). يمكن للصنف الفرعي أن يستدعي دوال الصنف الموروث عبر استعمال الصيغة الآتية parent::function_name()‎ (يمكن استعمالها لمستوى وراثة وحيد فقط، أي يمكن للصنف Child أن يستعملها لاستدعاء دوال الصنف Father، ويمكن للصنف Father أن يستعملها للصنف Grandfather؛ لكن لا يمكن أن يستعملها الصنف Child لاستدعاء دوال الصنف Grandfather.) أو الصيغة الآتية SuperClass_name:function_name()‎ التي يمكن استعمالها لاستدعاء دوال الصنف Grandfather من الصنف Child. يمكن أن يُعدِّل الصنف الفرعي في دوال الصنف الأب، وذلك يُعرَف بإعادة التعريف (overriding). لا تدعم لغة PHP الوراثة المتعددة؛ أي لا يمكن للصنف أن يرث أكثر من صنف واحد. محددات الوصول لقد تطرقنا سابقًا إلى موضوع محددات الوصول بشكل مبسط، حان الوقت الآن لشرحها بالتفصيل. هنالك كلماتٌ محجوزةٌ تسمى محددات الوصول توضع قبل تعريف المتغيرات أو الدوال الأعضاء في الصنف، وتعيّن مَن الذي يستطيع الوصول إلى ذاك المتغير أو الدالة، وهي: public (عام): ذاك المتغير أو الدالة يمكن الوصول إليه من داخل الصنف أو من خارجه private (خاص): لا يمكن الوصول إلى المتغير أو الدالة إلا من داخل الصنف نفسه protected (محمي): يسمح بالوصول إلى المتغير أو الدالة من الصنف نفسه والصنف المُشتَق منه فقط final (نهائي): هذه الدالة لا يمكن إسناد قيمة أخرى إليه أو تعريفها في الأصناف المُشتقَة (لا يمكن استخدام final مع الخصائص/المُتغيّرات). نستعمل عادةً المُحدِّد public للخاصيات أو الدوال التي تريد الوصول إليها من خارج الصنف، أما private فتستعمل للأجزاء الداخلية التي لا يلزم الوصول إليها من خارج الصنف، أما protected فهي للخاصيات التي تستعمل في بنية الصنف (كما في private) لكن من المقبول توريثها إلى أصنافٍ أخرى كي يعدلوها بما يلائم. فمثلًا، لو كنا نكتب صنفًا للاتصال بقاعدة البيانات، فسيكون مقبض الاتصال (connection handle) لقاعدة البيانات مخزنًا في متغير خاص، لأنه يستعمل داخل الصنف فقط، ولا يجب أن يكون متوفرًا لمستخدم هذا الصنف؛ أما عنوان الشبكة لمضيف خادوم قواعد البيانات، فهو خاص بالصنف، ولا يجب على المستخدم تعديله، لكن من المقبول تعديله من صنفٍ يرث هذا الصنف. أما الطلبيات التي تُجرى على قاعدة البيانات، فيجب أن تكون عامة، كي يستطيع مستخدم الصنف الوصول إليها. الدالة البانية والدالة الهادمة ذكرنا الدالة البانية سابقًا ومررنا عليها سريعًا، وقلنا وقتها أنَّ الدالة البانية تُنفَّذ عند إنشاء كائن من الصنف، وهي مناسبة لعمليات تهيئة المتغيرات وإعطائها قيمةً ابتدائيةً. تحمل هذه الدالة اسم ‎__construct. يجدر بالذكر أنَّ الدالة البانية للصنف الأب لا تستدعى تلقائيًا عند إنشاء كائن للصنف الابن، ويجب استدعاؤها يدويًا عبر parent::__construct()‎ ضمن الدالة البانية للصنف الابن. لكن إن لم تُعرَّف دالة بانية للصنف الابن، فسيرث الدالة البانية للصنف الأب تلقائيًا. مثالٌ عليها سيوضح ما سبق: <?php class BaseClass { function __construct() { print "In BaseClass constructor\n"; } } class SubClass extends BaseClass { function __construct() { parent::__construct(); print "In SubClass constructor\n"; } } class OtherSubClass extends BaseClass { // سيرث هذا الصنف الدالة البانية للصنف الأب } // ستنفذ الدالة البانية للصنف BaseClass $obj = new BaseClass(); // ستنفذ الدالة البانية للصنف BaseClass // وستنفذ الدالة البانية للصنف SubClass $obj = new SubClass(); // ستنفذ الدالة البانية للصنف BaseClass $obj = new OtherSubClass(); ?> أما الدالة الهادمة، فهي الدالة التي تُنفَّذ عندما لا يعود الكائن موجودًا، وتُعرَّف -كما الدالة البانية- بذكر اسمها ‎__destruct، ولا تستدعى الدالة الهادمة للصنف الأب إن أُعيد تعريفها في الصنف الابن. <?php class MyDestructableClass { function __construct() { print "In constructor\n"; $this->name = "MyDestructableClass"; } function __destruct() { print "Destroying " . $this->name . "\n"; } } $obj = new MyDestructableClass(); // الناتج: In constructor echo "We will destroy \$obj \n"; unset($obj); // الناتج: Destroying MyDestructableClass echo '$obj Destroyed'; ?> معرفة نوع الكائنات لقد رأيت كيف أنَّ الوراثة هي أمرٌ مهمٌ في البرمجة الكائنية، ولكن قد تختلط عليك الكائنات، ولن تدري لأي صنفٍ تنتمي. يأتي الحل مع الكلمة المحجوزة instanceof التي يمكن استعمالها كأحد المعاملات، فستُعيد TRUE إن كان الكائن المذكور اسمه على يسارها تابعًا لصنفٍ ما أو لصنفٍ مشتقٍ من الصنف المذكور على يمينها. على سبيل المثال: $obj = new SubClass(); if ($obj instanceof SubClass) { } if ($obj instanceof BaseClass) { } ناتج العبارتان الشرطيتان السابقتان هو TRUE لأن ‎$obj هو كائنٌ ينتمي إلى الصنف SubClass (أول عبارة شرطية)، وينتمي إلى صنفٍ مشتقٍ من BaseClass (العبارة الشرطية الثانية). أما لو أردت أن تعلم إن كان الكائن ينتمي إلى صنفٍ مشتقٍ من الصنف المذكور، فاستعمل الدالة is_subclass_of()‎، الذي تقبل وسيطين، أولهما هو الكائن الذي سنختبره، والثاني هو اسم الصنف الأب. <?php class BaseClass {} class SubClass extends BaseClass {} $obj = new SubClass(); if ($obj instanceof SubClass) { echo 'instanceof is TRUE'; } if (is_subclass_of($obj, 'SubClass')) { echo 'is_subclass_of is TRUE'; } ?> ستجد أن instanceof في المثال السابق ستعطي TRUE، بينما ستعطي is_subclass_of()‎ القيمة FALSE، لأن ‎$obj ليس كائنًا لصنف مشتق من الصنف SubClass، وإنما هو من الصنف SubClass نفسه. تحديد الصنف في معاملات الدوال لنقل أنك تريد تمرير كائن من صنف معيّن إلى دالة، ولا تريد السماح بتمرير سلسلة نصية أو رقم لها بدلًا من الكائن ذي الصنف المحدد؛ تستطيع فعل ذلك بذكر اسم الصنف قبل المعامل أثناء تعريف الدالة، كما يلي: <?php class Numbers { public function print_random() { echo rand(, 10); } } class Chars {} function random (Numbers $num) { $num->print_random(); } $char = new Chars(); random($char); // fatal error: Argument 1 passed to random() must be an instance of Numbers ?> الدوال "السحرية" عندما تشاهد دالةً يبدأ اسمها بشرطتين سفليتين، فاعلم أنها دالة سحرية (Magic function)، وهي متوفرة من PHP، وتحجز PHP جميع أسماء الدوال التي تبدأ بشرطتين سفليتين على أنها دالة سحرية، لذا يُنصَح بتجنب استعمال هذا النمط من التسمية لتلافي حدوث تضارب في المستقبل مع الدوال السحرية التي قد تعرفها الإصدارات الحديثة من PHP. لقد رأينا سابقًا الدالتين البانية ‎__construct()‎ والهادمة ‎__destruct()‎، وسنتحدث هنا عن الدوال ‎__get()‎ و ‎__set()‎ و ‎__call()‎ و ‎__toString()‎. تُعرَّف الدالتان ‎__get()‎ و ‎__set()‎ داخل الأصناف، تستعمل الدالة ‎__get()‎ عندما تحاول قراءة متغير غير مُعرَّف من متغيرات الصنف، وتُستعمَل الدالة ‎__set()‎ عند محاولة إسناد قيمة لمتغير غير موجود، انظر إلى المثال الآتي: <?php class MagicClass { public $name = 'Magic'; private $age = 123; public function __get($var) { echo "getting: $var "; echo $this->$var; } public function __set($var, $value) { echo "setting: $var to $value"; $this->$var = $value; } } $obj = new MagicClass(); echo $obj->name; // الناتج: Magic $obj->age = 123; // أصبح بإمكاننا -باستعمال الدوال السحرية المُعرفة في الصنف- الوصول إلى متغير ذي وصولٍ خاص، لا يجدر بنا فعل ذلك عمومًا. echo $obj->age; // الناتج: getting: age 123 echo $obj->last_name; // ستحاول الدالة __get الحصول على قيمة الخاصية last_name، لكنها غير موجودة، وسيظهر خطأ من مرتبة Notice لإشارة إلى ذلك. ?> قد نستفيد من الدالتين ‎__get()‎ و ‎__set()‎ بإظهار رسالة خطأ عند محاولة الوصول إلى عناصر غير موجودة (أو لا يُمسَح لنا بالوصول إليها). أما دالة ‎__call()‎ فغرضها مشابه لغرض ‎__get()‎ إلا أنها تُستعمَل عند محاولة استدعاء دالة غير موجودة. ستستدعى الدالة السحرية ‎__toString()‎ في حال تمت محاولة طباعة الكائن كسلسلة نصية. هذه الدالة بسيطة جدًا وتعمل كما يلي: <?php class MagicClass { public function __toString() { return "I'm Magical! :-)"; } // ... } $obj = new MagicClass(); echo $obj; ?> مصادر مقالات Classes in PHP و Inheritance in PHP لصاحبها Harish Kumar.فص ل Objects في كتاب Practical PHP Programming. فصل البرمجة غرضية التوجه في كتاب تعلم البرمجة بلغة PHP. صفحات Introduction و The Basics و Constructors and Destructors و Visibility و Object Inheritance و Magic Methods و Type Hinting في دليل PHP وغيرها.
  20. php 101

    سنعلم في هذا الدرس عن المصفوفات وحلقة foreach. لنفترض أنَّك تريد أن تُخزِّن مقدارًا كبيرًا من البيانات؛ أول 10000 من مضاعفات الرقم 5 على سبيل المثال، فعليك أنَّ تُعرِّف 10000 متغير لهم 10000 اسم؛ وهذه مهمة صعبة ومضنية بالتأكيد. أحد الحلول هو تخزين البيانات في مصفوفة، إذ يمكننا تخزين أي عدد نريده من القيم في مصفوفة وحيدة فقط! لنلقِ نظرةً عن آلية عمل المصفوفات. <?php // تعريف مصفوفة ذات ثلاثة عناصر $type1 = array('first element', 'second element', 'third element'); // نستعمل الدالة print_r لطباعة جميع عناصر المصفوفة // الناتج: Array ( [0] => first element [1] => second element [2] => third element ) print_r($type1); echo "<br>"; // نستعمل المفاتيح (الفهارس) للوصول إلى قيم معيّنة في المصفوفة // لاحظ أنَّ المفاتيح رقمية من 0 حتى 2 echo $type1[0]; echo "<br>"; echo $type1[1]; echo "<br>"; echo $type1[2]; echo "<br>"; ?> في السطر الثالث من الشيفرة السابقة، عرَّفنا مصفوفةً اسمها ‎ $type1وملأناها بثلاث قيم (first element، و second element، و third element). كيف يمكننا استعمالها الآن؟ كل قيمة من القيم المُخزَّنة في المصفوفة مرتبطة بمُعرِّف فريد يسمى الفهرس (index)؛ يمكنك الوصول إلى تلك القيم عبر الفهرس الخاص بها. يطبع السطر السابع في المثال السابق المصفوفة بأكملها باستعمال الدالة print_r()‎، وسترى أنَّه على الرغم من أنَّك قد ملأت القيم فقط، لكنك ستحصل أيضًا على أرقامٍ تبدأ من الصفر وترتبط بتلك القيم؛ وفي الواقع، تلك الأرقام هي الرقم التسلسلي للقيمة (تذكر أننا نبدأ العد في البرمجة من الرقم 0 بدلًا من 1). ثم قمنا بطباعة القيم التي خزناها في الموضع 0 و 1 و 2 على التوالي وبالترتيب. المصفوفات الترابطية استخدمنا الفهارس الافتراضية في المثال السابق (0، و 1، و2)، لكن يمكننا أن نُعرِّف الفهارس يدويًا كما في المثال الآتي: <?php // طريقةٌ أخرى لتعريف مصفوفة $type2 = array('key'=>'value', 'key2'=>'value2', 'key3'=> 'value3'); // الناتج: Array ( [key] => value [key2] => value2 [key3] => value3 ) print_r($type2); echo "<br>"; // المفاتيح هنا نصيّة، وهي key1، و key2، و key3 echo $type2['key3']; ?> عرَّفنا في المثال السابق الفهارس الخاصة بنا (تُسمى أيضًا المفاتيح [keys]) التي ترتبط مع تلك القيم. يسمى هذا النوع من المصفوفات بالمصفوفات ترابطية (associative arrays). الوصول إلى عناصر المصفوفات تُعتبَر كل قيمة في المصفوفة متغيرًا مستقلًا، فيمكننا أن نجري جميع العمليات التي يمكن القيام بها على المتغيرات (كالزيادة والنقصان وإسناد القيم …إلخ.): <?php // نعرِّف مصفوفةً فارغةً $arr = array(); // يمكننا إسناد البيانات إلى عناصر المصفوفة كما يلي $arr[0] = 'academy'; $arr[1] = 'hsoub'; // قد لا تكون المفاتيح ذات أرقام متتالية (لاحظ عدم وجود المفتاحين 2 و 3) $arr[4] = 'com'; // يمكننا استعمال نمطي المفاتيح (الرقمية والنصية) في نفس المصفوفة $arr['day'] = 'Monday'; $arr['num1'] = 4; $arr['num2'] = 5; // كل عنصر في المصفوفة مستقل تمامًا عما سواه $arr['num3'] = $arr['num1'] + $arr['num2']; // سنطبع كامل المصفوفة باستعمال print_r print_r($arr); ?> لاحظ كيف أننا عرفنا بدايةً مصفوفةً فارغة، ثم أضفنا عناصرها بذكر المتغير الحاوي على مصفوفة متبوعًا بأقواسٍ مربعة ([]) بداخلها مفتاح العنصر. يجدر بالذكر أننا نستطيع أن نستعمل مفاتيح رقمية ونصية في نفس المصفوفة. إذا أردنا أن نجعل PHP تُرقِّم عناصر المصفوفة تلقائيًا عند إسناد قيم لها، فيكفي أن نضع أقواسًا مربعة فارغة كما يلي: <?php // نعرِّف مصفوفةً فارغةً $arr = array(); // يمكننا جعل PHP تُرقِّم العناصر تلقائيًا كما يلي $arr[] = 'academy'; $arr[] = 'hsoub'; $arr[] = 'com'; // سنطبع كامل المصفوفة باستعمال print_r // الناتج: Array ( [0] => academy [1] => hsoub [2] => com ) print_r($arr); ?> يجدر بالذكر أننا نستطيع أن ندرج قيمة عنصر من عناصر المصفوفة في سلسلةٍ نصيةٍ مباشرةً كما في المتغيرات (أي يجب أن تكون علامة الاقتباس مزدوجةً) لكن علينا في المصفوفات أن نحيط اسم العنصر بقوسين معقوفين كما يلي (لاحظ أننا استعملنا الطريقة الأكثر شيوعًا الآن في تعريف المصفوفات، ألا وهي إحاطة عناصر المصفوفة بقوسين مربعين [] كما يظهر في المثال أدناه): المصفوفات والحلقات لنفترض أننا نريد إجراء بعض العمليات على كمية كبيرة من البيانات مخزَّنة في مصفوفة (ولنقل أننا نريد طباعة البيانات، أو حساب مجموع الأرقام الموجودة في المصفوفة)؛ فسنستعمل لهذا الغرض الحلقات، لنلقِ نظرةً على مثالٍ عن حلقة for: <?php $a = [1, 21, 23, 43, 32, 23, 4]; // عناصر المصفوفة هي: $a[0], $a[1], $a[2]... // سنُهيِّئ متغيرًا للمجموع ونسند إليه القيمة 0 $sum = 0; for($i = 0; $i < 7; $i++) { // ستزداد قيمة المتغير $i في كل تكرار للحلقة // أي أن قيمته ستتغير إلى قيمة مفتاح العنصر التالي في المصفوفة $sum += $a[$i]; } echo $sum; ?> أنصحك بأن تُعيد حلّ المثال السابق باستعمال حلقتَيّ while و do-while من درس الحلقات لكي تتدرب على استعمالها. هنالك حلقةٌ إضافيةٌ في PHP وُضِعَت خصيصًا للمصفوفات، اسمها حلقة foreach. إذ تبدأ هذه الحلقة من أول عنصر في المصفوفة وتنتهي بآخر عنصر فيها. لنعد كتابة المثال السابق باستخدام حلقة foreach: <?php $a = [1, 21, 23, 43, 32, 23, 4]; // عناصر المصفوفة هي: $a[0], $a[1], $a[2]... // سنُهيِّئ متغيرًا للمجموع ونسند إليه القيمة 0 $sum = 0; foreach ($a as $v) { // لو كنا نستعمل حلقة من نوع آخر، لكنا قد كتبنا // $v = $a[$i]; // $sum += $v; // i++; $sum += $v; } echo $sum; ?> نُسنِد -في كل تكرار للحلقة- قيمةً جديدةً للمتغير الذي اسمه ‎$v ونعطيه قيمة العنصر التالي في المصفوفة ‎$a؛ حلقة foreach مفيدة جدًا عندما لا تعرف عدد العناصر الموجودة في المصفوفة، أو إذا كنت تستعمل مصفوفة ترابطية (associative arrays). حلقة foreach مع المصفوفات الترابطية أما في حالة المصفوفات الترابطية، فعلينا تعريف متغيرين (بدلًا من واحد) لأننا لا نعلم قيمة الفهرس (أو المفتاح [key]) لكل عنصر. أول متغير نُعرِّفه هو المفتاح، والثاني هو القيمة التي ترتبط به. الشكل العام لحلقة foreach هو: foreach (array as $key => $value) { statements } تمعّن في المثال الآتي وانظر كيف أُسنِد المفتاح إلى متغير، وأُسنِدَت قيمته إلى متغيرٍ آخر؛ يجدر بالذكر أنَّ المصفوفة المستعملة هي مصفوفة متعددة الأبعاد، أي أنَّ قيمة العنصر هي بدورها مصفوفةٌ أخرى، ولا مانع من استعمال حلقة foreach داخل حلقة foreach أخرى إن دعت الضرورة إلى ذلك. <?php // نُعرِّف مصفوفة ذات بعدين $arr = [ 'student1' => array('SN' => 16472, 'math_grade' => 'A+'), 'student2' => array('SN' => 16483, 'math_grade' => 'C'), 'student3' => array('SN' => 16587, 'math_grade' => 'A') ]; // حلقة foreach تمر على جميع عناصر المصفوفة الرئيسية foreach ($arr as $student => $info) { // لاحظ كيف أنَّ القيمة المُنسدَة إلى المتغير $info هي مصفوفة أخرى echo "the serial number for $student is {$info['SN']}, and he got {$info['math_grade']} grade in math!"; } ?> دوال التعامل مع المصفوفات ألم تتساءل كيف سنعلم إن كانت المصفوفة تحتوي عنصرًا ما أم لا؟ ربما فكرت باستعمال حلقةٍ ما للمرور على جميع عناصر المصفوفة، لكن PHP تسهِّل عليك الأمر وتوفر لك دالةً لاختبار وجود عنصرٍ ما في المصفوفة ألا وهي الدالةin_array() ‎ التي تقبل وسيطين أولهما هو القيمة التي سيُبحَث عنها، وثانيهما هي المصفوفة التي سيُبحَث فيها؛ وستعيد هذه الدالة القيمة TRUE إن وجِدَت تلك القيمة في المصفوفة، و FALSE خلا ذلك. أما لو أردت معرفة إن كان مفتاحٌ ما موجودًا في المصفوفة، فاستعمل الدالةarray_key_exists() ‎ التي تقبل وسيطين أيضًا أولهما هو المفتاح الذي يُبحَث عنه، وثانيهما هو المصفوفة التي سيُبحَث فيها؛ وستعيد هذه الدالة TRUE إن وجد ذاك المفتاح، و FALSE عدا ذلك. مثالٌ عن استعمالهما: <?php $arr = ['subdomain' => 'academy', 'domain' => 'hsoub', 'root_domain' => 'com']; // التحقق إن كانت القيمة «hsoub» موجودةً في المصفوفة if (in_array('hsoub', $arr)) { echo '"hsoub" value found'; } if (array_key_exists('subdomain', $arr)) { echo '"subdomain" key found'; } ?> هل تتذكر كيف قسّمنا السلاسل النصية إلى قسمين يفصل بينهما محرف معيّن في درس السلاسل النصية وحصلنا على الجزء الواقع بعد ذاك المحرف؟ الدالة explode()‎ تفعل المِثل، لكنها تُخزِّن الناتج في مصفوفة، حيث تقبل وسيطين أولهما هو السلسلة النصية التي تُمثِّل الفاصل بين عناصر المصفوفة، وثانيهما هو السلسلة النصية التي تريد تقسيمها؛ انظر إلى ناتج المثال الآتي لإزالة الغموض عن الكلام السابق: <?php $str = 'hsoub academy is the best academy ever'; // سنقسم السلسلة النصية السابقة عند كلمة is، ثم سنطبع مخرجاتها $arr1 = explode('is', $str); // الناتج: Array ( [0] => hsoub academy [1] => the best academy ever ) print_r($arr1); // سنقسم السلسلة النصية السابقة عند كلمة academy، مما يُنتِج ثلاثة عناصر في المصفوفة $arr2 = explode('academy', $str); // الناتج: Array ( [0] => hsoub [1] => is the best [2] => ever ) print_r($arr2); ?> أما لو أردت دمج عناصر المصفوفة وتحويلها إلى سلسلة نصية، فاستعمل الدالة implode()‎؛ التي لها شكلان عامان أحدهما يقبل وسيطًا وحيدًا هو المصفوفة التي تريد تحويلها إلى سلسلة نصية؛ والشكل الثاني يقبل وسيطين أولهما هو السلسلة النصية التي ستوضع بين عناصر المصفوفة وثانيهما هو المصفوفة التي تريد تحويلها إلى سلسلة نصية. <?php $arr = ['academy', 'hsoub', 'com']; // إن استعملنا implode ذات الشكل الأول، فسنحصل على academyhsoubcom $str1 = implode($arr); echo $str1; // أما لو استعملنا الشكل الثاني، ومررنا «.» كوسيط، فسنحصل على academy.hsoub.com $str2 = implode('.', $arr); echo $str2; ?> يُلخِّص الجدول الآتي بعض دوال المصفوفات الشهيرة:. table{border: 1px solid, black; border-collapse: collapse;} th, td{border: 1px solid black;padding: 5px 10px;} th{background-color: #fbfcfc;} الدالة شرحها array_merge()‎ يُمرَّر إليها أكثر من مصفوفة كوسيط مهمتها هي دمج تلك المصفوفات مع بعضها بعضًا وإعادة المصفوفة الناتجة array_rand()‎‎ اختيار قيمة عشوائية واحدة أو أكثر تقبل وسيطًا إجباريًا هو المصفوفة التي ستؤخذ القيمة العشوائية منها ووسيطًا اختياريًا يُحدِّد عدد القيم التي ستُعاد تُعيد سلسلةً نصيةً تحوي مفتاح العنصر العشوائي المُختار إن اختارت قيمةً عشوائيةً وحيدة تعيد مصفوفة بمفاتيح العناصر العشوائية إن كان الوسيط الثاني أكبر من 1 ()array_search تبحث في المصفوفة عن قيمة مُعيّنة وستُعيد المفتاح المقابل لها إن وُجِدَت تقبل وسيطين أولهما هو القيمة التي ستبحث عنها، وثانيهما هو المصفوفة التي سيُبحَث فيها array_sum()‎ حساب مجموع القيم العددية في مصفوفة تقبل وسيطًا وحيدًا هو المصفوفة المُراد حساب مجموع الأعداد فيها ()array_unique تُزيل هذه الدالة جميع التكرارات في مصفوفة تُمرَّر إليها كوسيط ()count ربما هذه من أهم الدوال السابقة، إذ تُعيد عدد العناصر الموجودة في مصفوفة تُمرَّر إليها كوسيط. نستفيد كثيرًا من هذه الدالة في حلقة for إن لم نكن نعرف عدد عناصر المصفوفة نستطيع أن نكتب: for (int i=0; i<array.count(); i++) {} تمرين لديك المصفوفة الآتية باسم names: Array ( [16472] => Ayham [16483] => Ameen [15789] => Bashir ) والمصفوفة باسم grades: Array ( [16472] => Array ( [math] => 62 [arabic] => 76 [english] => 75 ) [16483] => Array ( [math] => 85 [arabic] => 71 [english] => 82 ) [15789] => Array ( [math] => 52 [arabic] => 86 [english] => 93 ) ) اكتب برنامجًا يأخذ اسم الطالب ثم يطبع جميع علاماته. المصادر مقال Array and foreach loop in PHP لصاحبه Harish Kumar. كتاب تعلم البرمجة بلغة PHP. صفحات Arrays و array وما هو موجود في Array Functions.
  21. سنكمل الآن ما تعلمناه في الدرس السابق عن السلاسل النصية. وقد كان محتوى الدرس الأول كالآتي: إنشاء والوصول إلى السلاسل النصية باستخدام $ و {}، واستخدام الدالة strlen()‎. البحث في السلاسل النصية باستعمال الدوال: strstr()‎ strpos()‎ و strrpos()‎ substr_count()‎ strpbrk()‎ الاستبدال في السلاسل النصية باستخدام الدوال: str_replace()‎ ()substr_replace ()strtr strtr()‎ التعامل مع حالات الحروف الكبيرة (uppercase) والصغيرة (lowercase) باستخدام الدوال: strtolower()‎ strtoupper()‎ ucfirst()‎ lcfirst()‎ ucword()‎ النسخ غير الحساسة لحالة الأحرف لجميع الدوال السابقة. أما هذا الدرس فسيحتوي على ما يلي: تنسيق السلاسل النصية باستخدام printf()‎، بما في ذلك تعيين دقة الأرقام العشرية. إزالة الفراغات (trimming) من أطراف السلاسل النصية باستعمال الدوال: trim()‎ ltrim()‎ rtrim()‎ إضافة حواشي (paddings) للنصوص باستعمال الدوال: str_pad()‎ STR_PAD_RIGHT STR_PAD_LEFT STR_PAD_BOTH التفاف (wrapping) النصوص عبر استعمال الدالة wordwrap()‎. تنسيق الأرقام باستخدام الدالة number_format()‎. الوقت والتاريخ. تنسيق السلاسل النصية الدالة printf()‎ الدالة printf()‎ هي أداةٌ قويةٌ تمكِّنك من تنسيق السلاسل النصية بطرقٍ مختلفة، تأخذ printf()‎ وسيطًا يُسمى سلسلة التنسيق (format string) يُتبَع عادةً بوسيطٍ اختياري أو أكثر يحتوي على السلسلة أو السلاسل التي ستوضع في السلسلة السابقة، ثم ستطبع هذه الدالة النتيجة النهائية. سلسلة التنسيق تحتوي على نصٍ عادي وفيه مُحدِّدات التنسيق (conversion specifications)، يتطلب وجود كل محدد تنسيق وسيطًا إضافيًا يُمرَّر إلى printf()‎، ومهمته هي تنسيق ذاك الوسيط ووضعه في سلسلة التنسيق، ثم بعد ذلك ستُعرَض السلسلة النهائية المُنسَّقة؛ تبدأ محددات التنسيق دومًا بإشارة النسبة المئوية (%)، ربما يبدو الأمر معقدًا للوهلة الأولى، لكن مثالًا بسيطًا كهذا سيجعل إيصال الفكرة أمرًا هينًا: <?php // الناتج: "Pi rounded to a whole number is: 3" printf( "Pi rounded to a whole number is: %d", M_PI ); ?> إن عبارة "Pi rounded to a whole number is: %d" هي سلسلة التنسيق، و "%d" ضمن السلسلة السابقة هي محدد للتنسيق، وفي هذه الحالة، يُخبِر هذه المحدد الدالة printf()‎ أن تقرأ الوسيط الإضافي وتضعه -بعد تنسيقه كعدد صحيح- في سلسلة التنسيق؛ الوسيط الإضافي هو الثابت M_PI الموجود في لغة PHP، التي يُمثِّل القيمة التقريبية للعدد π بعدد معيّن من المنازل العشرية (14 منزلة افتراضيًا)؛ أي أنَّ النتيجة النهائية لاستدعاء الدالة السابقة هي طباعة سلسلة التنسيق مع استبدال "%d" بقيمة الثابت π مُقرَّبًا إلى أقرب عدد صحيح. المزيد من المُحدِّدات: b: معاملة الوسيط كعدد صحيح (integer) وتنسيقه كعدد ثنائي. c: معاملة الوسيط كعدد صحيح وتنسيقه كمحرف بنظام ASCII الذي يحمل نفس القيمة العددية. d: معاملة الوسيط كعدد صحيح وتنسيقه كعدد عشري مع إشارة (signed). e: تنسيق الوسيط بالطريقة العلمية (مثلًا، 3.45e+2). f: تنسيق الوسيط كعدد ذو فاصلة عائمة (floating point)، آخذًا بالحسبان إعدادات «المحليّة» (locale) الحالية (على سبيل المثال، تستعمل بعض الدول الأوروبية الفاصلة كعلامة تفصل الأرقام الصحيحة عن الأرقام العشرية عوضًا عن النقطة؛ أي 3,14 بدلًا من 3.14). F: تنسيق الوسيط كعدد ذو فاصلة عائمة بغض النظر عن إعدادات المحليّة. o: معاملة الوسيط كعدد صحيح وتنسيقه كعدد بالنظامي الثماني. s: تنسيق الوسيط كسلسلة نصيّة. u: معاملة الوسيط كعدد صحيح وتنسيقه كعدد عشري دون إشارة (unsigned). x: معاملة الوسيط كعدد صحيح وتنسيقه كعدد بالنظام الست عشري بأحرفٍ ذات الحالة الصغيرة (lowercase). X: معاملة الوسيط كعدد صحيح وتنسيقه كعدد بالنظام الست عشري بأحرفٍ ذات الحالة الكبيرة (uppercase). %: إظهار إشارة النسبة المئوية (%)، لا يتطلب هذا المُحدِّد وجود وسيط إضافي. إضافة حواشي إلى المخرجات يمكنك إضافة محارف إلى يسار (افتراضيًا) أو إلى يمين الوسيط الذي يتم تنسيقه كي يُصبِح بعرضٍ معيّن، وهذا مفيدٌ إن أردت أن تُضيف أصفارًا تسبِق الأعداد، أو أن تحاذي عدِّة سلاسل نصية أفقيًا عبر إضافة فراغات على جوانبها. <?php // الناتج‏‎: "000123" printf( "%06d<br/>", 123 ); // الناتج‏‎: "004567" printf( "%06d<br/>", 4567 ); // الناتج‏‎: "123456" printf( "%06d<br/>", 123456 ); ?> دقة الأرقام عندما تُظهِر الأعداد ذات الفاصلة العائمة باستخدام المحدِّد f أو F، يمكنك استعمال مُحدِّد لدقة الأرقام لتعيين عدد المنازل العشرية التي سيُقرَّب (أو يدوَّر) إليها الرقم. لإضافة مُحدِّد دقة الأرقام، أضف نقطة (.) يلحقها عدد المنازل العشرية التي ستستخدم، قبل مُحدِّد النوع؛ انظر إلى المثال الآتي للتوضيح: <?php // الناتج‏‎: "123.456700" (الدقة الافتراضية) printf( "%f<br />", 123.4567 ); //الناتج ‏‎: "123.46" printf("%.2f<br />", 123.4567 ); // الناتج‏‎: "123" printf("%.0f<br />", 123.4567 ); // الناتج‏‎: "123.4567000000" printf("%.10f<br />", 123.4567 ); ?> يمكنك استخدام مُحدِّد الحاشية مع مُحدِّد الدقة، في حال أردت أن يكون طول الرقم معينًا (بما في ذلك الأرقام بعد الفاصلة العشرية، والفاصلة نفسها أيضًا): <?php // الناتج‏‎: "123.46" printf( "%.2f<br />", 123.4567 ); // الناتج‏‎: "000000123.46" printf( "%012.2f<br />", 123.4567 ); // الناتج‏‎: " 123.4567" printf( "%12.4f<br />", 123.4567 ); ?> إزالة الفراغات من أطراف السلاسل النصية قد لا ترغب في بعض الأحيان بوجود أيّة فراغات قبل أو بعد السلسلة النصية، وفي هذه الحالة نستعمل هذه الدوال: trim()‎: إزالة الفراغات (white-space) من بداية ونهاية السلسلة النصية. ltrim()‎: إزالة الفراغات من بداية السلسلة النصية فقط. rtrim()‎: إزالة الفراغات من نهاية السلسلة النصية فقط. انظر إلى ناتج المثال الآتي للتوضيح: <?php echo trim(" hsoub "); echo ltrim(" hsoub "); echo rtrim(" hsoub "); ?> إضافة حواشي إلى النصوص لقد رأينا سابقًا كيف يمكننا استخدام الدالة printf()‎ لإضافة حواشي إلى بداية أو نهاية سلسلة نصيّة؛ لكن لغة PHP توفِّر دالةً مخصصةً لهذا الأمر اسمها str_pad()‎، وهي أكثر مرونةً من printf()‎ وأسهل استخدامًا. لاستعمال الدالة str_pad()‎، مرِّر السلسلة التي ستتم إضافة الحواشي إليها، وعرض السلسلة النهائي، وستعيد الدالة السلسلة وقد تمت إضافة فراغات إلى يمينها (افتراضيًا): <?php echo '<pre>'; echo str_pad( "Hello, world!", 20 ); // الناتج‏‎: "Hello, world! " echo '</pre>'; ?> ولإضافة محارف أخرى غير الفراغ كحاشية، فمرِّر سلسلةً نصيةً كوسيطٍ ثالثٍ اختياري، لاحظ أنَّك تستطيع استخدام محرف وحيد أو أكثر من محرف؛ وفي الحالة الأخيرة، ستُكرَّر السلسلة النصية حسب العرض المُحدَّد: <?php // الناتج‏‎: "Hello, world!*******" echo str_pad( "Hello, world!", 20, "*" ) . "\n"; // الناتج‏‎: "Hello, world!1231231" echo str_pad( "Hello, world!", 20, "123" ) . "\n"; ?> يمكنك جعل الدالة str_pad()‎ تضع الحاشية على يسار السلسلة النصية، أو على يمنيها ويسارها معًا؛ وذلك بتمرير وسيط ثالث اختياري يحتوي على ثوابت الدالة المذكورين في الجدول الآتي: STR_PAD_RIGHT: إضافة الحاشية على اليمين (الحالة الافتراضية)، مما يحاذي السلسلة النصيّة إلى اليسار. STR_PAD_LEFT: إضافة الحاشية على اليسار، مما يحاذي السلسلة النصيّة إلى اليمين. STR_PAD_BOTH: إضافة الحاشية على الطرفين الأيمن والأيسر معًا، مما يؤدي إلى توسيط السلسلة النصية ما أمكن. مثال: (لاحظ وجود 3 محارف للحاشية على اليسار، و4 على اليمين؛ إذ لا يمكن توسيطها تمامًا): <?php // الناتج‏‎: "***Hello, world!****" echo str_pad( "Hello, world!", 20, "*", STR_PAD_BOTH ) . "\n"; ?> التفاف النصوص أحيانًا يكون عندك نصٌ طويلٌ مثل رسائل البريد الإلكتروني أو المقالات، وربما تريد أن تُقسَّم الأسطر بعرضٍ مختلف. تفعل الدالة wordwrap()‎ هذا الأمر؛ يمكنك تحديد عدد المحارف في السطر عبر هذه الدالة، انظر إلى هذا المثال أولًا: <?php $myString = "this is my string which is very long. it is containing five lines and a number of white spaces"; echo wordwrap ($myString); echo "<br><br><br>"; echo wordwrap ($myString, 40); echo "<br><br><br>"; echo wordwrap ($myString, 40, "<br />"); ?> لاحظ النتيجة بنفسك بفتح مصدر صفحة الويب ورؤية النتيجة لمختلف الجمل بقيمٍ مختلفة للوسيط الثاني (غير 40، مثل 10، أو 15، أو 20 ...إلخ.). تنسيق الأعداد تُستعمَل الدالة number_format()‎ لتنسيق الأعداد، وتستقبل وسيطًا أو وسيطين أو أربعة وسائط. أول وسيط هو العدد الذي سيُنسَّق الوسيط الثاني هو عدد المنازل العشرية الوسيط الثالث هو المحرف الذي سيفصل بين الأعداد الصحيحة والأرقام العشرية أما رابع وسيط، فيُحدِّد المحرف الذي سيفصل بين الآلاف في الأعداد الصحيحة يوضَّح ما سبق بالمثال الآتي: <?php $myNumber = 12344555.3453; // الناتج‏:‎ 1,23,44,555.3453 echo number_format($myNumber); echo "<br>"; // الناتج‏:‎ 1,23,44,555.34 echo number_format($myNumber,2); echo "<br>"; // الناتج‏:‎ 1 23 44 555,3453 echo number_format($myNumber,2,',',' '); echo "<br>"; ?> الوقت والتاريخ يلزم الحصول على الوقت والتاريخ وعرضه بطريقة مناسبة كثيرًا في تطوير الويب، ولهذا توفِّر PHP الأدوات اللازمة لذلك. أهم تلك الأدوات هي الدالة date()‎ التي تقبل سلسلةً نصيةً تُحدِّد تنسيق المخرجات، وتتألف من محارف التنسيق الآتية: d: يعيد رقم اليوم من الشهر، وتتراوح قيمته من 01 إلى 31. استخدام المحرف j للحصول على رقم اليوم دون 0 بادئة. m: يعيد رقم الشهر، وتتراوح قيمته من 01 إلى 12. استخدام المحرف n للحصول على رقم الشهر دون 0 بادئة. w: الحصول على رقم اليوم من الأسبوع، وتتراوح قيمته بين 0 الذي يشير إلى يوم الأحد، و6 ليوم السبت. h: الحصول على الساعة الحالية بنظام 12 ساعة. استخدم g للحصول على الساعة بنظام 24 دون 0 بادئة. استخدام a للحصول على am أو pm، و A للحصول على AM أو PM. H: الحصول على الساعة الحالية لكن بنظام 24 ساعة. استخدم G للحصول على الساعة بنظام 24 دون 0 بادئة. i: الحصول على الدقائق. s: الحصول على الثواني. Y: الحصول على السنة على هيئة أربعة أرقام. ويمكن تمرير وسيطٍ اختياري هو بصمة الوقت (timestamp) لكي تُعيد الدالة date()‎ قيمة التاريخ والوقت لها، لكن إن لم تُحدِّد بصمة الوقت، فستؤخذ القيمة من ناتج الدالة time()‎ التي تُعيد بصمة الوقت مقاسةً بالثواني منذ بداية وقت يونكس (Unix Time) (أي منتصف ليلة رأس السنة عام 1970). <?php // الناتج‎: 12:31:55 echo date('H:i:s'); // الناتج‎: 2015/12/23 echo date('Y/m/d'); ?> ملاحظة: يجدر بالذكر أنَّ الدالة mktime()‎ تنُشِئ بصمة الوقت لتاريخ معيّن كي تستعملها مع الدالة date، شكلها العام هو الآتي: mktime($hour, $minute, $second, $month, $day, $year); حيث أول وسيط هو الساعة، والثاني هو الدقيقة، والثالث هو الثانية، والرابع هو الشهر، والخامس هو اليوم من الشهر، والسادس هو السنة؛ مثالٌ عن استعمالها: <?php // الناتج هو مثلًا‏‎: 1450872238 $current_time = time(); echo $current_time; // ناتج بصمة الوقت هو‎: 1030134920 $past_time = mktime(22, 35, 20, 8, 23, 2002); echo $past_time; // الناتج هو‎: 12-23-2015 13:03 // يمكن أن نحذف الوسيط الثاني، لأن الدالة date ستعتمد الوقت الحالي المُعادة من الدالة time افتراضيًا echo 'current date is: ' . date ('m-d-Y H:i' , $current_time); // الناتج هو‎: 08-23-2002 22:35 // يمكن أن نحذف الوسيط الثاني، لأن الدالة date ستعتمد الوقت الحالي المُعادة من الدالة time افتراضيًا echo 'a date in the past: ' . date ('m-d-Y H:i' , $past_time); ?> تمرين اكتب برنامجًا يأخذ تاريخ ميلاد المستخدم ثم يُظهِر عمره بالسنوات والأشهر والأيام؛ مثلًا: 35 سنة، و 4 أشهر، و23 يومًا. المصادر مقال Strings in PHP part-2 لصاحبه Harish Kumar. صفحة sprintf، و date في دليل PHP وغيرها.
  22. سنبدأ الآن في تعلم التعامل مع السلاسل النصية وما هي العمليات التي تُجرى عليها. ولمّا كان الحديث عن السلاسل النصيّة يحتاج شرحًا طويلًا، فقد قسمناها إلى قسمين، لنأخذ فكرةً عن محتواهما: القسم الأول: إنشاء والوصول إلى السلاسل النصية باستخدام $ و {}، واستخدام الدالة strlen()‎. البحث في السلاسل النصية باستعمال الدوال: strstr()‎ strpos()‎ و strrpos()‎ substr_count()‎ strpbrk()‎ الاستبدال في السلاسل النصية باستخدام الدوال: str_replace()‎ ()substr_replace ()strtr strtr()‎ التعامل مع حالات الحروف الكبيرة (uppercase) والصغيرة (lowercase) باستخدام الدوال: strtolower()‎ strtoupper()‎ ucfirst()‎ lcfirst()‎ ucword()‎ النسخ غير الحساسة لحالة الأحرف لجميع الدوال السابقة. القسم الثاني: تنسيق السلاسل النصية باستخدام printf()‎، بما في ذلك تعيين دقة الأرقام العشرية. إزالة الفراغات (trimming) من أطراف السلاسل النصية باستعمال الدوال: trim()‎ ltrim()‎ rtrim()‎ إضافة حواشي (paddings) للنصوص باستعمال الدوال: str_pad()‎ STR_PAD_RIGHT STR_PAD_LEFT STR_PAD_BOTH التفاف (wrapping) النصوص عبر استعمال الدالة wordwrap()‎. تنسيق الأرقام باستخدام الدالة number_format()‎. الوقت والتاريخ. لماذا علي أن أتعلم عن السلاسل النصية؟ لأنه علينا -عند تطوير الويب- أن نحصل على البيانات من المستخدم؛ التي تكون في غالب الأحيان على شكل سلاسل نصيّة. لذا علينا أن نُرشِّح (filter) تلك البيانات لأغراضٍ أمنية، وذلك عبر التعلم عن كيفية التعامل مع السلاسل النصية. إنشاء السلاسل النصية والوصول إليها كما تعلم مسبقًا، نُعرِّف السلاسل النصية بكتابة النصوص ضمن علامتي اقتباس مفردتين أو مزدوجتين، وبإسنادها إلى متغير: $string = 'string'; أو: $string = "string"; سيتم تفسير أيّة متغيرات ترد ضمن السلاسل النصية بقيمة ذاك المتغير إن كانت السلسلة النصية محاطة بعلامتَي اقتباس مزدوجتين، وإلا فلن تُفسَّر تلك المتغيرات. أي أننا نستطيع أن نضع المتغيرات مباشرةً في السلاسل النصيّة كالآتي: <?php $site = 'academy.hsoub.com'; // الناتج هو: // Please visit academy.hsoub.com echo "Please visit $site"; // مثالٌ أكثر «تعقيدًا»‏ $cat = "cat"; // {} تشير إلى اسم المتغير // الناتج هو: // these are cats echo "these are {$cat}s"; ?> يمكننا "تهريب" (escape) بعض المحارف الخاصة، لكن لاحظ أنَّ المحارف الخاصة لا يمكن تهريبها إذا كانت ضمن علامتي اقتباس مفردتين، إذ تعمل مع علامات الاقتباس المزدوجة فقط. <?php $site = 'academy.hsoub.com'; // \n هو محرف السطر الجديد /* ستحصل على مخرجات كما يلي في المتصفح: string academy.hsoub.com أما لو نظرت إلى مصدر الصفحة، فستجد شيئًا شبيهًا بما يلي: string academy.hsoub.com ذلك ﻷن HTML لا تأخذ الفراغات بعين الاعتبار، لكن ذلك مفيدٌ في PHP */ echo "string\n $site"; ?> ملاحظة: إذا أردت تضمين علامة اقتباس مفردة داخل سلسلة نصية محاطة بعلامتي اقتباس مفردتين، فعليك «تهريبها» عبر وضع شرطة خلفية مائلة (\) قبلها: echo 'chars\' escaping'; معرفة طول سلسلة نصية يمكن الحصول على طول السلاسل النصية باستعمال الدالة strlen()‎، حيث تأخذ وسيطًا وحيدًا هو السلسلة النصية، وتُعيد (returns) طول تلك السلسلة. <?php $site = 'academy.hsoub.com'; // الناتج هو 17 echo strlen($site).'</br>'; // الناتج هو 14 (بما في ذلك الفراغات) echo strlen('it is a string'); ?> ملاحظة: من المثير للاهتمام أنَّك تستطيع الوصول إلى المحارف (characters) في سلسلة نصيّة بكتابة ‎$myname[0]، أو ‎$myname[1] وهلّم جرًا إلى نهاية السلسلة النصية؛ هذه هي طريقة الوصول إلى عناصر المصفوفات، التي سنأخذها في درسٍ لاحق. البحث في السلاسل النصية تأخذ الدوال التي تبحث عن السلاسل النصية وسيطين، أولهما هو السلسلة التي ستبحث فيها، وثانيهما هو النص التي ستبحث عنه في تلك السلسلة. إن لم يُعثر على النص فستعيد تلك الدوال القيمة false؛ يلخِّص هذا الجدول أبرز تلك الدوال: strstr()‎: إن عُثِرَ على النص، فستعيد الدالة strstr()‎ قسمًا من السلسلة النصية يبدأ من مكان العثور على النص إلى نهاية السلسلة. strpos()‎: تستعمل هذه الدالة للعثور على مكان وجود النص المُطابَق انطلاقًا من بداية السلسلة النصية، وستعيد مكانه. strrpos()‎: هذه الدالة شبيهة بالدالة السابقة strpos()‎ إلا أنها تبدأ البحث من النهاية. substr_count()‎: تحصي عدد مرات مطابقة النص الذي نبحث عنه في السلسلة النصية. strpbrk()‎: التحقق من وجود الحرف في السلسلة النصية وستعيد السلسلة النصية التي تلي ذاك الحرف. ملاحظة: كل تلك الدوال السابقة (باستثناء substr_count()‎) ستعمل إلى أن تحدث أول مُطابَقة ثم ينتهي تنفيذها؛ فمثلًا، لو بحثنا عن h في "hsoub hosub" فستعيد الدالة strstr('hsoub hsoub', 'h')‎ أول h تمت مطابقتها ثم سينتهي تنفيذها. انظر إلى المثال الآتي للمزيد من الإيضاح: <?php $string = "This is a @str string for a search"; // ستُطبَع الكلمة search // الجزء من السلسلة النصية التي تبدأ بالقسم sea echo strstr($string, 'sea').'</br>'; // ستُطبَع الكلمة earch // الجزء من السلسلة النصية التي تبدأ بالقسم ear echo strstr($string, 'ear').'</br>'; // سيُطبَع الرقم 8 // الذي هو موضع أول حرف 'a' // تذكر أنَّ العد يبدأ من الصفر وليس الواحد echo strpos($string, 'a').'</br>'; // سيُطبَع الرقم 30 // الذي هو موضع آخر حرف 'a' echo strrpos($string, 'a').'</br>'; // سيُطبَع الرقم 3 // عدد أحرف 'a' في السلسلة النصية echo substr_count($string, 'a').'</br>'; // ستُطبَع الجملة @str string for a search // التي تكون بعد محرف @ (بما فيها محرف @) echo strpbrk($string, '@').'</br>'; ?> الاستبدال في السلاسل النصية str_replace()‎: استبدال جميع أماكن ورود النص الذي نبحث عنه في السلسلة النصية. substr_replace()‎: استبدال القسم المُحدَّد من السلسلة الهدف بسلسلةٍ أخرى. strtr()‎: استبدال محارف معيّنة في السلسلة الهدف بمحارف أخرى. لنلقِ الآن نظرةً على كل دالةٍ على حدة. الدالة str_replace()‎ تأخذ هذه الدالة ثلاثة وسائط: أولها هو السلسلة التي سنبحث عنها، وثانيها هي السلسلة التي سيتم الاستبدال بها، وثالثها هي السلسلة التي سنبحث فيها. وستعيد هذه الدالة نسخةً من السلسلة الأصلية مع استبدال جميع أماكن ورود السلسلة التي يتم البحث عنها. هذا مثالٌ عنها: <?php $myString = "It was the best of times, it was the worst of times,"; // الناتج: "It was the best of bananas, it was the worst of bananas," echo str_replace( "times", "bananas", $myString ); ?> إن أردت أن تعرف عدد مرات استبدال السلسلة التي يتم البحث عنها، فمرِّر وسيطًا رابعًا اختيارًا، وسيُسنَد إليه عدد مرات الاستبدال: <?php $myString = "It was the best of times, it was the worst of times,"; // الناتج: "It was the best of bananas, it was the worst of bananas," echo str_replace( "times", "bananas", $myString, $num ) . "<br/>"; // الناتج: "The text was replaced 2 times." echo "The text was replaced $num times"; ?> الدالة substr_replace()‎ في حين أنَّ الدالة str_replace()‎ تبحث عن سلسلة نصيّة معينة لاستبدالها، لكن الدالة substr_replace()‎ تستبدل جزءًا مُحدَّدًا من السلسلة الهدف؛ عليك تمرير ثلاثة وسائط لاستعمالها: السلسلة الهدف التي ستُجرى عليها عملية الاستبدال، والنص الذي سيتم وضعه بدلًا من السلسلة المُستبدَلة، والفهرس (index، أي المكان) الذي ستبدأ منه عملية الاستبدال. تستبدل الدالة subsrt_replace()‎ جميع المحارف من نقطة البداية إلى نهاية السلسلة النصية، وتعيد نسخةً مُعدَّلةً من السلسلة (أي أنَّ السلسلة الأصلية ستبقى على حالها دون أن يُعدَّل فيها شيء)؛ يوضِّح هذا المثال طريقة عمل الدالة substr_replace()‎: <?php $myString = "It was the best of times, it was the worst of times,"; // الناتج: "It was the bananas" echo substr_replace( $myString, "bananas", 11 ); ?> يمكنك أن تلاحظ أنَّ الشيفرة السابقة استبدلت جميع محتويات السلسلة النصية الأصلية بدءًا من الفهرس index) 11) إلى النهاية بالنص "bananas"؛ إن لم تكن تريد استبدال كل النص من نقطة البداية إلى نهاية السلسلة النصية، فيمكنك تحديد وسيط رابع اختياري يحتوي عدد المحارف التي ستُستبدل: <?php $myString = "It was the best of times, it was the worst of times,"; // الناتج: "It was the best of bananas, it was the worst of times," echo substr_replace( $myString, "bananas", 19, 5 ); ?> الدالة strtr()‎ يمكنك أيضًا استخدام الدالة srttr()‎ لاستبدال سلاسل نصية بسلاسل نصية أخرى، عوضًا عن استبدال المحارف بمحارف فقط. عليك تمرير وسيطين لفعل ذلك: السلسلة التي تريد تغييرها، ومصفوفة (array) بأزواج «المفتاح/القيمة» حيث كل «مفتاح» يُمثِّل قيمة السلسلة النصية التي سيتم البحث عنها، وكل قيمة مرتبطة بذاك المفتاح هي السلسلة النصيّة التي ستستبدل تلك المُطابَقة. سنشرح المصفوفات في درسٍ لاحق. التعامل مع حالات الأحرف ستأخذ الدوال الآتية وسيطًا وحيدًا الذي هو سلسلةٌ نصيّةٌ؛ ما رأيك أن تتدرب عليها وأن تجربها بنفسك. ()strtolower: جعل كل أحرف السلسلة النصية بأحرفٍ ذات الحالة الصغيرة (lowercase) strtoupper()‎: جعل كل أحرف السلسلة النصية بأحرفٍ ذات الحالة الكبيرة (uppercase) ucfirst()‎: جعل أول حرف من السلسلة النصية حرفًا بالحالة الصغيرة. lcfirst()‎: جعل أول حرف من السلسلة النصية حرفًا بالحالة الكبيرة. ucword()‎: جعل أول حرف من كل كلمة في السلسلة النصية حرفًا بالحالة الكبيرة. الدوال غير الحساسة لحالة الأحرف هذه هي نسخٌ من الدوال السابقة التي لا تأخذ حالة الأحرف بعين الاعتبار أثناء عملها: strstr()‎ stristr()‎ strpos()‎ stripos()‎ strrpos()‎ strripos()‎ str_replace()‎ str_ireplace()‎ تمرين قد تحتاج إلى عرض البريد الإلكتروني للأشخاص الذين يضيفون تعليقات في موقعك، لكنك لا تريد أن تُرسَل إليهم رسائل عشوائية… اكتب برنامجًا يبدِّل رمز @ في البريد الإلكتروني إلى [at]، والنقطة في آخر العنوان إلى [dot] أي أنَّ «user.name@domain.com» سيُصبِح «user.name [at] domain [dot] com». (للمساعدة، انظر إلى صفحة دليل strstr في المصادر). المصادر مقال Strings in PHP part-1 لصاحبه Harish Kumar. صفحات Strings ،strstr ،strpos و str_replace، وغيرها.
  23. php 101

    سنتطرّق في هذا الدرس إلى مفهوم الحلقات في PHP، التي تسمح لك بتنفيذ تعليمات برمجية مرةً أو أكثر. فعلى سبيل المثال، لو أردت أن أطبع كلمة "hsoub" عشر مرات فعلي عندها أن أكتب الأمر echo مراتٍ عشر، لكن يمكنني عبر استعمال حلقة أن أكتب الأمر echo مرةً واحدةً لطباعة الجملة عشر مرات. هنالك أربعة أنواع من الحلقات في PHP هي: حلقة while حلقة do-while حلقة for حلقة foreach سنتعلم في هذا الدرس عن أول ثلاث حلقات لأن الرابعة متعلقة بالمصفوفات التي سنتعلمها لاحقًا، لذا سنؤجِّل شرح حلقة foreach إلى درسٍ قادم. حلقة while حلقة while هي من أبسط أشكال الحلقات في PHP، إذ تقوم هذه الحلقة بتنفيذ التعليمات البرمجية مرارًا وتكرارًا إلى أن يتحقق الشرط (أي تصبح قيمته FALSE)، ويتم التحقق من قيمة الشرط قبل كل تكرار، فلو تغيرت قيمته أثناء التنفيذ فسيستمر تنفيذ التعليمات الموجودة في الحلقة إلى نهايتها؛ وقد يتحقق شرط حلقة while من البداية (أي تكون قيمته من البداية FALSE)، وبهذا لن تُنفَّذ التعليمات الموجودة فيها أبدًا. الشكل العام للحلقة while هو: while (expr) { statments } خصائص هذا الشرط مماثلة لخصائص شرط عبارة if-else؛ فلطالما كانت قيمة الشرط true أو قيمةً ليست صفرية، فسيستمر تنفيذ الشيفرة مرارًا وتكرارًا. لنلقِ نظرةً على هذا المثال: <?php // نعطي قيمةً ابتدائية للمتغير $initial_value = 0; // أصغر من 10 هو الشرط الذي سينهي الحلقة while($initial_value < 10) { echo 'hsoub'.'<br>'; // سنزيد قيمة المتغير بمقدار 1 $initial_value++; } ?> تبدأ قيمة المتغير ‎$initial_value من القيمة 0 وسيستمر تنفيذ الحلقة لطالما كانت قيمة المتغير ‎initial_value$ أصغر من 10؛ تزداد قيمة ‎$initial_value بمقدار 1 في كل تكرار؛ وسيطبع المثال السابق الكلمة "hsoub" عشر مرات، ويُستعمَل الوسم <br> لإدراج سطرٍ جديد في مستندات HTML (لطباعة الكلمات في أسطرٍ مختلفة). تذكر أنَّ النقطة "." تجمع بين سلسلتين نصيتين. حلقة do-while هذه الحلقة مشابهة جدًا لحلقة while لكن الاختلاف بينها هو أنَّ هذه الحلقة تتحقق من قيمة الشرط بعد أن تنفِّذ الشيفرة الموجود ضمنها؛ أي أنها تتحقق من الشرط عند تكرار تنفيذ الشيفرة وليس عند تنفيذها لأول مرة. شكلها العام هو: do { statments } while (expr); مثالٌ عليها: <?php // نعطي قيمةً ابتدائية للمتغير $initial_value = 0; // أصغر من 10 هو الشرط الذي سينهي الحلقة do { echo 'hsoub'.'<br>'; // سنزيد قيمة المتغير بمقدار 1 $initial_value++; } while($initial_value < 10); ?> سيطبع هذا المثال الكلمة "hsoub" عشر مرات أيضًا، لكن الاختلاف يكمن فيما لو كانت القيمة الابتدائية للمتغير ‎$initial_value أكبر أو تساوي 10، ففي هذا الحالة لن تُنفَّذ حلقة while بينما ستُنفَّذ حلقة do-while. أي أنها ستنفَّذ مرةً واحدةً على الأقل. لاحظ وجود الفاصلة المنقوطة بعد while في حلقة do-while. حلقة for الشكل العام لحلقة for هو: for (initialize; condition; operation) { statments } لنأخذ مثالًا قبل أن نناقش آلية عمل هذه الحلقة: <?php // تهيئة المتغير داخل الحلقة for($initial = 0; $initial <10; $initial++) { echo 'hsoub'.'<br>'; } // تهيئة المتغير خارج الحلقة $initial_value = 0; for (; $initial_value < 10; $initial_value++) { echo 'hsoub'.'<br>'; } ?> شاهدنا -في أول نوعين من الحلقات- كيف أننا نهيّئ متغيرًا، ثم علينا التحقق من الشرط في الحلقة كي تُنفَّذ، ثم في النهاية علينا تعديل قيمة المتغير (زيادةً أو نقصانًا). لكننا نجري الخطوات الثلاث السابقة في مكانٍ وحيد في حلقة for. تأخذ الحلقة for ثلاثة وسائط (arguments): القيمة الابتدائية (initialize): وهي مماثلة لأول نوعين من الحلقات. يمكننا تهيئة المتغيرات في حلقة for بطريقتين، الأولى داخل الحلقة (بين الأقواس) والأخرى قبل الحلقة. لاحظ طريقة الكتابة في المثال السابق؛ حيث يُفصَل بين كل وسيط والآخر بفاصلة منقوطة؛ وإذا كنت تُهيّئ القيمة خارج الحلقة، فلا تنسَ أن تضع الفاصلة المنقوطة حتى ولو كانت القيمة فارغة. الشرط (condition): وهو يقارن بين قيمة المتغير الذي تمت تهيئته والقيمة المعطية. العملية (operation): وهي التي ستعدِّل في قيمة المتغير بعد نهاية تنفيذ كل تكرار للحلقة. أمثلة إضافية لا يكفي الشكل العام للأوامر والتعليمات لتعلم لغة البرمجة وفهمها فهمًا تامًا؛ لنحاول الآن استيعاب هذه الأمثلة: <?php // طباعة الأرقام من 10 إلى 0 for ($number=10; $number >= 0; $number--) { echo $number.'<br>'; } ?> <?php // زيادة الرقم بمقدار 2 في كل دورة for ($number=0; $number < 10; $number+=2) { echo $number.'<br>'; } ?> نجد -في المثال أعلاه- المعامل "‎+=‎" الذي يُضيف القيمة على الجانب الأيمن إلى قيمة المتغير على الجانب الأيسر؛ يمكنك أيضًا استعمال هذه المعاملات: "‎*=‎": الضرب، مثال ‎$number *= 2‎ "‎-=‎": الطرح "‎/=‎": القسمة "‎%=‎": باقي القسمة "‎^=‎": القوة (أو الأس) سنكتب الآن برنامجًا لطباعة مضاعفات الرقم 5 بين العددين 1 و 100؛ تذكَّر أن المعامل % يُعيد باقي القسمة. <?php for ($number=1; $number < 100; $number++) { if ($number % 5 == 0) { echo $number.'<br>'; } } ?> الشكل البديل لبنى التحكم تدعم PHP شكلًا بديلًا لأقواس بنى التحكم التي هي if، و while، و for، و foreach، و switch؛ وطريقة استعمال الشكل البديل هي وضع نقطتين رأسيتين (:) بدلًا من قوس البداية، واستبدال قوس النهاية بالكلمات "endif;‎"، أو "endwhile;‎"، أو "‎endfor;‎"، أو "endforeach;‎" (سنناقش تلك الحلقة في درسٍ لاحق)، أو "endswitch;‎" على التوالي وبالترتيب. <?php if ($a == 5): ?> A is equal to 5 <?php endif; ?> قسم HTML في المثال السابق (A is equal to 5) موجودٌ ضمن جملة if شرطية مكتوبة بالشكل البديل، لاحظ أن تمييز بداية ونهاية بنى التحكم أسهل عند دمج HTML مع PHP. ستظهر جملة "A is equal to 5" فقط إن كانت قيمة المتغير ‎$a مساوية للرقم 5. يمكن تطبيق الشكل البديل على عبارات else و elseif أيضًا. هذا مثالٌ عنها بالشكل البديل: <?php if ($a == 5): echo "a equals 5"; echo "..."; elseif ($a == 6): echo "a equals 6"; echo "!!!"; else: echo "a is neither 5 nor 6"; endif; ?> تمرين اكتب برنامجًا فيه حلقتين متداخلتين لطباعة جدول الضرب للأعداد من 1 إلى 9؛ حيث يكون ناتج خرجه هو: 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81 حاول أن تشغل السكربت السابق من سطر الأوامر (استعمل ‎\t لإدراج مسافة جدولة [tab]، و ‎\n لإدراج سطر جديد). المصادر مقال Loops in PHP لصاحبه Harish Kumar. صفحات while، و do-while، و for، و Alternative syntax في دليل PHP وغيرها.
  24. php 101

    يُبنى أي سكربت PHP من سلسلةٍ من التعليمات البرمجية، التي تكون عمليات إسناد، أو استدعاء لدوال، أو حلقات، أو جملًا شرطية. تنتهي التعلميات عادةً بفاصلة منقوطة، ويمكن تجميع التعليمات ضمن مجموعة عبر وضعها ضمن أقواس معقوفة (أي {}). سنفصِّل في هذا الدرس الجمل الشرطية (التي هي عبارات if-else، وعبارة switch). حيث تُستعمَل هذه العبارات لاتخاذ القرارات وتنفيذ إجراءات اعتمادًا على تحقيق شرطٍ معيّن وهي من أهم التعابير البرمجية التي علينا تعلمها؛ لننظر إلى مثالٍ أولًا. ليكن لدينا متغيرٌ اسمه ‎$a، ونريد أن نُظهِر الكلمة "hsoub" إن كانت قيمة المتغير ‎$a مساويةً للسلسلة النصية "hsoub"؛ ستبدو الشيفرة كالآتي: <?php $a = 'hsoub'; //تهيئة المتغير // التحقق من قيمة المتغير if ($a == 'hsoub') { //إذا كانت قيمة المتغير مساويةً للكلمة 'hsoub' فستُطبَع الكلمة hsoub echo 'hsoub'; } ?> يمكنك ملاحظة أننا استعملنا عبارة if للتحقق إن كانت قيمة المتغير ‎$a مساويةً للسلسلة النصية "hsoub" أم لا؛ ركِّز على البنية العامة: if( expr ) { statements } ستُنفَّذ العبارات داخل حلقة if إن كانت قيمة الشرط هي true أو قيمة غير صفرية (non-zero) أو قيمة غير فارغة (non-empty)؛ هذا شرحٌ للكلمات الثلاث السابقة: القيمة true: معنى هذا القيمة واضحٌ وجلي؛ ففي المثال السابق استعملنا معامل المقارنة "==" لنتحقق إن كانت قيمة المتغير ‎$a مساويةً للسلسلة النصية "hsoub" أم لا. إن كانت مساويةً فسيعيد المعاملُ القيمةَ true وخلا ذلك سيعيد القيمة false. قيمة غير صفرية: يمكننا تجربتها بوضع 0 أو أعداد أخرى ليست مساوية للصفر في مكان الشرط... في الحقيقة، تعتبر الصفر مساويةً للقيمة false ويعتبر أي شيء عداها قيمته true. قيمة غير فارغة: جميع المتغيرات الفارغة أو غير الموجودة (null) تعتبر false، وبقية القيم أو المتغيرات تعتبر true. لاحظ أنَّ القيم الفارغة لا تعني أن تترك مكان الشرطِ فارغًا في عبارة if، وإنما تعني السلاسل النصية أو المتغيرات الفارغة أو غير الموجودة. حاول تجربة الأنواع الثلاثة آنفة الذكر لإيضاح ما سبق تمامًا. عبارة else تستعمل هذه العبارة عندما نحتاج إلى اختيار أحد احتمالين؛ فنريد مثلًا أن نُصنِّف طلاب الصف بناءً على درجاتهم، إذ يعتبر الطلاب الذين يحصلون على درجةٍ أقل من 33 راسبين، وسيعتبرون عدا ذلك ناجحين. سيبدو السكربت كما يلي: <?php $marks = 23; // علامة الطالب // عدِّل قيمة المتغير لتحصل على نتائج مختلفة if ($marks < 33) { echo 'you have failed'; } else { echo 'you have passed!'; } // الشيفرة السابقة تكافئ الشيفرة الآتية // لاحظ كيف عطلناها بوضعها في تعليق /* if ($marks < 33) { echo 'you have failed'; } if ($marks >= 33) { echo 'you have passed!'; } */ ?> من الواضح أنَّه سينفَّذ إما ما هو موجودٌ داخل عبارة if، أو ما هو موجودٌ داخل عبارة else؛ وذلك بعد التحقق من قيمة المتغير ‎$marks، إذ ينفَّذ ما هو موجودٌ في else إن لم يتحقق شرط if. التشعب في العبارات الشرطية يمكنك إنشاء عبارة شرطية داخل عبارة شرطية أخرى، فمثلًا لو أردنا أن نتحقق إن أخذ الطالب الدرجة ‎A+‎ أم لا، فسنعدِّل السكربت ليبدو كما يلي: <?php $marks = 23; // علامة الطالب // عدِّل قيمة المتغير لتحصل على نتائج مختلفة if ($marks < 33) { echo 'you have failed'; } else { // نكتب جملة شرطية داخل عبارة else if ($marks > 90) { echo 'you have passed and got A+ grade'; } else{ echo 'you have passed but not got A+ grade'; } } ?> عبارات elseif إن كان لدينا أكثر من خيارين فعلينا وقتها استعمال عبارة elseif، وهي شبيهةٌ بالعبارات المتشعبة؛ فيمكننا مثلًا إعادة كتابة السكربت السابق ليبدو كما يلي: <?php $marks = 23; // علامة الطالب // عدِّل قيمة المتغير لتحصل على نتائج مختلفة if ($marks < 33) { echo 'you have failed'; } elseif ($marks > 90) { echo 'you have passed and got A+ grade'; } else { echo 'you have passed but not got A+ grade'; } ?> إن لم يتحقق الشرط الأول (الدرجة >= 33)، فستتحقق العبارة elseif من الشرط المتعلق بها (الدرجة > 90) فإن لم يتحقق هذا الشرط أيضًا فستنفَّذ عبارة else. يمكنك كتابة عبارات elseif لأي عدد من المرات، فمثلًا، لو كان لديك أربعة خيارات (بدلًا من ثلاثة) فعليك وقتها استعمال عبارة elseif مرتين. تمرين: حاول أن تُعدِّل السكربت السابق لكي يعطي التقديرات الآتية للطلاب: عبارة switch إن جرَّبت إعادة كتابة المثال السابق لتضمين جميع التقديرات الممكنة للدرجات، فستجد أنَّ عليك كتابة الشروط مرارًا وتكرارًا؛ وما سبق مجرد مثالٍ بسيط، فما بالك بمثالٍ ضخمٍ بلائحةٍ ضخمة؟ لنتحدث الآن عن طريقةٍ جديدةٍ للجمل الشرطية تسمى "عبارة switch"؛ التي هي شبيهةٌ بسلسلةٍ من جمل if الشرطية. لنلقِ نظرةً على هذه الشيفرة أولًا: <?php $name = 'hsoub'; switch($name) { case 'variable': echo "it is a variable"; break; case 'hsoub': echo "best academy ever!"; break; default: echo 'this is necessary default case'; break; // هذه العبارة ليست ضرورية } ?> لنحاول فهم ما جرى في السكربت السابق: نبدأ السكربت بتعريف متغير اسمه "name". ثم نمرِّر ذاك المتغير إلى عبارة switch. ستأخذ العبارة swtich المتغير وتحاول مطابقة قيمته مع الحالات (cases) المُعرَّفة داخلها، فإن طابقت تلك القيمة أيّة حالةٍ فسينفَّذ ما يليها إلى أن نصل إلى عبارة break. سينتهي تنفيذ الحلقة (أي "سنخرج" منها) بعد تنفيذ أوّل عبارة break. يجب أن يكون في كل عبارة switch حالة افتراضية (default case) التي تنفَّذ إن لم تُطابِق المدخلات أيّة حالةٍ من الحالات. ليس من الضروري وجود عبارة break بعد الحالة الافتراضية، يمكنك ألّا تضيفها. أي بكلامٍ آخر، عبارة switch هي مجموعة من عبارات if-else. وتبدأ تنفيذها عند مطابقة حالة من الحالات المُعرَّفة (أو الحالة الافتراضية)، وتنتهي عند عبارة break أو قوس الإغلاق "‎}‎". ميزة استعمال switch هي أنها ستقلل من طول الشيفرة المكتوب. لنعد الآن إلى مثالنا السابق عن تقديرات الطلاب ونحاول حلّ المشكلة عبر عبارة switch: <?php $marks = 0; // علامة الطالب // عدِّل قيمة المتغير لتحصل على نتائج مختلفة // ندور العلامات إلى عدد بخانة واحدة $m = ($marks - 1)/10; // الدالة intval تعيد الجزء الصحيح من العدد // مثلًا 3.2 تصبح 3 و 3.8 تصبح 3 switch (intval($m)) { case 0: case 1: case 2: echo "F"; break; case 3: echo "D"; break; case 4: echo "C"; break; case 5: echo "C+"; break; case 6: echo "B"; break; case 7: echo "B+"; break; case 8: echo "A"; break; case 9: echo "A+"; break; default: // الحالة الافتراضية إن لم تُطابَق أيّة حالة echo "wrong input for marks"; break; } ?> من الواضح أننا لم نكتب شيفراتٍ كثيرة كما في السابق؛ لنشرح ما حدث في السكربت السابق: بدأنا السكربت بإنقاص الدرجات بمقدار 1 لكي يكون أول رقم (العشرات) من كل تقدير متساويًا (ما عدا التقدير F)، أي مثلًا 50 ستصبح 49 و100 ستصبح 99 ثم قسمنا الدرجات على 10 لجعلها تتراوح بين ‎-0.1 و9.9؛ أي أنَّ 10 ستصبح 0.1 و67 ستصبح 6.7. الدالة intval هي دالة موجودة في لغة PHP مهمتها إعادة الجزء الصحيح من العدد؛ أي أنها -مثلًا- ستعيد الرقم 3 إن كان العدد المُمرَّر إليها هو 3.4 أو 3.5 أو 3.8. باختصار، سنمرِّر الجزء الصحيح من العدد إلى العبارة switch. ثم سنحاول مطابقة ذاك الرقم مع الحالات داخل عبارة switch؛ وكما ذكرنا سابقًا، سيستمر تنفيذ الشيفرات التي تلي سطر مطابقة الحالي إلى أن نصادف عبارة break، فلذا ستُشير الحالات 0 و 1 و 2 إلى نفس الأسطر البرمجية (تلك التي ستطبع F) لعدم وجود عبارة break بينها. المعامل الثلاثي "‎?:‎" يُمثِّل هذا المعامل صيغةً مختصرةً لجملة if-else الشرطية، شكل العام كالآتي: (expr1) ? (expr2) : (expr3) سيتم التحقق أولًا من القيمة المنطقية للتعبير expr1، فإن كانت TRUE فسيُنفَّذ expr2، أما لو كانت FALSE فسينفَّذ expr3. هذا مثالٌ عنه: <?php $marks = 23; echo $marks < 33? 'you have failed' : 'you have passed!'; // السطر السابق يكافئ ما يلي if ($marks < 33) { echo 'you have failed'; } else { echo 'you have passed!'; } ?> تمرين حاول أن تعدِّل الأمثلة السابقة. اكتب برنامجًا فيه متغيرين هما x و y، يمثلان الإحداثيات الديكارتية لنقطة، واستعمل الجمل الشرطية لمعرفة إن كانت تلك النقطة في الربع الأول أو الثاني أو الثالث أو الرابع. [مصدر الصورة: ويكيبيديا] فكِّر بمشاكل أخرى تتطلب "اتخاذًا للقرارات" وجربها باستخدام عبارة if أو switch، واسأل في التعليقات إن واجهتك أيّة صعوبات. المصادر المقال Conditional statements in php لصاحبه Harish Kumar. صفحات if و else و else-if في دليل PHP وغيرها.
  25. تَعِد PHP 7، التي صدرت في 3 ديسمبر 2015، بتحسينات كبيرة في سرعتها على النُسخ السابقة من اللغة، مع مميزات جديدة مثل تلميح النوع العددي (scalar type hinting). سنشرح كيفية ترقية خادوم Apache أو Nginx يستخدم PHP 5.x (أي إصدار) إلى PHP 7. تحذير: كما هو الحال مع معظم النسخ الرئيسية لإصدارات اللغة، من الأفضل الانتظار لبعض الوقت قبل الانتقال إلى PHP 7 في بيئة الإنتاج. في غضون ذلك، يكون الوقت مناسب لاختبار توافقية تطبيقاتك مع الإصدار الجديد، إجراء مقاييس الأداء والتّعرف على الميزات الجديدة للغة. إذا كُنت تُشغل أي خدمات أو تطبيقات بمستخدمين نُشطاء، فالآمن اختبار PHP 7 في بيئة إدراج staging environment قبل تثبيتها في بيئة الإنتاج. ملحوظة: بيئة الإدراج (staging environment) هي بيئة تطوير تقع بين بيئة الاختبار وبيئة الإنتاج، تُستخدم في تجميع، اختبار واستعراض الإصدارات الجديدة من البرمجيات قبل نقلها إلى بيئة الإنتاج. المتطلبات الأساسية يُفتَرض أنك تستخدم PHP 5.x على أوبنتو 14.04، باستخدام إما mod_php بالتزامن مع Apache، أو PHP-FPM بالتزامن مع Nginx. ويُفتَرض أن لديك مُستخدم عادي غير المستخدم الجذر بصلاحيات sudo للمهام الإدارية. إضافة PPA لحزم PHP 7.0 أرشيف الحزم الشخصي، أو PPA، هو مُستودع Apt مُستضاف على Launchpad. وهذه الأرشيفات الشخصية تسمح لمطوري الطرف الثالث ببناء وتوزيع الحزم لأوبنتو خارج قنوات تطوير الحزم الرسمية. وهي مصادر مفيدة غالبًا من البرمجيات التجريبية، البنّى المُعدلة والمنقولات الخلفية backports لإصدارات النظام القديمة. ملحوظة: الحزم المنقولة خلفًا (package backports) هي حزم لبرمجيات حديثة أعيدت ترجمتها لتوزيعة قديمة (نُقلت إلى الخلف)، وعادة ما يكون النقل إلى التوزيعة المستقرة. يقوم Ondřej Surý على صيانة حزم PHP لدبيان، ويوفر أرشيف شخصي للنسخة PHP 7.0 على أوبنتو. قبل القيام بأي شيء، سجل دخولك إلى النظام، وأضف أرشيف Ondřej الشخصي إلى قائمة مصادر Apt بالنظام: $ sudo add-apt-repository ppa:ondrej/php-7.0 ستلاحظ وصف الأرشيف الشخصي، متبوعًا بمحث للاستمرار. اضغط Enter للمواصلة. ملحوظة: إذا كانت محليات نظامك مضبوطة لأي شيء غير UTF-8، فقد تفشل عملية إضافة الأرشيف الشخصي لوجود مشكلة برمجية في التعامل مع الحروف في اسم المؤلف. وكالتفاف حول المشكلة يمكنك تثبيت الحزمة language-pack-en-base لتتأكد من توليد المحليات المطلوبة، وتتجاوز إعدادات محليات النظام عند إضافة الأرشيف الشخصي: $ sudo apt-get install -y language-pack-en-base $ sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php-7.0 بمجرد انتهاء تثبيت الأرشيف الشخصي، حدّث ذاكرة الحزم المُخبأة لكي يتم تضمين محتويات الأرشيف: $ sudo apt-get update الآن أصبح لدينا وصول لحزم PHP 7.0، ويمكننا استبدال نسخة PHP الحالية. ترقية mod_php مع Apache هذا القسم يوضح عملية ترقية نظام يستخدم Apache كخادوم و mod_php لتنفيذ شفرة PHP. إذا كُنت تستخدم Nginx و PHP-FPM انتقل للقسم التالي. تثبت الحزم الجديدة سوف يُرقي كل حزم PHP الهامة، باستثناء php5-mysql، التي سيتم حذفها. $ sudo apt-get install php7.0 ملحوظة: إذا قُمت بتعديلات هامة على أي ملف من ملفات الضبط في/etc/php5/، فهذه الملفات ستظل في مكانها، ويمكن الرجوع إليها. ملفات ضبط PHP 7.0 تجدها الآن في etc/php/7.0/. إذا كُنت تستخدم MySQL، تأكد من إعادة تثبيت جسر PHP MySQL المُحدّثة: $ sudo apt-get install php7.0-mysql ترقية PHP-FPM مع Nginx هذا القسم يوضح عملية ترقية نظام يستخدم Nginx كخادوم و PHP-FPM لتنفيذ شفرة PHP. تثبيت حزم PHP-FPM الجديدة واعتمادياتها: $ sudo apt-get install php7.0-fpm سيطلب منك الاستمرار، اضغط Enter لإكمال التثبيت. إذا كُنت تستخدم MySQL، تأكد من إعادة تثبيت جسر PHP MySQL المُحدّثة: $ sudo apt-get install php7.0-mysql ملحوظة: إذا قُمت بتعديلات هامة على أي ملف من ملفات الضبط في/etc/php5/، فهذه الملفات ستظل في مكانها، ويمكن الرجوع إليها. ملفات ضبط PHP 7.0 تجدها الآن في etc/php/7.0/. ترقية مواقع Nginx لتستخدم مسار المقبس الجديد يتواصل Nginx مع PHP-FPM باستخدام مقبس نطاق يونكس. ترسم المقابس خريطة لمسار على نظام الملفات، تستخدم PHP 7 مسار افتراضيًا جديدًا : PHP 5: /var/run/php5-fpm.sock PHP 7: /var/run.php7.0-fpm.sock افتح ملف ضبط الموقع الافتراضي بالمحرر nano (أو أي مُحرر من اختيارك): sudo nano /etc/nginx/sites-enabled/default قد يختلف ضبطك قليلا. ابحث عن كتلة تبدأ بـ }$location ~ \.php وسطر يبدو مثل ;fastcgi_pass unix:/var/run/php5-fpm.sock غيّر هذا ليستخدم unix:/var/run/php/php7.0-fpm.sock. مثال لملف etc/nginx/sites-enabled/default/ server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /var/www/html; index index.php index.html index.htm; server_name server_domain_name_or_IP; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } اخرج واحفظ الملف. يمكنك القيام بهذا في nano بالضغط على Ctrl-x للخروج، y للتأكيد و Enter للتأكيد على اسم الملف الذي سيتم الكتابة فوقه. ينبغي تكرار هذه الخطوة لأي مواقع مُعرّفة في المُجلّد etc/nginx/sites-enabled/ والتي تحتاج أن تدعم PHP. الآن يمكننا إعادة تشغيل nginx: $ sudo service nginx restart اختبار PHP بعد ضبط الخادوم وتثبيت الحزم الجديدة، يمكننا التحقق من أن PHP تعمل. ابدأ بالتحقق من نسخة PHP المُثبتة بالأمر: $ php -v المخرجات PHP 7.0.0-5+deb.sury.org~trusty+1 (cli) ( NTS ) Copyright (c) 1997-2015 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies يمكننا كذلك إنشاء ملف اختبار في مُجلد جذر وثائق الخادوم (document root). مسار هذا المُجلد يعتمد على خادومك وضبطك، قد يكون واحدًا من: var/www/html/ /var/www/ usr/share/nginx/html/ افتح ملفًا جديدًا باستخدام nano يسمى info.php في جذر الوثائق. يكون على Apache، افتراضيًا بالمسار الأول: $ sudo nano /var/www/html/info.php على Nginx، قد تستخدم: $ sudo nano /usr/share/nginx/html/info.php وألصق الشيفرة التالية بالملف: <?php phpinfo(); ?> أغلق المُحرر، واحفظ info.php. الآن، حمل العنوان التالي في متصفحك: http://server_domain_name_or_IP/info.php استبدل server_domain_name_or_IP باسم نطاق أو عنوان ip الخادوم. ينبغي أن ترى رقم نُسخة PHP ومعلومات ضبط PHP 7. بمجرد أن تُراجع هذه المعلومات، فمن الأفضل (لزيادة أمان خادومك) حذف الملف info.php: $ sudo rm /var/www/html/info.php خاتمة الآن لديك PHP 7، مُثبت ويعمل. قد ترغب في إلقاء نظرة على دليل الهجرة الرسمي إلى PHP 7. ترجمة -وبتصرّف- للمقال How To Upgrade to PHP 7 on Ubuntu 14.04 لصاحبه Brennen Bearnes.