اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'متغيرات'.

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

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

نوع المحتوى


التصنيفات

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

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

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

التصنيفات

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

التصنيفات

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

التصنيفات

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

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

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

التصنيفات

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

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

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

  1. بعد أن تعرّفنا في الدّرس السّابق على طريقة تنصيب بايثون وكيفيّة العمل معها، سنكمل في هذا الدّرس مشوار تعلّم هذه اللغة بتعلّم كيفيّة التّعامل مع البيانات مثل المُتغيّرات وأنواعها كالأرقام وإسناد القيم. ولكن قبل ذلك عليك أن تتعرّف على طريقة دعم اللغة العربيّة، ويجب عليك أن تفهم بعض المُصطلحات المتداولة في مجال البرمجة (والتّي اعتَمدتُ عليها في هذا الدّرس). تذكير: نقوم بتنفيذ الأسطر البرمجيّة مُباشرة من مُفسّر بايثون، لمزيد من المعلومات عن المُفسّر راجع الدّرس السّابق. وللتوسع في لغة بايثون وتعلمها أكاديميًا، ننصحك بالانضمام إلى دورة تطوير تطبيقات باستخدام لغة بايثون التي تقدمها أكاديمية حسوب. دعم اللغة العربية في بايثون قد تواجه خطأ إذا حاولت تنفيذ أمر طباعة جملة "مرحبا بالعالم" مُستخدما حروفا عربية، لذلك يجب عليك أن تكتب السّطر التّالي، قبل كتابة أي أمر يحتوي على كلمات عربية: # -*- coding: utf-8 -*- المصطلحات مخرج Output: تعني الجواب أو النّتيجة الذي يُقدّمها مُفسّر بايثون، فمثلا إذا طلبت من مُفسّر بايثون طباعة كلمة Hello، فستستخدم السّطر التّالي: >>> print "Hello" Hello هنا نُسمّي Hello المُخرج الذي يُرجعه البرنامج (أي نتيجة الأمر). مُتغيّر: وهو الاسم الذي نُطلقه على حرف أو “كلمة” تحمل قيمة مُعيّنة، مثلا: >>> name = "abdelhadi" هنا قُمنا بإنشاء مُتغيّر name وأسندنا له القيمة abdelhadi. وإذا أردنا إظهار القيمة abdelhadi فيكفي أن نكتب اسم المُتغيّر في مُفسّر بايثون: >>> print name كما يُمكن أن نضيف تحّية على الشّكل التّالي: >>> print "Hello " + name تُفسّر الشيفرة أعلاه وتكون مُخرجاتها: Hello Abdelhadi يُمكن أن يحمل المُتغيّر عدّة أنواع من القيم، كالأرقام والنّصوص والأحرف… تعيين القيم يُعتبر تعيين قيمة لاسم معيّن من أهمّ أساسيّات البرمجة، وهذا الاسم معروف في البرمجة بالمُتغيّر، وإليك مثالا على ذلك: >>> x = 4 >>> x * x 16 قمنا في المثال أعلاه بوضع القيمة 4 للمتغيّر x، بعبارة أخرى المُتغيّر x يحمل القيمة 4. بحيث يُمكننا استعمال x عوضا عن 4 في باقي الأسطر في برنامجنا. وبعدها قمنا بالعمليّة الحسابيّة x * x أي 4 * 4 وحصلنا على 16 كنتيجة. إذا حاولت أن تستخدم مُتغيّرًا لم يُعرّف من قبل في برنامجك، فستحصل على خطأ كالتّالي: >>> foo Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'foo' is not defined >>> foo = 4 >>> foo 4 حاولنا أعلاه أن نقوم باستخدام المُتغيّر foo الذي لم نعرّفه أساساً، فحصلنا على رسالة من مُفسّر بايثون مفادها بأنّ المُتغيّر foo ليس موجودا. وبعد تعريفه وتعيين القيمة "4" له أصبح بإمكاننا استدعاؤه بدون أي مشكلة. إذا وضعت قيمة مُغايرة لمتغيّر يحمل مُسبقاً قيمة ما، فالقيمة القديمة تُستَبدَل بالقيمة الجديدة، بحيث يحمل المتغيّر القيمة الجديدة. >>> x = 4 >>> x 4 >>> x = 'hello' >>> x 'hello' في المثال أعلاه، قمنا بتحديد القيمة "4" للمتغيّر x ثمّ بعد ذلك قمنا بتحديد "hello" لنفس المُتغيّر فأصبح x يحمل القيمة hello في نهاية المطاف. ويُمكنك تعيين أكثر من قيمة لأكثر من مُتغيّر في آن واحد. >>> a, b = 1, 2 >>> a 1 >>> b 2 >>> a + b 3 ومُبادلة قيمتي مُتغيّرين (بحيث يحمل المُتغيّر قيمة الآخر) سهل جدّا في لغة بايثون: >>> a, b = 1, 2 >>> a, b = b, a >>> a 2 >>> b 1 عند تعيينِ قيمة في بايثون، تكون الأهميّة للجانب الأيمن قبل الأيسر، بحيث يقوم بايثون بالتّعرّف على القيّم في الجانب الأيمن ثمّ يقوم بتعيينها للمتغيّرات في الجانب الأيسر لعلامة = . إذ ما يقع على يسار علامة = هو المُتغير وما يقع على يمينها هو القيمة. التعليقات تُستعمل التّعليقات في البرمجة لشرح وظيفة سطر معين أو لإعطاء فكرة عن برنامجك لمن يقرأ شيفرته، وتكون التّعليقات مسبوقة بعلامة # إما في سطر مستقل أو في نفس سطر الشّيفرة، وتتميّز بأنّها لا تؤثّر على عمل البرنامج إذ يتجاهلها المُفسّر ولا تُنفّذ، وهي عموما اختيارية، لذا فأنت لست مُجبرا على كتابتها، وإليك مثالاً على التّعليقات: >>> # السّطر التّالي عبارة عن تعيين قيمة لمتغيّر >>> x = 'hello' # هذا السّطر عبارة عن تعيين قيمة لمتغيّر الأرقام لقد تعرّفنا من قبل حول كيفيّة التّعامل مع الأرقام بشكل بسيط. >>> 42 42 >>> 4 + 2 6 تدعم بايثون الأعداد العشريّة كذلك. >>> 4.2 4.2 >>> 4.2 + 2.3 6.5 وتدعم العمليّات المُختلفة مثل الإضافة والفرق وغيرهما من العمليّات الحسابيّة: + إضافة - الفرق * الضّرب / القسمة ** الأس (القوة) % باقي القسمة لنجرّب هذه العمليّات على الأعداد الصّحيحة: # عمليّة إضافة >>> 7 + 2 9 # عمليّة فرق >>> 7 - 2 5 # عمليّة ضرب >>> 7 * 2 14 # عمليّة قسمة >>> 7 / 2 3 # الأس >>> 7 ** 2 49 # باقي القسمة >>> 7 % 2 1 إذا تمعّنت في النّظر ستجد أنّ ناتج قسمة 7 على 2 يُساوي 3 وليس 3.5 وهذا لأنّ الرّمز / يُرجع الأرقام الصحيحة فقط عندما يعمل معها، لننظر مالذي سيحدث إذا جرّبنا نفس الأمر لكن بأعداد عشريّة هذه المرّة: >>> 7.0 / 2.0 3.5 >>> 7.0 / 2 3.5 >>> 7 / 2.0 3.5 يُمكن القيّام بالعمليّات الحسابيّة بالاعتماد على أكثر من عامل: >>> 7 + 2 + 5 - 3 11 >>> 2 * 3 + 4 10 هذا مهمّ جدّا وذلك لفهم كيفيّة تعامل لغة بايثون مع العمليّات الحسابيّة، حيث هناك أولويّات للعمليّات وذلك كالقائمة التّالية، من الأقل أولويّة إلى الأه: + - * / % ** ولفهم ذلك أكثر، إليك هذا المثال: عند تنفيذ العمليّة 2 + 3 * 4 في بايثون فالعمليّة الأولى التّي تُنفّذ هي 3 * 4 ، لأن العامل * أكثر أولويّة من عامل +، وبعد ذلك تضاف القيمة إلى 2. >>> 2 + 3 * 4 14 يُمكننا أن نعتمد على الأقواس () لتحديد أولويّات العمليّات، انظر المثال التّالي: >>> (2 + 3) * 4 20 في المثال أعلاه، قمنا بوضع العمليّة 2+3 بين قوسين لإخبار مُفسّر بايثون بأنّ لهذه العملية الأولويّة ويجب حسابها أوّلا، فإن لم نقم بوضع القوسين لقام المُفسّر بحساب العمليّة 4*3 ثم إضافة العدد 2. جميع العمليّات باستثناء ** يبدأ تطبيقها من اليسار ثمّ اليمين. 1 + 2 + 3 * 4 + 5 ↓ 3 + 3 * 4 + 5 ↓ 3 + 12 + 5 ↓ 15 + 5 ↓ 20 تمارين تمرين 1 ما هي مُخرجات (القيّم التّي سيطبعها) البرنامج التّالي: x = 4 y = x + 1 x = 2 print x, y تمرين 2 ما هي مُخرجات (نتيجة) البرنامج التّالي: x, y = 2, 6 x, y = y, x + 2 print x, y تمرين 3 ما هي مُخرجات البرنامج التّالي: a, b = 2, 3 c, b = a, c + 1 print a, b, c ترجمة -وبتصرف- للكتاب Python Practice Book لصاحبه Anand Chitipothu.
  2. إذا أردت أن تصبح مطوّر ووردبريس فهذا يتطلب أيضًا تعلم لغة البرمجة الشهيرة 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
  3. رأينا في الدرس السابق كيف كتبنا سكربتًا يولِّد صفحة HTML، لكن هذا ليس كافيًا لنا، فلنقم ببعض التعديلات. #!/bin/bash # sysinfo_page - A script to produce an HTML file cat <<- _EOF_ <html> <head> <title> My System Information </title> </head> <body> <h1>My System Information</h1> </body> </html> _EOF_ هل لاحظت كيف أنَّ العبارة "My System Information" مكررة مرتين في السكربت السابق؟ لنُحسِّنها هكذا: #!/bin/bash # sysinfo_page - A script to produce an HTML file title="My System Information" cat <<- _EOF_ <html> <head> <title> $title </title> </head> <body> <h1>$title</h1> </body> </html> _EOF_ أضفنا سطرًا إلى بداية السكربت ووضعنا ‎$title بدلًا من العبارة "My System Information". المتغيرات ما فعلناه في الأعلى سيمهد لنا الطريق لشرح فكرة أساسية جدًا موجودة في جميع لغات البرمجة تقريبًا: المتغيرات (variables). المتغيرات هي أماكن في الذاكرة يمكن أن تُستعمَل لتخزين المعلومات، ويُشار إليها باسمٍ مُميِّزٍ لها. أنشأنا في السكربت السابق متغيرًا اسمه title ووضعنا العبارة "My System Information" في الذاكرة، ثم استخدمنا ‎$title لإخبار الصَدَفة أننا نريد إجراء "توسعة المعاملات" (parameter expansion) ونضع محتوى المتغير بدلًا من اسمه. عندما ترى الصَدَفة كلمةً تبدأ برمز $ فستحاول معرفة إذا كانت تُشير تلك الكلمة إلى متغير، ثم ستضع القيمة المُخزَّنة فيه -أي المتغير- مكان ورود تلك الكلمة. كيفية إنشاء متغير كل ما عليك فعله لإنشاء متغير هو وضع اسم المتغير في سطرٍ مستقل متبوعًا برمز المساواة (=) دون أيّة فراغات، ثم كتابة المعلومات التي تريد إسنادها بعد رمز المساواة. أسماء المتغيرات حسنًا، أنت من يُسمي المتغيرات، لكن هنالك بعض القواعد التي عليك مراعاتها: يجب أن تبدأ أسماء المتغيرات بحرف. يجب ألّا يحتوي اسم المتغير على فراغات. استخدم الشرطات السفلية (_) بدلًا منها. لا تستطيع استخدام علامات الترقيم. كيف أثر المتغير على السكربت الذي نكتبه سهَّلت إضافة المتغير title الأمر علينا من ناحيتين: الأولى هي تقليل مقدار الكتابة الذي نحتاجه، والثانية (وهي المهمة) هي أننا جعلنا صيانة السكربت أسهل. كلما ازدادت خبرتك في كتابة سكربتات الشِل (أو أي لغة برمجة أخرى)، فستتعلم أنَّك لا تنتهي من كتابة البرنامج في خطوة واحدة، فهنالك تعديلات وتحسينات من قبِل كاتب البرنامج أو من غيره؛ وهذا هو حجر الأساس لعملية تطوير البرمجيات مفتوحة المصدر. فلنقل مثلًا أنَّك تريد تغيير العبارة "My System Information" إلى "Linuxbox System Information"، فكنت تحتاج -في النسخة القديمة من السكربت- إلى تغيير تلك العبارة في مكانين منفصلين، أما في النسخة الجديدة التي فيها المتغير title فلا حاجة إلى تغيير تلك العبارة إلا في مكانٍ وحيد. قد تظن أنَّ هذا التغيير تافه أو ليس له فائدة حقيقية، لكن ذلك لأنَّ السكربت الذي نكتبه ما يزال بسيطًا وقصيرًا؛ لكن التنظيم أساسيٌ جدًا في السكربتات الكبيرة والمعقدة. متغيرات البيئة Environment Variables هنالك بعض المتغيرات المضبوطة في جلسة الصَدَفة من قِبل ملفات البدء التي رأيناها سابقًا. استعمل الأمر printenv لرؤية جميع المتغيرات الموجودة في البيئة عندك؛ يحتوي أحد تلك المتغيرات "اسم المضيف" (hostname) لنظامك؛ ونستطيع أن نُضيف ذاك المتغير إلى السكربت كالآتي: #!/bin/bash # sysinfo_page - A script to produce an HTML file title="System Information for" cat <<- _EOF_ <html> <head> <title> $title $HOSTNAME </title> </head> <body> <h1>$title $HOSTNAME</h1> </body> </html> _EOF_ أصبح السكربت الآن يضع اسم الحاسوب الذي نعمل عليه في صفحة HTML الناتجة. لاحظ أنَّ أسماء متغيرات البيئة (وفق التقاليد البرمجية) تُكتَب بأحرفٍ كبيرة. تعويض الأوامر سنحاول الآن تحسين السكربت بوضع ناتج من أحد الأوامر فيه. كانت آخر نسخة من السكربت قادرةً على إنشاء صفحة HTML تحتوي على أسطر نصية بسيطة تتضمن اسم المضيف لجهازنا المأخوذ من متغير البيئة المسمى HOSTNAME، سنُحدِّث السكربت الآن لإضافة بصمة وقت إلى الصفحة لكي تُشير إلى آخر تحديث لها، مع ذكر اسم المستخدم الذي قام بالتحديث. #!/bin/bash # sysinfo_page - A script to produce an HTML file title="System Information for" cat <<- _EOF_ <html> <head> <title> $title $HOSTNAME </title> </head> <body> <h1>$title $HOSTNAME</h1> <p>Updated on $(date +"%x %r %Z") by $USER</p> </body> </html> _EOF_ كما لاحظت، استعملنا متغير بيئة جديد هو USER لكي نحصل على اسم المستخدم؛ واستعملنا تعبيرًا غريب المظهر: $(date +"%x %r %Z") المحارف ‎$()‎ تقول "يجب وضع ناتج الأمر المُحاط بالأقواس هنا". وأردنا في السكربت السابق وضع ناتج الأمر date +"%x %r %Z"‎ الذي يطبع التاريخ والوقت الحاليين. لدى الأمر date ميزاتٌ وخياراتُ تنسيقٍ كثيرة، نستطيع إلقاء نظرة عليها كالآتي: $ date --help | less لاحظ أنَّ هنالك صيغة قديمة بديلة عن (‎$(command هي استخدام علامة الاقتباس الخلفية "`"، هذه الصيغة القديمة متوافقة مع صَدَفة Bourne Shell الأصلية (sh)؛ لكنني لا أنوي استخدام الشكل القديم لأنني أشرح استخدام bash الحديثة وليس sh. تدعم صَدَفة bash جميع السكربتات المكتوبة لـ sh، ولهذا تكون الصيغتان الآتيتان متكافئتين: $(command) `command` إسناد ناتج أحد الأوامر إلى متغير يمكننا أيضًا إسناد ناتج أحد الأوامر إلى متغير: right_now=$(date +"%x %r %Z") نستطيع أيضًا وضع متغير داخل متغير آخر كما يلي: right_now=$(date +"%x %r %Z") time_stamp="Updated on $right_now by $USER" الثوابت كما يوحي اسم "المتغيرات": قيمة المتغير قابلة للتبديل، وهذا يعني أنَّه من المحتمل أثناء تنفيذ السكربت أن تُعدَّل قيمة المتغير نتيجةً لعمليةٍ قمتَ بها. في المُقابل، هنالك قيم يجب ألّا تتغير بعد ضبطها، وتسمى "الثوابت" (constants). سبب ذكري لهذا الموضوع هو أنَّ مفهوم الثوابت شائعٌ في البرمجة، وتدعمها أغلبية لغات البرمجة، لكن لكي أكون صريحًا معك، لم أشاهد استعمالًا عمليًا لها. فلو كان من المفترض أن تبقى قيم المتغير ثابتةً فسيسمى المتغير بأحرفٍ كبيرة لتذكير المبرمج أنَّ قيمة المتغير ثابتة. تُعتبَر متغيرات البيئة ثوابتَ لأنها نادرًا ما تتغير؛ وتُعطى الثوابت أسماءً ذات أحرفٍ كبيرة عادةً. سأستعمل العرف الآتي في هذا السكربت: الأحرف الكبيرة للثوابت والأحرف الصغيرة للمتغيرات. يبدو السكربت الذي نعمل عليه كالآتي حاليًا: #!/bin/bash # sysinfo_page - A script to produce an HTML file title="System Information for $HOSTNAME" RIGHT_NOW=$(date +"%x %r %Z") TIME_STAMP="Updated on $RIGHT_NOW by $USER" cat <<- _EOF_ <html> <head> <title> $title </title> </head> <body> <h1>$title</h1> <p>$TIME_STAMP</p> </body> </html> _EOF_ ترجمة -وبتصرّف- للمقالَين Variables و Command Substitution And Constants لصاحبهما William Shotts.
  4. تعرّفنا في الدّرس السّابق على لغة روبي ووميزاتها. في هذا الدّرس سوف نستعرض بعض أنواع البيانات في Ruby، وسنتعرّف باستفاضة على نوع السلاسل. كما سنتعرّف على أحد أهمّ سمات أيّ لغة برمجة، ألا وهي المتغيّرات. سنستخدم في الجزء الأول من الدّرس سطر أوامر روبي التفاعليّ. افتح الطرفيّة وابدأ جلسة irb عن طريق كتابة أمر irb والضغط على زر Enter. القيم والأنواع القيمة هي أبسط شيء يتعامل معه البرنامج مثل حرف أو رقم. تعرّفنا في الدّرس السّابق على بعض تلك القيم. تختلف القيمة 2 عن القيمة "Hello World"، حيث أن الأولى هي عدد صحيح Integer أمّا الثّانية فهي من نوع سلسلة String، جاءت التسمية من كونها سلسلة من الأحرف. يمكنك التعرّف بسهولة على السلاسل من خلال علامات الاقتباس المحيطة بالقيمة. هناك نوع آخر يسمّى Float وهو أيّ رقم يحتوي على علامة عشريّة، مثلاً: 2.5، 13.6، 4.0. ملحوظة: قد تعتقد أن "12" و"1.5" هي أرقام وتتعامل معها في برنامجك على ذلك فتنفّذ عليها عمليّات حسابيّة وتكتشف بعد ذلك أنّ مفسّر روبي يظهر لك علّة برمجية Bug. سبب ذلك أنّها ربّما تكون أرقامًا بالنسبة لك ولكن المفسّر يعتبرها سلاسل نصيّة حيث أنّها محاطة بعلامات الاقتباس والمفسّر مُبَرْمَج على تصنيف أيّ شيء بين علامات اقتباس على أنّه سلسلة. تريد التأكد من ذلك بنفسك؟ جرّب جمع "12" + "1.5". أو بطريقة أخرى يمكنك استخدام الدّالة المدمجة is_a لسؤال روبي هل هذه القيمة نوعها Integer مثلاً وستردّ عليك روبي true أو false. فمثلاً إذا أردت التأكّد من نوع قيمة معيّنة مثل 12 اكتب الأمر التالي: 12.is_a?(Integer) الآن للعودة إلى ما إذا كان كل من "12" و"1.5” أرقامًا أم سلاسل، جرّب الأوامر التالية (تأكّد من كتابة أوّل حرف بشكل كبير Capital): "12".is_a?(Integer) "1.5".is_a?(Float) أحيانًا عند كتابة أعداد كبيرة قد تجد نفسك محتاجًا إلى إرفاق فواصل لجعل العدد قابلاً للقراءة أكثر، مثلاً 1,000,000. لو فعلت ذلك في روبي ستحصل على خطأ. ولكن يمكنك فعل ذلك مع الأمر puts. مثلاً يمكن كتابة: puts 1,000,000 ماذا كانت النتيجة؟ لم تتوقعها أليس كذلك؟ قامت روبي قامت بطباعة: 1 0 0 رقم 1 و 0 و 0 في أسطر مختلفة. حدث ذلك لأنّ روبي قد فسّرت هذا العدد على أنّه ثلاثة أرقام مستقلّة ومفصول بينها بفواصل. في روبي يمكن استخدام الأمر puts لطباعة أكثر من قيمة في أكثر من سطر عن طريق الفصل بين تلك القيم بفاصلة. فمثلاً لو أردت طباعة "Hello" في سطر وبعدها "World" في سطر باستخدام أمر روبي واحد يمكن استخدام الأمر التالي: puts "Hello", "World" Hello World السلاسل السلاسل في روبي هي مجموعات من الأحرف. يمكن إنشاء سلسلة نصيّة عن طريق كتابة أحرف ونصوص داخل علامتي اقتباس مزدوجة. مثلاً لكتابة سلسلة تحتوي على نصّ Hello Ruby اكتب الأمر التّالي: "Hello Ruby" يمكن استخدام علامة الاقتباس المفردة أيضًا لإنشاء سلسلة في روبي، لذلك فيمكن إنشاء السلسلة السّابقة كالتّالي: 'Hello Ruby' إذا أردت استخدام أحد نوعي علامات الاقتباس في داخل نصّك فعليك استخدام النّوع الآخر لإنشاء السلسلة فمثلا لو أردت إنشاء سلسلة نصيّة بها I'm learning Ruby، واستخدمت علامة الاقتباس المفردة لإنشاء السلسلة سيؤدّي ذلك إلى حدوث خطأ ولن يتمّ تنفيذ الأمر. لذلك فالطريقة الصحيحة لكتابة هذه السلسلة هو استخدام علامة الاقتباس المزدوجة: "I'm learning Ruby" مثال آخر: puts '"Never memorize something that you can look up." -Albert Einstein' خيار آخر لاستخدام علامات الاقتباس في السلاسل يسمّى هروب علامة الاقتباس escaping، يحدث هذا عن طريق وضع خط مائل عكسي Backslash قبل علامة الاقتباس والذي سيؤدّي إلى اعتبارها حرفًا عاديًّا بدلاً من تنفيذها كوسيلة لإنشاء سلسلة. يمكن إذًا كتابة السلسلتين السّابقتين كالتّالي: 'I\'m learning Ruby" "\"Never memorize something that you can look up.\" -Albert Einstein" ذكرنا في الدّرس الأوّل أنّ كل شيء في روبي هو كائن Object. يمكن للكائنات تنفيذ أفعال يُطلق عليها اسم دوال. هناك الكثير من الطرق لجعل كائن ينفّذ دالّة ولكن الطريقة الأكثر شيوعًا هي التنويت النُقطي Dot Notation وهو عبارة عن أن تكتب الكائن (في مثالنا هذا الكائن هو السلسلة "Hello Ruby") متبوع بنقطة ثم اسم الدّالة التي تريد استدعاءها. لنجرّب استدعاء الدّالة length والتي هي دالّة مدمجة في روبي تقوم بإرجاع طول السلسلة أو بمعنى آخر عدد الأحرف الموجودة في السلسلة: "Hello Ruby".length المتغيرات أحد أقوى السمات في أيّ لغة برمجة هي القدرة على التعامل مع المتغيّرات. المتغيّر ببساطة هو عنوان (أو "اسم") يشير إلى قيمة معيّنة. بمعنى آخر فالمتغيّر هو طريقة لحفظ الكائنات في الذّاكرة من أجل الاستخدام لاحقًا. يمكن في روبي تعيين متغيّر إلى كائن بسهولة باستخدام عامل التساوي (Equals Operator =): name = "Sara" في هذا المثال، اسم المتغيّر يشير إلى السلسلة "Sara". يعني هذا أنّه بإمكاننا استدعاء دوال مختلفة مباشرةً على اسم المتغيّر بدلاً من كتابة السلسلة في كلّ مرة أردنا استدعاء دالّة. الآن إذا أردت استدعاء الدّالة length لحساب طول السلسلة يمكن ببساطة كتابة ذلك كالتّالي: name.length لنجرّب الآن بعض دوّال روبي التي يمكن استخدامها مع السّلاسل في روبي (السّلاسل عبارة عن كائنات في روبي) على هذا المتغيّر. على سبيل المثال، دالّة reverse ستقوم بطباعة السلسلة معكوسة: name.reverse دوال upcase و downcase من الدوال الخاصّة بالسلاسل أيضًا دالّتا upcase و downcase. تقوم دالّة upcase بتحويل كل الأحرف الموجودة في السلسلة النصيّة إلى أحرف كبيرة Capital Letters. أمّا دالّة downcase فتحوّل كل الأحرف الموجودة في السلسلة إلى أحرف صغيرة Small Letters. جرّب استدعاء الدّالتين على المتغيّر name: name.upcase name.downcase هناك عدد كبير جدًا من الدوال الخاصّة بالسلاسل يمكنك التعرّف على جميعها عن طريق استخدام دالّة methods (نعم هذا هو اسمها) على المتغيّر الخاصّ بك، هكذا: name.methods عند تنفيذ الأمر ستقوم روبي بعرض جميع الدوال المختلفة التي يمكن لهذا النوع من الكائنات استخدامها. يمكنك أيضًا معرفة أكثر عن تلك الدوال عن طريق قراءة التوثيقات الخاصّة بها. دوال Bang ربّما لاحظت أن جميع الدوال التي استخدمناها حتّى الآن لم تغيّر شيئًا في السلسلة، فمثلاً إذا أردتُ معرفة القيمة الموجودة في المتغيّر name من جديد سأجد أن القيمة ما زالت كما عيّنتها من البداية (لمعرفة قيمة متغيّرك فقط اكتب اسم المتغيّر واضغط Enter أو استخدم puts إن أردت). لم تتغيّر القيمة وتصبح السلسلة معكوسة ولا جميع الحروف كبيرة أو صغيرة. لكن ماذا لو أردت فعلاً تغيير تلك القيمة؟ سنجرّب بعض الدوال التي تقوم بالفعل بتغيير قيمة السلسلة. أنشئ متغيّرًا باسم fruit واجعله يساوي السلسلة "apple". يمكن تغيير قيمة ذلك المتغيّر عن طريق استدعاء دوال تسمّى بدوال Bang، تنتهي تلك الدوال بعلامة التعجّب أو ما يسمّى برمز Bang. فمثلاً لو أردت تنفيذ الدالة reverse على السلسلة الخاصّة بك وحفظ القيمة الجديدة بدلاً من القيمة الأصليّة يمكن كتابة ذلك ببساطة هكذا: fruit.reverse! عندما نقوم بطباعة المتغيّر بعد ذلك نلاحظ تغيّر القيمة إلى elppa بدلاً من القيمة السّابقة apple. بهذا نكون قد استغنينا تمامًا عن القيمة الأصليّة واستبدلناها بالقيمة الحاليّة. معظم الدوال الخاصّة بالسلاسل لديها دالّة Bang مماثلة. على سبيل المثال هناك أيضًا دالّة Bang مقابلة لدالّة upcase العاديّة. إذًا فيمكننا كتابة: fruit.upcase! سيطبع هذا الأمر قيمة السلسلة بأحرف كبيرة وأيضًا من جديد سيتمّ استبدال القيمة السابقة بالقيمة الجديدة والتي هي ELPPA. إذا كانت هناك علامة تعجّب Bang في نهاية دالّة روبي فهذا غالبًا يعني كن حذرًا، يمكن لهذه الدالّة أن تكون خطرًا. في حالة الأمثلة السّابقة فهي تعني أنّ قيمة السلسلة ستتغيّر فيجب أن تكون حذرًا متى قمت باستخدام هذه الدوال. تسلسل الدوال قد يكون راودك تساؤل حول ماذا لو أردت تنفيذ العديد من الدوال على أحد المتغيّرات، هل يجب كتابة استدعاء الدالّة على المتغيّر لكل دالّة على حدة؟ لحسن الحظّ يمكن استدعاء أكثر من دالة في وقتٍ واحد على نفس المتغيّر. على سبيل المثال إذا عدنا من جديد إلى المتغيّر name وأردنا كتابته معكوسًا وبأحرف كبيرة، يمكن كتابة ذلك تسلسليًّا هكذا: name.reverse.upcase ولكن تذكّر دائمًا أنّه يتمّ تنفيذ الدوال بالترتيب من اليسار إلى اليمين. رغمّ أنّها لا تهمّ في حالة المثال أعلاه، فحتى إذا بدّلنا الترتيب ستكون النتيجة مشابهة. إلا أنّه يمكن أن يتغيّر النّاتج عن النّاتج الذي تتوقعه في حالات أخرى، لذلك يجب التحقّق من الترتيب عند استخدام هذه الطريقة في استدعاء الدوال. إدراج شيفرات برمجية في السلاسل يمكن بطريقة بسيطة جدًا إدراج شيفرات برمجيّة في سلاسل نصيّة وتنفيذ تلك الشيفرات. يمكن فعل ذلك عن طريق وضع الشيفرات البرمجيّة داخل حاضنات Curly Brackets مع إضافة رمز التلبيد Hash في البداية: "Hello my name is #{name}" يطبع هذا نصًا يحتوي على الجملة المكتوبة بالإضافة إلى النصّ الموجود في المتغيّر name الذي قمنا بإنشائه سابقًا. لذلك فالسلسلة السابقة ستصبح "Hello my name is Sara". ما حدث هو أنّه قد تمّ إدراج قيمة المتغيّر name بداخل السلسلة حيث أنّ علامة التلبيد مع الحاضنات تخبر روبي بأن الموجود بينها هو شيفرات يجب على روبي تنفيذها أولاً وليس طباعتها كما هي. هناك أمر مهمّ عليك تذكّره وهو أنّه عند استخدام شيفرات برمجيّة بداخل سلسلة فلا بد من استخدام علامات الاقتباس المزدوجة. إذا استخدمت علامات اقتباس مفردة فسيتمّ طباعة النصّ كما هو {Hello my name is \#{name. والخط المائل هذا يعني أنّه قد تمّ تخطي هذه القيمة وطُبعت كما هي، مثلما رأينا في السّابق مع 'I\'m'. تطبيق عملي الآن بعد التعرّف على المتغيّرات والسلاسل حان الوقت لكتابة برنامج حقيقي باستخدامهما. في هذا البرنامج سيتمّ طباعة سلسلة نصيّة تسأل المستخدم عن اسمه، ثمّ يقوم البرنامج بعد ذلك باستخدام الاسم الذي سيدخله المستخدم لتطبيق بعض الدوال التي تطرّقنا إليها. أوّلاً نحتاج لإنشاء ملفّ روبي، سمّه ما تريد ولكن لا تنس إضافة rb. إلى نهاية اسم الملفّ. لقد أسميتُ ملفّي greetings.rb. بدايةً سنحتاج إلى طباعة رسالة للمستخدم لسؤاله عن اسمه. لفعل ذلك سنستخدم الأمر puts: puts "Hello, what's your name?" بعد ذلك سنحتاج إلى تمكين المستخدم من كتابة اسمه. أمر gets أمر gets هو اختصار لـ get string والذي يقوم بإيقاف البرنامج وانتظار عمليّة إدخال من المستخدم قبل متابعة تنفيذ البرنامج. سيكون المُدخَل عبارة عن سلسلة كما هو واضح من اسم الأمر. إحدى دوال السلاسل دالّة تسمّى chomp يمكن تطبيقها على سلسلة لحذف الحرف الذي يتمّ إضافته افتراضيًّا للسلسلة بعد الضغط على Enter، حيث أنّه عند استقبال إدخال من المستخدم وبضغطه على زرّ Enter يتمّ تلقائيًّا إضافة حرف سطر جديد إلى نهاية السلسلة. إذًا لتمكين المستخدم من إدخال اسمه نحتاج إلى استخدام أمر gets للحصول على المدخل واستدعاء دالّة chomp لحذف الحرف الزائد وحفظ ناتج ذلك في متغيّر لاستخدامه في وقتٍ لاحق. نكتب ذلك في روبي كالآتي: name = gets.chomp وأخيرًا سنقوم بكتابة شيفرات برمجيّة تتعامل مع هذا المدخل وتطبع بعض المعلومات عنه، أضف ما يلي بعد الأمرين السّابقين في ملفّ روبي الخاصّ بك: puts "Hello #{name}. Your name's length is #{name.length}. That's not really long! Your name backwards is #{name.reverse.downcase.capitalize}" ليُصبح كامل الملف على النّحو التّالي: puts "Hello, what's your name?" name = gets.chomp puts "Hello #{name}. Your name's length is #{name.length}. That's not really long! Your name backwards is #{name.reverse.downcase.capitalize}" يقوم هذا الأمر بطباعة سلسلة نصيّة تحتوي على شيفرات برمجيّة تطبع اسم المستخدم، عدد الأحرف في اسم المستخدم واسم المستخدم معكوسًا. لاحظ في الجزء الثالث كيف أضفنا تسلسل دوال من ثلاث دوال، إحداها هي دالّة جديدة تسمّى capitalize. تقوم دالّة capitalize بتغيير الحرف الأوّل فقط من السلسلة وتحويله إلى حرف كبير على عكس دالة upcase التي تحوّل جميع أحرف السلسلة. احفظ الملفّ بعد كتابة الشيفرات البرمجيّة كاملة ثم قم بتنفيذه عن طريق فتح الطرفيّة والتوجّه إلى مسار المجلّد الذي قمت بحفظ الملفّ به ثم كتابة ruby متبوعًا باسم الملف (أي أنه في حالتي سأكتب الأمر ruby greetings.rb)، إذا واجهتك مشكلة في ذلك فراجع كيف قمنا بعمل ذلك في الدّرس الأوّل. خاتمة بهذا نكون قد انتهينا من الدّرس الثاني وتعرفنا على بعض المفاهيم الأساسيّة في روبي. جاء دورك للتطبيق وحدك، قارن ما يفعله البرنامج بالشيفرات البرمجيّة الخاصّة به للتعرّف أكتر على وظيفة كل جزء. طبّق أيضًا استخدام دوال أخرى لم نستخدمها في البرنامج. كذلك ربّما تريد تجربة كتابة اسمك ثنائيًّا أو ثلاثيًّا مع إضافة مسافة بين كل اسم، هل يتمّ حساب المسافة كحرف ضمن الاسم؟ ابحث في الدوال الخاصّة بالسلاسل عن سلسلة تعالج هذا الأمر وطبّقها.
  5. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في الأجزاء الأولى عن الخطوات الأساسيّة لنشر تطبيق، وفي بقيّة الأجزاء تكلمنا عن مواضيع أكثر تقدّمًا مثل قواعد البيانات، عفاريت الطابور queue daemons، وجدولة المهام (عبر cron). سنقوم في هذا الدّرس بالبناء على ما تعلمناه في الدروس السابقة عن طريق تحويل الـ playbook في Ansible من دعمها لتطبيق واحد إلى دعمها لنشر تطبيقات PHP متعدّدة على خادوم أو عدّة خواديم، سنتحدث في هذا الجزء عن إعداد المتغيرات، وسنكمل في الجزء اللاحق عن إضافة المزيد من التطبيقات ونشرها. سنستخدم تطبيقات Lumen بسيطة كجزء أمثلتنا، ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك، من المفضّل أن تستخدم تطبيقات الأمثلة حتى تجد نفسك متآلفًا مع القيام بالتغييرات للـ playbook. المتطلبات الأساسيةتحتاج من أجل متابعة الدّرس إلى: الخادومين الاثنين اللذين قمنا بإعدادهما في الأجزاء السابقة.خادوم Ubuntu جديد (ثالث) يتم إعداده مثل خادوم PHP الأصلي الموجود في الأجزاء السابقة، مع مستخدم sudo غير جذري ومفاتيح SSH، حيث سنستخدمه لإظهار كيفيّة نشر تطبيقات متعدّدة إلى خواديم متعدّدة باستخدام Ansible Playbook واحدة، سنشير لعناوين IP لخادوم PHP الأصلي وخادوم PHP الجديد بـ your_first_server_ip و your_second_server_ip على الترتيب.ملف etc/hosts/ مُحدَّث على حاسوبك المحلّي مع إضافة الأسطر التالية له، تستطيع تعلّم المزيد حول هذا الملف في الخطوة السادسة من هذا الدّرس.your_first_server_ip laravel.example.com one.example.com two.example.com your_second_server_ip laravel.example2.com two.example2.comأمثلة المواقع التي سنستخدمها في هذا الدّرس هي laravel.example.com، one.example.com، و two.example.com، إن أردت استخدام نطاقك الخاص ستحتاج لتحديث تسجيلات DNS النشطة لديك بدلًا من ذلك. الخطوة الأولى – إعداد متغيرات الـ Playbookسنقوم في هذه الخطوة بإعداد متغيّرات الـ playbook لتعريف تطبيقنا الجديد. في الدروس السابقة قمنا بكتابة خصائص الإعدادات بشكل حرفي وهو أمر طبيعي بالنسبة للعديد من الـ playbooks التي تقوم بتنفيذ مهام محدّدة من أجل تطبيق محدّد، أمّا عندما نريد دعم عدّة تطبيقات أو توسيع مدى الـ playbook الخاصّة بنا فلن يعود هنالك معنى من كتابة كل شيء حرفيًّا. وكما شاهدنا سابقًا تزوّدنا Ansible بمتغيرات نستطيع استخدامها في تعريفات المهام وقوالب الملفّات، ما لم نشاهده حتى الآن هو كيفيّة تعيين المتغيرات، في أعلى الـ playbook بجانب مُعامِلات hosts وtasks نستطيع تعريف مُعامِل vars وتعيين متغيراتنا هناك. نقوم بالانتقال إلى الدليل ansible-php الذي تحدثنا عنه في الدّروس السابقة: cd ~/ansible-php/ نفتح الـ playbook الحاليّة من أجل تحريرها: nano php.yml ينبغي أن تبدو بداية الملف كما يلي: Top of original php.yml --- - hosts: php sudo: yes tasks: . . . نستطيع من أجل تعريف المتغيرات إضافة القسم vars فقط، بجانب hosts، sudo، وtasks، ولإبقاء الموضوع بسيط سنبدأ مع متغيّر بسيط جدًّا من أجل المستخدم www-data كما يلي: Updated vars in php.yml --- - hosts: php sudo: yes vars: wwwuser: www-data tasks: . . . نقوم بعدها بتحديث كافّة المرّات التي ورد فيها المستخدم www-data ونضع بدلًا منها المتغيّر {{ wwwuser }}. نضغط على CTRL+\ من أجل البحث والاستبدال باستخدام nano، سنشاهد مُحث prompt يقول: Search (to replace):. نكتب www-data ونضغط ENTER، سيتغيّر المُحِث إلى: Replace with:نكتب هنا {{ wwwuser }} ونضغط ENTER مرّة أخرى، سيأخذنا nano عبر كل مثال من www-data ويسألنا: Replace this instanace?نستطيع أن نضغط y لاستبدال كل واحدة منها، أو نضغط a لاستبدالها كلّها. ملاحظة: تأكّد من عدم تغيير تعريف المتغير الذي أضفناه للتو في أعلى الملف، يجب أن يكون هنالك 11 مثال من www-data نحتاج إلى استبدالها. وقبل أن نكمل هنالك شيء نحتاج للانتباه له فيما يتعلّق بالمتغيرات، بإمكاننا بشكل طبيعي إضافتها كما يلي عندما تكون في سطر أطول: Example task in php.yml - name: create /var/www/ directory file: dest=/var/www/ state=directory owner={{ wwwuser }} group={{ wwwuser }} mode=0700 ومع ذلك إن كان المتغيّر هو القيمة الوحيدة في السلسلة نحتاج إلى وضعه ضمن علامتي اقتباس كي يستطيع مُحلِّل YAML فهمه بشكل صحيح: Updated task in php.yml - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: "{{ wwwuser }}" when: dbpwd.changed يجب أن يحدث هذا في الـ playbook في كل مرّة نحصل فيها على: sudo_user: {{ wwwuser }}نستطيع استخدام بحث واستبدال عام بنفس الطريقة ووضع: sudo_user: "{{ wwwuser }}" بدلًا من: sudo_user: {{ wwwuser }}ينبغي وجود أربعة أسطر تحتاج إلى هذا التغيير. وبعد أن ننتهي من تغييرها نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass ينبغي ألّا توجد مهام متغيّرة، وهو يعني أنّ المتغيّر wwwuser يعمل بشكل صحيح. الخطوة الثانية – تعريف المتغيرات المتداخلة من أجل الإعدادات المعقدةسننظر في هذا القسم إلى المتغيّرات المتداخلة من أجل خيارات الإعدادات المعقدة. قمنا في الخطوة السابقة بإعداد متغيّر بسيط، ولكن يمكن أيضًا أن نُداخِل بين المتغيّرات وأن نُعرِّف قائمة من المتغيّرات، يزودنا هذا بالوظيفة التي نحتاجها لتعريف قائمة من المواقع التي نرغب بإعدادها على خادومنا. دعونا في البداية ننظر إلى مستودع git الحالي الذي قمنا بإعداده في الـ playbook: Existing git task in php.yml - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/do-community/do-ansible-adv-php.git update=yes version=example نستطيع استخراج المعلومات المفيدة التالية: الاسم name (دليل)، المستودع repository، الفرع branch، والنطاق domain، وبما أنّنا نقوم بإعداد تطبيقات متعدّدة سنحتاج أيضًا إلى اسم نطاق من أجله للإجابة عليه، سنستخدم laravel.example.com ولكن إن كنت تملك نطاقك الخاص فضعه هنا. ينتج عن هذا المتغيرات الأربعة التالية التي نستطيع تعريفها من أجل هذا التطبيق: Application variables name: laravel repository: https://github.com/do-community/do-ansible-adv-php.git branch: example domain: laravel.example.com نفتح الآن الـ playbook من أجل تحريرها: nano php.yml نستطيع في القسم العلوي vars إضافة تطبيقنا إلى قائمة التطبيقات الجديدة: Updated applications variables in php.yml --- - hosts: php sudo: yes vars: wwwuser: www-data applications: - name: laravel domain: laravel.example.com repository: https://github.com/do-community/do-ansible-adv-php.git branch: example ... إن قمنا الآن بتشغيل الـ playbook (باستخدام ansible-playbook php.yml --ask-sudo-pass) فلن يتغير شيء لأنّنا لم نقم بعد بإعداد مهامنا لكي تستخدم المتغير applications الجديد، إن ذهبنا إلى http://laravel.example.com/ في متصفحنا فينبغي أن يظهر تطبيقنا الأصلي. الخطوة الثالثة – المرور على المتغيرات عن طريقة حلقة loop في المهامسنتعلم في هذا القسم كيفيّة المرور على قوائم المتغيرات عبر حلقة loop في المهام. كما أشرنا سابقًا تحتاج قوائم المتغيرات المرور عليها عبر حلقة في كل مهمة نرغب في استخدامها فيها، وكما شاهدنا مع المهمّة install packages نحتاج إلى تعريف حلقة من العناصر ومن ثمّ تطبيق المهمّة لكل عنصر في القائمة. نفتح الـ playbook من أجل تحريرها: nano php.yml سنبدأ ببعض المهام السهلة، ينبغي أن نجد مهمتي env في منتصف الـ playbook تقريبًا: Existing env tasks in php.yml - name: set APP_DEBUG=false lineinfile: dest=/var/www/laravel/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false - name: set APP_ENV=production lineinfile: dest=/var/www/laravel/.env regexp='^APP_ENV=' line=APP_ENV=production نلاحظ أنّها مكتوبة الآن بشكل حرفي مع الدليل laravel، نحتاج إلى تحديثها لكي تستخدم الخاصية name لكل تطبيق، ولفعل هذا نضيف الخيار with_items كي يمر على شكل حلقة خلال قائمة applications لدينا، وضمن المهمّة نفسها سنبدل المرجع laravel بالمتغير {{ item.name }}. ينبغي أن تبدو كما يلي: Updated .env tasks in php.yml - name: set APP_DEBUG=false lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^APP_DEBUG=' line=APP_DEBUG=false with_items: applications - name: set APP_ENV=production lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^APP_ENV=' line=APP_ENV=production with_items: applications ننتقل بعدها إلى الأسفل إلى مهمتي Laravel cron، يمكن تحديثهما كما فعلنا تمامًا مع مهام env، سنقوم بإضافة item.name إلى المُعامِل name من أجل مُدخلات لأنّ Ansible تستخدم هذا الحقل لتعرّف بشكل فريد كل مُدخل cron، إن تركناها كما هي فلن نكون قادرين على الحصول على مواقع متعددة على نفس الخادوم لأنّها ستكتب فوق بعضها بشكل ثابت وسيتم حفظ القيمة الأخيرة فقط. ينبغي أن تبدو المهمة كما يلي: Updated cron tasks in php.yml - name: Laravel Scheduler cron: > job="run-one php /var/www/{{ item.name }}/artisan schedule:run 1>> /dev/null 2>&1" state=present user={{ wwwuser }} name="{{ item.name }} php artisan schedule:run" with_items: applications - name: Laravel Queue Worker cron: > job="run-one php /var/www/{{ item.name }}/artisan queue:work --daemon --sleep=30 --delay=60 --tries=3 1>> /dev/null 2>&1" state=present user={{ wwwuser }} name="{{ item.name }} Laravel Queue Worker" with_items: applications إن قمنا بحفظ وتشغيل الـ playbook الآن (باستخدام ansible-playbook php.yml --ask-sudo-pass) فيجب أن نرى أنّه فقط تم تحديث مهمّتي cron، وهذا بسبب التغيير في المُعامِل name، ولا توجد أيّة تغييرات عدا عن ذلك، وهذا يعني أنّ قائمة تطبيقاتنا تعمل كما هو متوقع، ولم نقم بأيّة تغييرات إلى خادومنا كنتيجة لإعادة تصنيع الـ playbook لدينا. الخطوة الرابعة – تطبيق المتغيرات من الحلقة looped variables في قوالب templatesسنغطي في هذا القسم كيفيّة استخدام المتغيرات من الحلقة في القوالب. نستطيع استخدام هذه المتغيرات بنفس الطريقة تمامًا التي استخدمناها في المهام، كما هو الحال مع جميع المتغيرات الأخرى، تأتي الصعوبة عندما نأخذ بعين الاعتبار مسارات الملفات بالإضافة للمتغيرات، لأنّنا سنحتاج في بعض الأحيان إلى أخذ اسم الملف بعين الاعتبار وحتى تنفيذ أوامر أخرى بسبب الملف الجديد. نحتاج في حالة Nginx إلى إنشاء ملف إعدادات جديد لكل تطبيق وإخبار Nginx أنّه ينبغي تمكينها، نريد أيضًا إزالة ملف إعداداتنا الافتراضي: etc/nginx/sites-available/default/ خلال العمليّة. نفتح في البداية الـ playbook من أجل تحريرها: nano php.yml نقوم بإيجاد المهمة Configure Nginx (قرب منتصف الـ playbook) وتحديثها كما فعلنا مع المهام الأخرى: Updated nginx task in php.yml - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/{{ item.name }} with_items: applications notify: - restart php5-fpm - restart nginx وبينما نحن هنا نقوم بإضافة المهمتين الإضافيتين اللتين أشرنا لهما سابقًا، نخبر Nginx في البداية حول ملف إعدادات الموقع الجديد، يتم فعل هذا باستخدام بارتباط رمزي بين أدلة sites-available و sites-enabled في /var/nginx/. نضيف هذه المهمة بعد المهمة Configure nginx: New symlink task in php.yml - name: Configure nginx symlink file: src=/etc/nginx/sites-available/{{ item.name }} dest=/etc/nginx/sites-enabled/{{ item.name }} state=link with_items: applications notify: - restart php5-fpm - restart nginx نرغب بعدها في إزالة ملف إعدادات الموقع المُمكّن افتراضيًّا default كي لا يسبب مشاكل مع ملفّات إعدادات موقعنا الجديد، يتم عمل هذا بسهولة باستخدام الوحدة file: New file task php.yml - name: Remove default nginx site file: path=/etc/nginx/sites-enabled/default state=absent notify: - restart php5-fpm - restart nginx لاحظ أنّنا لم نحتاج إلى وضع applications في حلقة لأنّنا كنّا نبحث عن ملف واحد. يجب أن تبدو كتلة Nginx في الـ playbook كما يلي الآن: Updated nginx tasks in php.yml - name: Configure nginx template: src=nginx.conf dest=/etc/nginx/sites-available/{{ item.name }} with_items: applications notify: - restart php5-fpm - restart nginx - name: Configure nginx symlink file: src=/etc/nginx/sites-available/{{ item.name }} dest=/etc/nginx/sites-enabled/{{ item.name }} state=link with_items: applications notify: - restart php5-fpm - restart nginx - name: Remove default nginx site file: path=/etc/nginx/sites-enabled/default state=absent notify: - restart php5-fpm - restart nginx نحفظ الـ playbook ونفتح الملف nginx.conf من أجل تحريره: nano nginx.conf نقوم بتحديث ملف الإعدادات بحيث يستخدم متغيراتنا: Updated nginx.conf server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /var/www/{{ item.name }}/public; index index.php index.html index.htm; server_name {{ item.domain }}; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/{{ item.name }}/public; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } مع ذلك لم نقم بالانتهاء بعد، أتلاحظ default_server في الأعلى؟ نريد تضمينها فقط من أجل تطبيق laravel لجعله التطبيق الافتراضي، لعمل هذا نستطيع استخدام جملة IF بسيطة لنتحقّق إذا ما كان item.name يساوي laravel وإن كان كذلك نعرض default_server. ستبدو كما يلي: Updated nginx.conf with conditionals server { listen 80{% if item.name == "laravel" %} default_server{% endif %}; listen [::]:80{% if item.name == "laravel" %} default_server ipv6only=on{% endif %}; نحدّث nginx.conf وفقًا لذلك ونحفظه. حان الوقت الآن لتشغيل الـ playbook لدينا: ansible-playbook php.yml --ask-sudo-pass يجب أن تلاحظ أنّه تم تعليم مهام Nginx بأنّها تغيرت، عند الانتهاء من تشغيل الـ playbook نحدّث الموقع في متصفحنا ويجب أن يعرض ما يلي: http://laravel.example.com/ Queue: YES Cron: YES الخطوة الخامسة – وضع متغيرات متعددة في حلقة معاسنقوم في هذه الخطوة بوضع متغيّرات متعدّدة معًا في مهمّة. حان الوقت الآن لمعالجة مثال حلقات أكثر تعقيدًا، خصوصًا المتغيّرات المُسجّلَة، من أجل دعم حالات مختلفة ومنع تشغيل مهام غير ضرورية، تتذكر أنّنا استخدمنا register: cloned في مهمّة استنساخ مستودع git لتسجيل المتغير cloned مع حالة المهمّة، نستخدم بعدها when: cloned|changed في المهام التالية لتحفيز المهام بشكل شرطي، نحتاج الآن إلى تحديث هذه المراجع لتدعم حلقة التطبيقات. نفتح أوّلًا الـ playbook من أجل تحريرها: nano php.yml نبحث عن المهمّة Clone git repository: Existing git task in php.yml - name: Clone git repository git: > dest=/var/www/laravel repo=https://github.com/do-community/do-ansible-adv-php.git update=yes version=example sudo: yes sudo_user: "{{ wwwuser }}" register: cloned وبما أنّنا نقوم بتسجيل المتغيرات في هذه المهمة فلن نحتاج إلى فعل أي شيء لم نفعله سابقًا: Updated git task in php.yml - name: Clone git repository git: > dest=/var/www/{{ item.name }} repo={{ item.repository }} update=yes version={{ item.branch }} sudo: yes sudo_user: "{{ wwwuser }}" with_items: applications register: cloned نبحث الآن عن المهمة composer create-project: Original composer task in php.yml - name: composer create-project composer: command=create-project working_dir=/var/www/laravel optimize_autoloader=no sudo: yes sudo_user: "{{ wwwuser }}" when: cloned|changed نحتاج الآن إلى تحديثها للمرور عبر حلقة على applications و cloned، يتم فعل هذا باستخدام الخيار with_together وتمرير applications وcloned إليها، وبينما تقوم with_together بالمرور عبر حلقة على المتغيرين فيتم الصول إلى العناصر باستخدام item.#، حيث أنّ # هي فهرس المتغير، فعلى سبيل المثال: with_together: - list_one - list_two يشير item.0 إلى list_one ويشير item.1 إلى list_two. يعني هذا أنّنا نستطيع من أجل applications نستطيع الوصول إلى الخصائص عبر: item.0.name، نحتاج من أجل cloned إلى تمرير النتائج من المهام والتي يمكن الوصول إليها عبر cloned.results ومن ثمّ نستطيع التحقّق إن تم تغييرها من خلال item.1.changed. يعني هذا أنّ المهمة ستصبح: Updated composer task in php.yml - name: composer create-project composer: command=create-project working_dir=/var/www/{{ item.0.name }} optimize_autoloader=no sudo: yes sudo_user: "{{ wwwuser }}" when: item.1.changed with_together: - applications - cloned.results نقوم الآن بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass ينبغي ألّا تحدث أيّة تغييرات من هذا التشغيل، ومع ذلك نمتلك الآن متغيرًا مُسجّلًا يعمل بشكل رائع مع حلقة. الخطوة السادسة – المتغيرات المسجلة المعقدة والحلقاتسنتعلم في هذا القسم حول المزيد من المتغيرات المسجلة المعقدة والحلقات. الجزء الأكثر تعقيدًا من التحويل هو مُداولة handling المتغير المسجّل الذي نستخدمه من أجل توليد كلمة السر لقاعدة بيانات MySQL، ولا يوجد أكثر مما فعلناه في هذه الخطوة لم نقم بتغطيته، نحتاج فقط إلى تحديث عدد من المهام في وقت واحد. نفتح الـ playbook من أجل تحريرها: nano php.yml نبحث عن مهام MySQL ونقوم بإضافة المتغيرات البسيطة كما فعلنا في المهمة السابقة: Updated MySQL tasks in php.yml - name: Create MySQL DB mysql_db: name={{ item.name }} state=present with_items: applications - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/{{ item.name }}/.dbpw with_items: applications register: dbpwd - name: Create MySQL User mysql_user: name={{ item.name }} password={{ dbpwd.stdout }} priv={{ item.name }}.*:ALL state=present when: dbpwd.changed - name: set DB_DATABASE lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_DATABASE=' line=DB_DATABASE={{ item.name }} with_items: applications - name: set DB_USERNAME lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_USERNAME=' line=DB_USERNAME={{ item.name }} with_items: applications - name: set DB_PASSWORD lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed - name: Save dbpw file lineinfile: dest=/var/www/{{ item.name }}/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: "{{ wwwuser }}" when: dbpwd.changed - name: Run artisan migrate shell: php /var/www/{{ item.name }}/artisan migrate --force sudo: yes sudo_user: "{{ wwwuser }}" when: dbpwd.changed نضيف بعدها with_together كي نستطيع استخدام كلمة سر قاعدة بياناتنا، ومن أجل توليد كلمة السر نحتاج إلى المرور بحلقة خلال dbpwd.results وسنكون قادرين على الوصول لكلمة السر من item.1.stdout بما أنّه سيتم الوصول لـ applications عبر item.0. نستطيع تحديث الـ playbook وفق ذلك: Updated MySQL tasks in php.yml - name: Create MySQL DB mysql_db: name={{ item.name }} state=present with_items: applications - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/{{ item.name }}/.dbpw with_items: applications register: dbpwd - name: Create MySQL User mysql_user: name={{ item.0.name }} password={{ item.1.stdout }} priv={{ item.0.name }}.*:ALL state=present when: item.1.changed with_together: - applications - dbpwd.results - name: set DB_DATABASE lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_DATABASE=' line=DB_DATABASE={{ item.name }} with_items: applications - name: set DB_USERNAME lineinfile: dest=/var/www/{{ item.name }}/.env regexp='^DB_USERNAME=' line=DB_USERNAME={{ item.name }} with_items: applications - name: set DB_PASSWORD lineinfile: dest=/var/www/{{ item.0.name }}/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ item.1.stdout }} when: item.1.changed with_together: - applications - dbpwd.results - name: Save dbpw file lineinfile: dest=/var/www/{{ item.0.name }}/.dbpw line="{{ item.1.stdout }}" create=yes state=present sudo: yes sudo_user: "{{ wwwuser }}" when: item.1.changed with_together: - applications - dbpwd.results - name: Run artisan migrate shell: php /var/www/{{ item.0.name }}/artisan migrate --force sudo: yes sudo_user: "{{ wwwuser }}" when: item.1.changed with_together: - applications - dbpwd.results بعد أن يتم تحديثها نقوم بحفظها وتشغيلها: ansible-playbook php.yml --ask-sudo-pass بالرغم من جميع التغييرات التي قمنا بها على الـ playbook فلا يجب أن يكون هنالك تغييرات في مهام قاعدة البيانات، ومع التغييرات في هذه الخطوة نكون قد انتهينا من التحويل من playbook تدعم تطبيق وحيد إلى playbook تدعم تطبيقات متعددة. الخاتمةتحدثنا في هذا الجزء عن إعداد المتغيرات، وسنكمل في الجزء اللاحق عن إضافة المزيد من التطبيقات ونشرها إلى خادوم آخر. ترجمة -وبتصرّف- لـ How To Deploy Multiple PHP Applications using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
×
×
  • أضف...