تحسين كود WordPress باستخدام PHP الحديث
نشرت: 2022-03-10وُلد WordPress منذ خمسة عشر عامًا ، ولأنه حافظ تاريخياً على التوافق مع الإصدارات السابقة ، لم تتمكن الإصدارات الأحدث من الكود من الاستفادة الكاملة من أحدث الإمكانات التي توفرها الإصدارات الأحدث من PHP. بينما أحدث إصدار من PHP هو 7.3.2 ، لا يزال WordPress يقدم دعمًا يصل إلى PHP 5.2.4.
لكن تلك الأيام ستنتهي قريباً! سيقوم WordPress بترقية الحد الأدنى من دعم إصدار PHP ، بحيث يصل إلى PHP 5.6 في أبريل 2019 ، و PHP 7 في ديسمبر 2019 (إذا سارت الأمور وفقًا للخطة). يمكننا بعد ذلك أن نبدأ أخيرًا في استخدام إمكانيات البرمجة الضرورية لـ PHP دون خوف من تعطل مواقع عملائنا. يا هلا!
نظرًا لأن خمسة عشر عامًا من التعليمات البرمجية الوظيفية لـ WordPress قد أثرت على كيفية قيام المطورين بالبناء باستخدام WordPress ، فقد تكون مواقعنا وموضوعاتنا ومكوناتنا الإضافية مليئة برمز أقل من الأمثل يمكنه الحصول على ترقية بكل سرور.
تتكون هذه المقالة من جزأين:
- أهم الميزات الجديدة ذات الصلة
تمت إضافة المزيد من الميزات إلى إصدارات PHP 5.3 و 5.4 و 5.5 و 5.6 و 7.0 (لاحظ عدم وجود PHP 6) وسنستكشف أكثرها صلة. - بناء برامج أفضل
سنلقي نظرة فاحصة على هذه الميزات وكيف يمكنها مساعدتنا في بناء برامج أفضل.
لنبدأ باستكشاف ميزات PHP "الجديدة".
الفئات ، OOP ، الصلبة وأنماط التصميم
تمت إضافة الفئات والكائنات إلى PHP 5 ، لذلك يستخدم WordPress بالفعل هذه الميزات ، ولكن ليس بشكل مكثف أو شامل: نموذج الترميز في WordPress هو في الغالب برمجة وظيفية (تنفيذ العمليات الحسابية عن طريق استدعاء وظائف خالية من حالة التطبيق) بدلاً من الكائن البرمجة الموجهة (OOP) (إجراء عمليات حسابية من خلال معالجة حالة الكائنات). ومن ثم أصف أيضًا الفئات والأشياء وكيفية استخدامها من خلال OOP.
يعد OOP مثاليًا لإنتاج تطبيقات معيارية: تسمح الفئات بإنشاء مكونات ، يمكن لكل منها تنفيذ وظيفة محددة والتفاعل مع المكونات الأخرى ، ويمكن أن توفر التخصيص من خلال خصائصها المغلفة ووراثتها ، مما يتيح درجة عالية من إعادة استخدام الكود. نتيجة لذلك ، يكون التطبيق أرخص من حيث الاختبار والصيانة ، حيث يمكن عزل الميزات الفردية عن التطبيق والتعامل معها بمفردها ؛ هناك أيضًا زيادة في الإنتاجية حيث يمكن للمطور استخدام المكونات المطورة بالفعل وتجنب إعادة اختراع العجلة لكل تطبيق.
يحتوي الفصل على خصائص ووظائف ، والتي يمكن إبرازها باستخدام private
(يمكن الوصول إليه فقط من داخل الفئة المحددة) ، protected
(يمكن الوصول إليه من داخل الفئة المحددة وسلفها والفئات الموروثة) public
(يمكن الوصول إليها من كل مكان). من داخل دالة ، يمكننا الوصول إلى خصائص الفئة عن طريق إضافة أسمائهم مسبقًا بـ $this->
:
class Person { protected $name; public function __construct($name) { $this->name = $name; } public function getIntroduction() { return sprintf( __('My name is %s'), $this->name ); } }
يتم إنشاء مثيل لفئة في كائن من خلال الكلمة الأساسية new
، وبعد ذلك يمكننا الوصول إلى خصائصها ووظائفها من خلال ->
:
$person = new Person('Pedro'); echo $person->getIntroduction(); // This prints "My name is Pedro"
يمكن للفئة الوراثية تجاوز الوظائف public
protected
من فئات أسلافها ، والوصول إلى وظائف السلف عن طريق تقديمها مسبقًا مع parent::
class WorkerPerson extends Person { protected $occupation; public function __construct($name, $occupation) { parent::__construct($name); $this->occupation = $occupation; } public function getIntroduction() { return sprintf( __('%s and my occupation is %s'), parent::getIntroduction(), $this->occupation ); } } $worker = new WorkerPerson('Pedro', 'web development'); echo $worker->getIntroduction(); // This prints "My name is Pedro and my occupation is web development"
يمكن جعل الطريقة abstract
، بمعنى أنه يجب تنفيذها بواسطة فئة وراثية. يجب أن تكون الفئة التي تحتوي على طريقة abstract
abstract
نفسها ، مما يعني أنه لا يمكن إنشاء مثيل لها ؛ لا يمكن إنشاء مثيل إلا للفئة التي تطبق الطريقة المجردة:
abstract class Person { abstract public function getName(); public function getIntroduction() { return sprintf( __('My name is %s'), $this->getName() ); } } // Person cannot be instantiated class Manuel extends Person { public function getName() { return 'Manuel'; } } // Manuel can be instantiated $manuel = new Manuel();
يمكن للفئات أيضًا تحديد الأساليب والخصائص static
، والتي تعيش ضمن الفئة نفسها وليس ضمن إنشاء مثيل للفئة ككائن. يتم الوصول إليها من خلال self::
من داخل الفصل ومن خلال اسم الفصل + ::
من خارجه:
class Factory { protected static $instances = []; public static function registerInstance($handle, $instance) { self::$instances[$handle] = $instance; } public static function getInstance($handle) { return self::$instances[$handle]; } } $engine = Factory::getInstance('Engine');
لتحقيق أقصى استفادة من OOP ، يمكننا استخدام مبادئ SOLID لإنشاء أساس سليم وسهل التخصيص للتطبيق ، وأنماط تصميم لحل مشكلات محددة بطريقة مجربة ومختبرة. أنماط التصميم موحدة وموثقة جيدًا ، مما يمكّن المطورين من فهم كيفية ارتباط المكونات المختلفة في التطبيق ببعضها البعض ، وتوفير طريقة لهيكلة التطبيق بطريقة منظمة مما يساعد على تجنب استخدام المتغيرات العالمية (مثل global $wpdb
) التي تلوث البيئة العالمية.
مساحات الأسماء
تمت إضافة مساحات الأسماء إلى PHP 5.3 ، وبالتالي فهي مفقودة تمامًا حاليًا من نواة WordPress.
تسمح Namespaces بتنظيم قاعدة التعليمات البرمجية هيكليًا لتجنب التعارضات عندما يكون لعناصر مختلفة نفس الاسم - بطريقة مشابهة لأدلة نظام التشغيل التي تسمح بوجود ملفات مختلفة بنفس الاسم طالما يتم تخزينها في أدلة مختلفة. تقوم Namespaces بعمل نفس خدعة التغليف لعناصر PHP (مثل الفئات والسمات والواجهات) لتجنب الاصطدامات عندما يكون للعناصر المختلفة نفس الاسم من خلال وضعها في مساحات أسماء مختلفة.
تعد مساحات الأسماء أمرًا ضروريًا عند التفاعل مع مكتبات الطرف الثالث نظرًا لأنه لا يمكننا التحكم في كيفية تسمية عناصرها ، مما يؤدي إلى حدوث تضارب محتمل عند استخدام الأسماء القياسية مثل "ملف" أو "مسجل" أو "رافع" لعناصرنا. علاوة على ذلك ، حتى داخل مشروع واحد ، تمنع مساحات الأسماء من أن تصبح أسماء الفئات طويلة جدًا لتجنب التعارض مع الفئات الأخرى ، مما قد يؤدي إلى أسماء مثل "MyProject_Controller_FileUpload".
يتم تعريف مساحات الأسماء باستخدام namespace
الكلمات الرئيسية (الموضوعة على السطر مباشرة بعد الفتح <?php
) ويمكن أن تمتد على عدة مستويات أو مساحات أسماء فرعية (على غرار وجود عدة أدلة فرعية حيث يتم وضع ملف) ، والتي يتم فصلها باستخدام \
:
<?php namespace CoolSoft\ImageResizer\Controllers; class ImageUpload { }
للوصول إلى الفئة أعلاه ، نحتاج إلى تأهيل اسمها بالكامل بما في ذلك مساحة الاسم الخاصة بها (وتبدأ بـ \
):
$imageUpload = new \CoolSoft\ImageResizer\Controllers\ImageUpload();
أو يمكننا أيضًا استيراد الفئة إلى السياق الحالي ، وبعد ذلك يمكننا الإشارة إلى الفئة باسمها مباشرةً:
use CoolSoft\ImageResizer\Controllers\ImageUpload; $imageUpload = new ImageUpload();
من خلال تسمية مساحات الأسماء باتباع الاصطلاحات المعمول بها ، يمكننا الحصول على مزايا إضافية. على سبيل المثال ، باتباع توصية معايير PHP PSR-4 ، يمكن للتطبيق استخدام آلية التحميل التلقائي الخاصة بـ Composer لتحميل الملفات ، وبالتالي تقليل التعقيد وإضافة إمكانية التشغيل البيني غير الاحتكاكية بين التبعيات. يؤسس هذا الاصطلاح لتضمين اسم البائع (على سبيل المثال ، اسم الشركة) باعتباره مساحة الاسم الفرعية العليا ، متبوعًا بشكل اختياري باسم الحزمة ، وبعد ذلك فقط متبوعًا ببنية داخلية تتوافق فيها كل مساحة اسم فرعية مع دليل يحمل نفس الاسم. تعين النتيجة من 1 إلى 1 الموقع الفعلي للملف في محرك الأقراص بمساحة اسم العنصر المحدد في الملف.
سمات
تمت إضافة السمات إلى PHP 5.4 ، وبالتالي فهي مفقودة تمامًا حاليًا من نواة WordPress.
تدعم PHP الوراثة الفردية ، لذلك يتم اشتقاق فئة فرعية من فئة أصل واحد ، وليس من عدة فئات. ومن ثم ، فإن الفئات التي لا تمتد من بعضها البعض لا يمكنها إعادة استخدام الكود من خلال وراثة الصنف. السمات هي آلية تتيح التكوين الأفقي للسلوك ، مما يجعل من الممكن إعادة استخدام الكود بين الفئات التي تعيش في تسلسلات هرمية للفئات المختلفة.
تشبه السمة فئة ، ومع ذلك ، لا يمكن إنشاء مثيل لها بمفردها. بدلاً من ذلك ، يمكن اعتبار الكود المحدد داخل سمة "نسخًا ولصق" في فئة التأليف في وقت التجميع.
يتم تعريف trait
باستخدام الكلمة الأساسية للسمة ، وبعد ذلك يمكن استيرادها إلى أي فئة من خلال الكلمة الأساسية use
. في المثال أدناه ، يمكن لفئتين غير مرتبطتين تمامًا ، Person
Shop
إعادة استخدام نفس الرمز من خلال سمة Addressable
:
trait Addressable { protected $address; public function getAddress() { return $this->address; } public function setAddress($address) { $this->address = $address; } } class Person { use Addressable; } class Shop { use Addressable; } $person = new Person('Juan Carlos'); $person->setAddress('Obelisco, Buenos Aires');
يمكن للفصل أيضًا أن يؤلف أكثر من سمة واحدة:
trait Exportable { public class exportToCSV($filename) { // Iterate all properties and export them to a CSV file } } class Person { use Addressable, Exportable; }
يمكن أيضًا أن تتكون السمات من سمات أخرى ، وتحدد طرقًا مجردة ، وتقدم آلية لحل النزاعات عندما يكون لسمتين أو أكثر من السمات المكونة نفس اسم الوظيفة ، من بين ميزات أخرى.
واجهات
تمت إضافة واجهات إلى PHP 5 ، لذلك يستخدم WordPress بالفعل هذه الميزة ، ولكن بشكل مقتصد للغاية: يتضمن النواة أقل من عشر واجهات في المجموع!
تسمح الواجهات بإنشاء رمز يحدد الأساليب التي يجب تنفيذها ، ولكن دون الحاجة إلى تحديد كيفية تنفيذ هذه الأساليب بالفعل. إنها مفيدة لتحديد العقود بين المكونات ، مما يؤدي إلى نمطية أفضل وقابلية للصيانة للتطبيق: يمكن أن تكون الفئة التي تنفذ واجهة عبارة عن صندوق أسود من التعليمات البرمجية ، وطالما أن تواقيع الوظائف في الواجهة لا تتغير ، يمكن ترقية الكود حسب الرغبة دون إحداث تغييرات جذرية ، مما قد يساعد في منع تراكم الديون الفنية. بالإضافة إلى ذلك ، يمكنهم المساعدة في تقليل قفل البائع ، من خلال السماح بتبديل تنفيذ واجهة ما بواجهة بائع مختلف. نتيجة لذلك ، من الضروري ترميز التطبيق مقابل الواجهات بدلاً من التطبيقات (وتحديد التطبيقات الفعلية من خلال حقن التبعية).
يتم تعريف interface
باستخدام الكلمة الأساسية للواجهة ، ويجب أن تسرد فقط التوقيع على أساليبها (أي بدون تحديد محتوياتها) ، والتي يجب أن تكون مرئية public
(بشكل افتراضي ، إضافة عدم وجود كلمة رئيسية للرؤية يجعلها عامة):
interface FileStorage { function save($filename, $contents); function readContents($filename); }
تحدد الفئة أنها تنفذ الواجهة من خلال الكلمة الأساسية الخاصة implements
:
class LocalDriveFileStorage implements FileStorage { function save($filename, $contents) { // Implement logic } function readContents($filename) { // Implement logic } }
يمكن للفصل أن ينفذ أكثر من واجهة ويفصل ,
:
interface AWSService { function getRegion(); } class S3FileStorage implements FileStorage, AWSService { function save($filename, $contents) { // Implement logic } function readContents($filename) { // Implement logic } function getRegion() { return 'us-east-1'; } }
نظرًا لأن الواجهة تعلن عن الغرض من ما يفترض أن يفعله المكون ، فمن المهم للغاية تسمية الواجهات بشكل مناسب.
عمليات الإغلاق
تمت إضافة الإغلاق إلى PHP 5.3 ، وبالتالي فهي مفقودة حاليًا تمامًا من نواة WordPress.
عمليات الإغلاق هي آلية لتنفيذ وظائف مجهولة الهوية ، مما يساعد على إلغاء فوضى مساحة الاسم العالمية من الوظائف ذات الاستخدام الفردي (أو نادرًا ما تستخدم). من الناحية الفنية ، فإن عمليات الإغلاق هي حالات من Closure
الطبقي ، ومع ذلك ، في الممارسة العملية ، يمكننا على الأرجح أن نكون غير مدركين لهذه الحقيقة دون أي ضرر.
قبل عمليات الإغلاق ، كلما مررت دالة كوسيطة إلى دالة أخرى ، كان علينا تحديد الوظيفة مسبقًا وتمرير اسمها كوسيطة:
function duplicate($price) { return $price*2; } $touristPrices = array_map('duplicate', $localPrices);
مع عمليات الإغلاق ، يمكن بالفعل تمرير وظيفة مجهولة (أي بدون اسم) مباشرة كمعامل:
$touristPrices = array_map(function($price) { return $price*2; }, $localPrices);
يمكن لعمليات الإغلاق استيراد المتغيرات إلى سياقها من خلال use
الكلمة الأساسية:
$factor = 2; $touristPrices = array_map(function($price) use($factor) { return $price*$factor; }, $localPrices);
مولدات كهرباء
تمت إضافة المولدات إلى PHP 5.5 ، وبالتالي فهي مفقودة حاليًا تمامًا من نواة WordPress.
توفر المولدات طريقة سهلة لتنفيذ التكرارات البسيطة. يتيح المولد كتابة التعليمات البرمجية التي تستخدم foreach
للتكرار عبر مجموعة من البيانات دون الحاجة إلى إنشاء مصفوفة في الذاكرة. وظيفة المولد هي نفس الوظيفة العادية ، باستثناء أنه بدلاً من العودة مرة واحدة ، يمكن أن yield
عدة مرات كما تحتاج إليها من أجل توفير القيم المراد تكرارها.
function xrange($start, $limit, $step = 1) { for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } foreach (xrange(1, 9, 2) as $number) { echo "$number "; } // This prints: 1 3 5 7 9
الحجج وإقرارات نوع الإرجاع
تم تقديم إعلانات نوع وسيطة مختلفة في إصدارات مختلفة من PHP: WordPress قادر بالفعل على إعلان الواجهات والمصفوفات (وهو ما لا يفعله: بالكاد وجدت مثيلًا واحدًا لوظيفة تعلن عن مصفوفة كمعامل في النواة ، ولا توجد واجهات) ، وسوف ستتمكن قريبًا من التصريح عن العناصر القابلة للاستدعاء (المضافة في PHP 5.4) والأنواع العددية: bool و float و int و string (تمت إضافتها في PHP 7.0). تمت إضافة إقرارات نوع الإرجاع إلى PHP 7.0.
تسمح إعلانات نوع الوسيطة للوظائف بالتصريح عن النوع المحدد الذي يجب أن تكون عليه الوسيطة. يتم تنفيذ التحقق من الصحة في وقت الاستدعاء ، مما يؤدي إلى استثناء إذا لم يكن نوع الوسيطة هو النوع المصرح به. إقرارات نوع الإرجاع هي نفس المفهوم ، ومع ذلك ، فهي تحدد نوع القيمة التي سيتم إرجاعها من الوظيفة. تعد تعريفات النوع مفيدة لتسهيل فهم الغرض من الوظيفة ولتجنب أخطاء وقت التشغيل من تلقي أو إرجاع نوع غير متوقع.
يتم التصريح عن نوع الوسيطة قبل اسم متغير الوسيطة ، ويتم التصريح عن نوع الإرجاع بعد الوسائط مسبوقًا بـ :
function foo(boolean $bar): int { }
التصريحات من نوع الوسيطة العددية لها خياران: قسري وصارم. في الوضع القسري ، إذا تم تمرير النوع الخطأ كمعامل ، فسيتم تحويله إلى النوع الصحيح. على سبيل المثال ، الدالة التي يتم إعطاؤها عددًا صحيحًا للمعلمة التي تتوقع سلسلة ستحصل على متغير من نوع السلسلة. في الوضع المتشدد ، لن يُقبل سوى متغير من النوع الدقيق للإعلان.
الوضع الإجباري هو الوضع الافتراضي. لتمكين الوضع المتشدد ، يجب أن نضيف بيان declare
المستخدم مع إعلان strict_types
:
declare(strict_types=1); function foo(boolean $bar) { }
عوامل التركيب والنحو الجديدة
يمكن لـ WordPress بالفعل تحديد قوائم الوسائط متغيرة الطول من خلال الوظيفة func_num_args
. بدءًا من PHP 5.6 ، يمكننا استخدام الرمز المميز ...
للإشارة إلى أن الوظيفة تقبل عددًا متغيرًا من الوسائط ، وسيتم تمرير هذه الوسائط إلى المتغير المحدد كمصفوفة:
function sum(...$numbers) { $sum = 0; foreach ($numbers as $number) { $sum += $number; } return $sum; }
بدءًا من PHP 5.6 ، يمكن أن تتضمن الثوابت تعبيرات عددية تتضمن قيمًا حرفية رقمية وسلسلة بدلاً من القيم الثابتة فقط ، وكذلك المصفوفات:
const SUM = 37 + 2; // A scalar expression const LETTERS = ['a', 'b', 'c']; // An array
بدءًا من PHP 7.0 ، يمكن أيضًا تعريف المصفوفات باستخدام define
:
define('LETTERS', ['a', 'b', 'c']);
أضاف PHP 7.0 عدة عوامل تشغيل جديدة: عامل الاندماج الفارغ ( ??
) ومشغل سفينة الفضاء ( <=>
).
عامل الاندماج الفارغ ??
هو سكر نحوي للحالة الشائعة للحاجة إلى استخدام ثلاثي بالتزامن مع isset (). تقوم بإرجاع المعامل الأول إذا كان موجودًا وليس NULL ؛ وإلا فإنه يقوم بإرجاع المعامل الثاني.
$username = $_GET['user'] ?? 'nobody'; // This is equivalent to: // $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
يتم استخدام عامل تشغيل سفينة الفضاء <=>
لمقارنة تعبيرين ، بإرجاع -1 أو 0 أو 1 عندما يكون المعامل الأول أقل من أو يساوي أو أكبر من المعامل الثاني على التوالي.
echo 1 <=> 2; // returns -1 echo 1 <=> 1; // returns 0 echo 2 <=> 1; // returns 1
هذه هي أهم الميزات الجديدة التي تمت إضافتها إلى PHP الممتدة للإصدارات 5.3 إلى 7.0. يمكن الحصول على قائمة الميزات الإضافية الجديدة ، غير المدرجة في هذه المقالة ، من خلال تصفح وثائق PHP حول الترحيل من إصدار إلى إصدار.
بعد ذلك ، نحلل كيف يمكننا تحقيق أقصى استفادة من كل هذه الميزات الجديدة ، ومن الاتجاهات الحديثة في تطوير الويب ، لإنتاج برامج أفضل.
توصيات معايير PHP
تم إنشاء توصيات معايير PHP من قبل مجموعة من مطوري PHP من أطر عمل ومكتبات شائعة ، في محاولة لإنشاء اتفاقيات بحيث يمكن دمج المشاريع المختلفة بسلاسة أكبر ويمكن للفرق المختلفة العمل بشكل أفضل مع بعضها البعض. التوصيات ليست ثابتة: قد يتم إهمال التوصيات الحالية ويتم إنشاء التوصيات الأحدث لتحل محلها ، ويتم إصدار التوصيات الجديدة بشكل مستمر.
التوصيات الحالية هي كما يلي:
مجموعة | توصية | وصف |
---|---|---|
أنماط الترميز يقلل التنسيق القياسي من الاحتكاك المعرفي عند قراءة التعليمات البرمجية من مؤلفين آخرين | PSR-1 | معيار الترميز الأساسي |
PSR-2 | دليل أسلوب الترميز | |
التحميل التلقائي تزيل برامج التحميل التلقائي تعقيد تضمين الملفات عن طريق تعيين مساحات الأسماء لمسارات نظام الملفات | PSR-4 | تحسين التحميل التلقائي |
واجهات تعمل الواجهات على تبسيط مشاركة الكود بين المشاريع باتباع العقود المتوقعة | PSR-3 | واجهة المسجل |
PSR-6 | واجهة التخزين المؤقت | |
PSR-11 | واجهة الحاوية | |
PSR-13 | روابط الوسائط التشعبية | |
PSR-16 | مخبأ بسيط | |
HTTP واجهات ومعايير قابلة للتشغيل المتبادل للحصول على نهج محايد للتعامل مع طلبات واستجابات HTTP ، سواء من جانب العميل والخادم | PSR-7 | واجهات رسائل HTTP |
PSR-15 | معالجات HTTP | |
PSR-17 | مصانع HTTP | |
PSR-18 | عميل HTTP |
فكر ورمز في المكونات
تجعل المكونات من الممكن استخدام أفضل الميزات من إطار عمل دون أن تكون مقفلة في إطار العمل نفسه. على سبيل المثال ، تم إصدار Symfony كمجموعة من مكونات PHP القابلة لإعادة الاستخدام والتي يمكن تثبيتها بشكل مستقل عن إطار عمل Symfony ؛ يستخدم Laravel ، وهو إطار PHP آخر ، العديد من مكونات Symfony ، وأصدر مجموعته الخاصة من المكونات القابلة لإعادة الاستخدام التي يمكن استخدامها بواسطة أي مشروع PHP.
يتم نشر كل هذه المكونات في Packagist ، وهو مستودع لحزم PHP العامة ، ويمكن إضافتها بسهولة إلى أي مشروع PHP من خلال Composer ، وهو مدير تبعية شائع للغاية لـ PHP.
يجب أن يكون WordPress جزءًا من دورة التطوير الحميدة هذه. لسوء الحظ ، لم يتم إنشاء نواة WordPress نفسها باستخدام مكونات (كما يتضح من الغياب شبه التام للواجهات) ، علاوة على ذلك ، لا تحتوي حتى على ملف composer.json المطلوب لتمكين تثبيت WordPress من خلال Composer. هذا لأن مجتمع WordPress لم يوافق على ما إذا كان WordPress هو تبعية للموقع (في هذه الحالة يكون تثبيته من خلال Composer مبررًا) أو إذا كان الموقع نفسه (في هذه الحالة قد لا يكون Composer هو الأداة المناسبة للوظيفة) .
في رأيي ، إذا كنا نتوقع أن يظل WordPress مناسبًا لمدة الخمسة عشر عامًا القادمة (على الأقل WordPress باعتباره CMS للخلفية) ، فيجب التعرف على WordPress على أنه تبعية للموقع وإتاحته للتثبيت من خلال Composer . السبب بسيط للغاية: مع وجود أمر واحد بالكاد في المحطة ، يتيح Composer إعلان وتثبيت تبعيات المشروع من بين آلاف الحزم المنشورة في Packagist ، مما يجعل من الممكن إنشاء تطبيقات PHP قوية للغاية في وقت قصير ، ويحب المطورون تعمل بهذه الطريقة. إذا لم يتكيف WordPress مع هذا النموذج ، فقد يفقد الدعم من مجتمع التطوير ويسقط في غياهب النسيان ، بقدر ما لم يعد FTP محبوبًا بعد إدخال عمليات النشر المستندة إلى Git.
أود أن أزعم أن إصدار Gutenberg يوضح بالفعل أن WordPress هو تبعية للموقع وليس الموقع نفسه: Gutenberg يتعامل مع WordPress باعتباره CMS بدون رأس ، ويمكنه العمل مع أنظمة الخلفية الأخرى أيضًا ، كما يوضح Drupal Gutenberg. ومن ثم ، يوضح جوتنبرج أن نظام إدارة المحتوى الذي يشغل موقعًا ما يمكن أن يكون قابلاً للتبديل ، وبالتالي يجب التعامل معه على أنه تبعية. علاوة على ذلك ، يُقصد من Gutenberg نفسه أن يكون قائمًا على مكونات JavaScript التي تم إصدارها من خلال npm (كما أوضح من قبل العميل الأساسي Adam Silverstein) ، لذلك إذا كان من المتوقع أن يقوم عميل WordPress بإدارة حزم JavaScript الخاصة به من خلال مدير الحزم npm ، فلماذا لا يتم تمديد هذا المنطق إلى الواجهة الخلفية لإدارة تبعيات PHP من خلال Composer؟
الآن الخبر السار: ليست هناك حاجة لانتظار حل هذه المشكلة لأنه من الممكن بالفعل التعامل مع WordPress على أنه تبعية للموقع وتثبيته من خلال Composer. قام John P. Bloch بعكس نواة WordPress في Git ، وإضافة ملف composer.json ، وإصداره في Packagist ، ويوفر Bedrock لـ Roots حزمة لتثبيت WordPress بهيكل مجلد مخصص مع دعم لأدوات التطوير الحديثة وأمان محسن. ويتم تغطية السمات والإضافات أيضًا ؛ طالما تم إدراجها في قالب WordPress وأدلة المكونات الإضافية ، فهي متوفرة ضمن WordPress Packagist.
نتيجة لذلك ، يعد إنشاء كود WordPress خيارًا منطقيًا دون التفكير في السمات والإضافات ، ولكن التفكير من حيث المكونات ، وإتاحتها من خلال Packagist لاستخدامها من قبل أي مشروع PHP ، بالإضافة إلى حزمها وإصدارها كقوالب و المكونات الإضافية للاستخدام المحدد لـ WordPress. إذا كان المكون يحتاج إلى التفاعل مع واجهات برمجة تطبيقات WordPress ، فيمكن عندئذٍ تلخيص واجهات برمجة التطبيقات هذه خلف واجهة يمكن ، إذا دعت الحاجة ، تنفيذها لأنظمة إدارة المحتوى الأخرى أيضًا.
إضافة محرك قالب لتحسين طبقة العرض
إذا اتبعنا توصية التفكير والتشفير في المكونات ، وتعاملنا مع WordPress على أنه تبعية للموقع بخلاف الموقع نفسه ، فيمكن لمشاريعنا التحرر من الحدود التي يفرضها WordPress واستيراد الأفكار والأدوات المأخوذة من أطر أخرى.
يعتبر عرض محتوى HTML على جانب الخادم مثالاً على ذلك ، ويتم ذلك من خلال قوالب PHP العادية. يمكن تحسين طبقة العرض هذه من خلال محركات القوالب Twig (بواسطة Symfony) و Blade (بواسطة Laravel) ، والتي توفر بنية موجزة للغاية وميزات قوية تمنحها ميزة على قوالب PHP العادية. على وجه الخصوص ، يمكن أن تستفيد الكتل الديناميكية لـ Gutenberg بسهولة من محركات القوالب هذه ، نظرًا لأن عملية عرض HTML للكتلة على جانب الخادم منفصلة عن بنية قالب WordPress الهرمي.
مهندس تطبيق للاستخدام العام
يسمح لنا التشفير مقابل الواجهات ، والتفكير من حيث المكونات ، بتصميم تطبيق للاستخدام العام وتخصيصه للاستخدام المحدد الذي نحتاج إلى تقديمه ، بدلاً من الترميز فقط للاستخدام المحدد لكل مشروع لدينا. على الرغم من أن هذا النهج أكثر تكلفة على المدى القصير (يتضمن عملاً إضافيًا) ، إلا أنه يؤتي ثماره على المدى الطويل عندما يمكن تسليم مشاريع إضافية بجهود أقل من مجرد تخصيص تطبيق للاستخدام العام.
لكي يكون هذا النهج فعالاً ، يجب مراعاة الاعتبارات التالية:
تجنب التبعيات الثابتة (بقدر الإمكان)
كان من الممكن اعتبار jQuery و Bootstrap (أو Foundation ، أو <–Inert your free your library here–> ) من العناصر الضرورية منذ بضع سنوات ، ومع ذلك ، فقد تراجعت بشكل مطرد أمام vanilla JS وميزات CSS الأصلية الأحدث. ومن ثم ، فإن مشروع الاستخدام العام الذي تم ترميزه قبل خمس سنوات والذي كان يعتمد على هذه المكتبات قد لا يكون مناسبًا في الوقت الحاضر بعد الآن. ومن ثم ، كقاعدة عامة ، كلما انخفض مقدار التبعيات الثابتة في مكتبات الطرف الثالث ، زاد تحديثها على المدى الطويل.
التحسين التدريجي للوظائف
WordPress هو نظام CMS كامل يتضمن إدارة المستخدم ، وبالتالي يتم تضمين دعم إدارة المستخدم خارج الصندوق. ومع ذلك ، لا يتطلب كل موقع WordPress إدارة المستخدم. ومن ثم ، يجب أن يأخذ تطبيقنا هذا في الاعتبار ، ويعمل على النحو الأمثل على كل سيناريو: دعم إدارة المستخدم كلما لزم الأمر ، ولكن لا تقم بتحميل الأصول المقابلة عندما لا تكون كذلك. يمكن أن يعمل هذا النهج أيضًا بشكل تدريجي: لنفترض أن العميل يطلب تنفيذ نموذج اتصل بنا ولكن ليس لديه ميزانية ، لذلك نقوم بتشفيره باستخدام مكون إضافي مجاني بميزات محدودة ، وعميل آخر لديه الميزانية لشراء الترخيص من عرض مكون إضافي تجاري أفضل الميزات. بعد ذلك ، يمكننا ترميز وظائفنا إلى الوظيفة الأساسية بشكل افتراضي ، واستخدام الميزات بشكل متزايد من أي مكون إضافي متوفر في النظام.
مراجعة مستمرة للتعليمات البرمجية والوثائق
من خلال مراجعة الكود المكتوب مسبقًا ووثائقه بشكل دوري ، يمكننا التحقق مما إذا كان محدثًا فيما يتعلق بالاتفاقيات والتقنيات الجديدة ، وإذا لم يكن الأمر كذلك ، فاتخذ إجراءات لترقيته قبل أن يصبح الدين الفني مكلفًا للغاية للتغلب عليه ونحتاج إلى إعادة ترميزها بالكامل من البداية.
القراءة الموصى بها : كن يقظًا: وظائف PHP و WordPress التي يمكن أن تجعل موقعك غير آمن
حاول تقليل المشكلات ولكن كن مستعدًا عند حدوثها
لا يوجد برنامج مثالي بنسبة 100٪ على الإطلاق: الأخطاء موجودة دائمًا ، ولم نعثر عليها بعد. على هذا النحو ، نحتاج إلى التأكد من أنه بمجرد ظهور المشكلات ، يسهل إصلاحها.
اجعلها بسيطة
لا يمكن الحفاظ على البرامج المعقدة على المدى الطويل: ليس فقط لأن أعضاء الفريق الآخرين قد لا يفهمونها ، ولكن أيضًا لأن الشخص الذي قام بترميزها قد لا يفهم الكود الخاص به / بها بعد بضع سنوات على الطريق. لذلك يجب أن يكون إنتاج برامج بسيطة أولوية ، لأن البرامج البسيطة فقط هي التي يمكن أن تكون صحيحة وسريعة.
الفشل في وقت الترجمة أفضل من وقت التشغيل
إذا كان من الممكن التحقق من صحة جزء من التعليمات البرمجية ضد الأخطاء في وقت التجميع أو وقت التشغيل ، فيجب علينا إعطاء الأولوية لحل وقت الترجمة ، لذلك يمكن أن يظهر الخطأ ويتم التعامل معه في مرحلة التطوير وقبل أن يصل التطبيق إلى الإنتاج. على سبيل المثال ، يتم استخدام كل من الثابت const
define
const
، ومع ذلك ، في حين يتم التحقق من صحة الثابت في وقت الترجمة ، يتم التحقق من صحة define
في وقت التشغيل. لذلك ، كلما أمكن ، يفضل استخدام const
على define
.
باتباع هذه التوصية ، يمكن تحسين ربط وظائف WordPress الموجودة في الفئات بتمرير الفئة الفعلية كمعامل بدلاً من سلسلة مع اسم الفئة. في المثال أدناه ، إذا تمت إعادة تسمية الفئة Foo
، في حين أن الخطاف الثاني سينتج خطأ في التحويل البرمجي ، فإن الخطاف الأول سيفشل في وقت التشغيل ، ومن ثم يكون الخطاف الثاني أفضل:
class Foo { public static function bar() { } } add_action('init', ['Foo', 'bar']); // Not so good add_action('init', [Foo::class, 'bar']); // Much better
لنفس السبب المذكور أعلاه ، يجب أن نتجنب استخدام المتغيرات العامة (مثل global $wpdb
): فهذه لا تلوث السياق العالمي فقط وليس من السهل تتبع مصدرها ، ولكن أيضًا ، إذا تمت إعادة تسميتها ، فإن الخطأ سوف يتم إنتاجه في وقت التشغيل. كحل ، يمكننا استخدام حاوية حقن التبعية للحصول على مثيل للكائن المطلوب.
التعامل مع الأخطاء / الاستثناءات
يمكننا إنشاء بنية لكائنات Exception
، بحيث يمكن للتطبيق أن يتفاعل بشكل مناسب وفقًا لكل مشكلة معينة ، إما للاسترداد منه كلما أمكن ذلك أو إظهار رسالة خطأ مفيدة للمستخدم عندما لا يكون كذلك ، وبشكل عام لتسجيل الخطأ لـ المشرف لإصلاح المشكلة. ودائمًا احمِ المستخدمين من شاشة الموت البيضاء: يمكن اعتراض جميع Error
Exception
غير المكتشفة من خلال الوظيفة set_exception_handler
لطباعة رسالة خطأ غير مخيفة على الشاشة.
اعتماد أدوات البناء
يمكن أن توفر أدوات الإنشاء الكثير من الوقت عن طريق أتمتة المهام التي يصعب تنفيذها يدويًا. لا يوفر WordPress تكاملاً مع أي أداة بناء محددة ، لذا فإن مهمة دمجها في المشروع ستقع بالكامل على عاتق المطور.
هناك أدوات مختلفة لإنجاز أغراض مختلفة. على سبيل المثال ، هناك أدوات بناء لتنفيذ مهام لضغط الصور وتغيير حجمها ، وتقليل ملفات JS و CSS ، ونسخ الملفات إلى دليل لإنتاج إصدار ، مثل Webpack و Grunt و Gulp ؛ تساعد الأدوات الأخرى في إنشاء سقالات المشروع ، مما يساعد في إنتاج بنية المجلد للقوالب أو المكونات الإضافية ، مثل Yeoman. في الواقع ، مع وجود العديد من الأدوات ، فإن تصفح المقالات التي تقارن الأدوات المختلفة المتاحة سيساعد في العثور على الأداة الأنسب لاحتياجاتنا.
ومع ذلك ، في بعض الحالات ، لا توجد أدوات بناء يمكنها أن تحقق بالضبط ما يحتاجه مشروعنا ، لذلك قد نحتاج إلى ترميز أداة البناء الخاصة بنا باعتبارها امتدادًا للمشروع نفسه. على سبيل المثال ، لقد فعلت ذلك لإنشاء ملف service-worker.js لإضافة دعم لعمال الخدمة في WordPress.
خاتمة
نظرًا لتركيزه القوي على الحفاظ على التوافق مع الإصدارات السابقة ، الممتد حتى PHP 5.2.4 ، لم يتمكن WordPress من الاستفادة من أحدث الميزات المضافة إلى PHP ، وقد جعلت هذه الحقيقة WordPress منصة غير مثيرة للغاية للتعليمات البرمجية من بين العديد من المطورين.
لحسن الحظ ، قد تنتهي هذه الأيام القاتمة قريبًا ، وقد يصبح WordPress نظامًا أساسيًا لامعًا ومثيرًا للترميز مرة أخرى: إن متطلبات PHP 7.0+ بدءًا من ديسمبر 2019 ستوفر الكثير من ميزات PHP ، مما يتيح للمطورين إنتاج أكثر قوة و برامج أكثر أداءً. في هذه المقالة ، راجعنا أهم ميزات PHP المتوفرة حديثًا وكيفية تحقيق أقصى استفادة منها.
قد يكون الإصدار الأخير من Gutenberg علامة على الأوقات الجيدة القادمة: حتى لو لم يتم قبول Gutenberg نفسه بشكل كامل من قبل المجتمع ، فإنه على الأقل يظهر استعدادًا لدمج أحدث التقنيات (مثل React و Webpack) في جوهرها. . هذا التحول في الأحداث يجعلني أتساءل: إذا كان بإمكان الواجهة الأمامية الحصول على مثل هذا التغيير ، فلماذا لا تمتد إلى الواجهة الخلفية؟ بمجرد أن يتطلب WordPress إصدار PHP 7.0 على الأقل ، يمكن أن تتسارع الترقية إلى الأدوات والمنهجيات الحديثة: بقدر ما أصبح npm مدير حزمة JavaScript المفضل ، فلماذا لا تجعل Composer هو مدير تبعية PHP الرسمي؟ إذا كانت الكتل هي الوحدة الجديدة لمواقع البناء في الواجهة الأمامية ، فلماذا لا تستخدم مكونات PHP كوحدة لدمج الوظائف في الواجهة الخلفية؟ وأخيرًا ، إذا كان Gutenberg يتعامل مع WordPress على أنه نظام إدارة محتوى قابل للتبديل ، فلماذا لا ندرك بالفعل أن WordPress هو تبعية للموقع وليس الموقع نفسه؟ سأترك لك هذه الأسئلة المفتوحة للتفكير فيها والتفكير فيها.