باستخدام ميزات اللغة الجديدة في PHP V5، يمكن تحسين قابلية الصيانة وموثوقية التعليمات البرمجية بشكل كبير. من خلال قراءة هذه المقالة، سوف تتعلم كيفية الاستفادة من هذه الميزات الجديدة لترحيل التعليمات البرمجية التي تم تطويرها في PHP V4 إلى PHP V5.
قام PHP V5 بإجراء تحسينات كبيرة بناءً على PHP V4. تعمل ميزات اللغة الجديدة على تسهيل إنشاء مكتبات صفية موثوقة وصيانتها. بالإضافة إلى ذلك، ساعدت إعادة كتابة المكتبة القياسية في جعل PHP أكثر توافقًا مع مصطلحات الويب الأخرى، مثل لغة البرمجة Java™. دعونا نلقي نظرة على بعض ميزات PHP الجديدة الموجهة للكائنات ونتعلم كيفية ترحيل كود PHP V4 الموجود إلى PHP V5.
أولاً، دعونا نلقي نظرة على كيفية تغيير ميزات اللغة الجديدة ومنشئ PHP لطريقة إنشاء الكائنات باستخدام PHP V4. كانت فكرة V5 هي إنشاء لغة ذات قوة صناعية لتطوير تطبيقات الويب. وهذا يعني فهم قيود PHP V4، ثم استخراج بنيات اللغة الجيدة المعروفة من اللغات الأخرى (مثل Java وC# وC++ وRuby وPerl) ودمجها في PHP.
الميزة الجديدة الأولى والأكثر أهمية هي حماية الوصول لأساليب الفئة ومتغيرات الحالة - الكلمات الأساسية العامة والمحمية والخاصة. تسمح هذه الميزة الجديدة لمصممي الفصل بالحفاظ على التحكم في الخصائص الجوهرية للفئة مع إخبار مستخدمي الفئة بالفئات التي يمكن الوصول إليها وتلك التي لا يمكن الوصول إليها.
في PHP V4، كل التعليمات البرمجية عامة. في PHP V5، يمكن لمصممي الفئة الإعلان عن الكود الذي يكون مرئيًا للعالم الخارجي (عام) وأي كود يكون مرئيًا فقط داخل الفصل (خاص) أو فقط للفئات الفرعية للفئة (محمية). بدون عناصر التحكم في الوصول هذه، سيتم إعاقة تطوير التعليمات البرمجية في فريق كبير أو توزيع التعليمات البرمجية كمكتبة لأن مستخدمي هذه الفئات من المحتمل أن يستخدموا أساليب خاطئة أو رمز وصول يجب أن يكون متغيرات أعضاء خاصة.
ميزة جديدة كبيرة أخرى هي واجهة الكلمات الرئيسية والملخص، والتي تسمح ببرمجة العقود. البرمجة التعاقدية تعني أن إحدى الفئات تقدم عقدًا لفئة أخرى - بمعنى آخر: "هذا ما سأفعله، ولا تحتاج إلى معرفة كيفية القيام بذلك." تلتزم جميع الفئات التي تنفذ الواجهة بهذا العقد. يوافق جميع مستخدمي الواجهة على استخدام الأساليب المحددة في الواجهة فقط. الكلمة الأساسية المجردة تجعل العمل مع الواجهات أمرًا سهلاً للغاية، كما سأشرح لاحقًا.
تسمح هاتان الميزتان الرئيسيتان - التحكم في الوصول وبرمجة العقود - لفرق كبيرة من المبرمجين بالعمل بسلاسة أكبر مع قواعد الأكواد الكبيرة. تعمل هذه الميزات أيضًا على تمكين IDE من توفير مجموعة أكثر ثراءً من ميزات اللغة الذكية. لا تتناول هذه المقالة العديد من مشكلات الترحيل فحسب، ولكنها تقضي أيضًا بعض الوقت في شرح كيفية استخدام ميزات اللغة الرئيسية الجديدة هذه.
التحكم في الوصول
لتوضيح ميزات اللغة الجديدة، استخدمت فئة تسمى Configuration. تحتوي هذه الفئة البسيطة على عناصر تكوين لتطبيق الويب - على سبيل المثال، المسار إلى دليل الصور. من الناحية المثالية، ستكون هذه المعلومات موجودة في ملف أو قاعدة بيانات. تظهر القائمة 1 نسخة مبسطة.
القائمة 1.access.php4
<?php
تكوين الطبقة
{
var $_items = array();
function Configuration() {
$this->_items[ 'imgpath' ] = 'images';
}
الحصول على الدالة(مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
$c = التكوين الجديد();
echo( $c->get( 'imgpath' )."n" );
?>
هذه فئة PHP V4 تقليدية تمامًا. يحتفظ متغير العضو بقائمة عناصر التكوين، ويقوم المُنشئ بتحميل العناصر، وتقوم طريقة الوصول المسماة get() بإرجاع قيمة العنصر.
بعد تشغيل البرنامج النصي، سيظهر الكود التالي في سطر الأوامر:
%php access.php4
الصور
%
جيد جدًا! تعني هذه النتيجة أن الكود يعمل بشكل طبيعي ويتم تعيين قيمة عنصر تكوين imgpath وقراءتها بشكل طبيعي.
الخطوة الأولى في تحويل هذه الفئة إلى PHP V5 هي إعادة تسمية المُنشئ. في PHP V5، تسمى طريقة تهيئة الكائن (المنشئ) __construct. يظهر هذا التغيير الصغير أدناه.
القائمة 2.access1.php5
<?php
تكوين الطبقة
{
var $_items = array()
;
$this->_items[ 'imgpath' ] = 'images';
}
الحصول على الدالة(مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
$c = التكوين الجديد();
echo( $c->get( 'imgpath' )."n" );
?>
التغييرات هذه المرة ليست كبيرة. انتقلت للتو إلى اتفاقية PHP V5. الخطوة التالية هي إضافة التحكم في الوصول إلى الفصل للتأكد من أن مستخدمي الفصل لا يمكنهم قراءة وكتابة متغير العضو $_items مباشرة. يظهر هذا التغيير أدناه.
القائمة 3.access2.php5
<?php
تكوين الطبقة
{
خاص $_items = array();
وظيفة عامة __construct() {
$this->_items[ 'imgpath' ] = 'images';
}
الحصول على الوظيفة العامة (مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
$c = التكوين الجديد();
echo( $c->get( 'imgpath' )."n" );
?>
إذا تمكن مستخدم هذا الكائن من الوصول إلى مصفوفة العناصر مباشرة، فسيتم رفض الوصول لأن المصفوفة تم وضع علامة "خاص" عليها. لحسن الحظ، اكتشف المستخدمون أن طريقة get() توفر أذونات القراءة المرحب بها كثيرًا.
لتوضيح كيفية استخدام الأذونات المحمية، أحتاج إلى فئة أخرى، والتي يجب أن ترث من فئة التكوين. لقد اتصلت بهذه الفئة DBConfiguration وافترضت أن الفصل سيقرأ قيم التكوين من قاعدة البيانات. يظهر هذا الإعداد أدناه.
القائمة 4.access3.php
<?php
تكوين الطبقة
{
محمية $_items = array();
وظيفة عامة __construct() {
$هذا->تحميل();
}
تحميل الوظيفة المحمية () { }
الحصول على الوظيفة العامة (مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
تعمل فئة DBConfiguration على توسيع التكوين
{
تحميل الوظيفة المحمية () {
$this->_items[ 'imgpath' ] = 'images';
}
}
$c = new DBConfiguration();
echo( $c->get( 'imgpath' )."n" );
?>
توضح هذه القائمة الاستخدام الصحيح للكلمة الأساسية المحمية. تحدد الفئة الأساسية طريقة تسمى التحميل (). ستتجاوز الفئات الفرعية من هذه الفئة طريقة التحميل () لإضافة البيانات إلى جدول العناصر. تعد طريقة التحميل () داخلية للفئة وفئاتها الفرعية، لذا فإن الطريقة غير مرئية لجميع المستهلكين الخارجيين. إذا كانت جميع الكلمات الأساسية خاصة، فلا يمكن تجاوز طريقة التحميل ().
لا أحب هذا التصميم حقًا، لكنني اخترته لأنه كان علي منح فئة DBConfiguration حق الوصول إلى مصفوفة العناصر. أرغب في الاستمرار في الحفاظ على مصفوفة العناصر بالكامل بواسطة فئة التكوين، بحيث عند إضافة فئات فرعية أخرى، لن تحتاج هذه الفئات إلى معرفة كيفية الحفاظ على مصفوفة العناصر. لقد أجريت التغييرات التالية.
القائمة 5.access4.php5
<?php
تكوين الطبقة
{
خاص $_items = array();
وظيفة عامة __construct() {
$هذا->تحميل();
}
تحميل الوظيفة المحمية () { }
إضافة وظيفة محمية (مفتاح $، قيمة $) {
$this->_items[ $key ] = $value;
}
الحصول على الوظيفة العامة (مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
تعمل فئة DBConfiguration على توسيع التكوين
{
تحميل الوظيفة المحمية () {
$this->add( 'imgpath', 'images' );
}
}
$c = new DBConfiguration();
echo( $c->get( 'imgpath' )."n" );
?>
يمكن الآن أن تكون مصفوفات العناصر خاصة لأن الفئات الفرعية تستخدم طريقة add() المحمية لإضافة عناصر التكوين إلى القائمة. يمكن لفئة التكوين تغيير الطريقة التي تقوم بها بتخزين وقراءة عناصر التكوين بغض النظر عن فئاتها الفرعية. طالما أن طريقتي التحميل () والإضافة () تعملان بنفس الطريقة، فلن يكون هناك أي مشاكل في التصنيف الفرعي.
بالنسبة لي، يعد التحكم في الوصول الإضافي هو السبب الرئيسي للتفكير في الانتقال إلى PHP V5. هل هذا فقط لأن Grady Booch قال أن PHP V5 هي واحدة من اللغات الأربع الرئيسية الموجهة للكائنات؟ لا، لأنني قبلت ذات مرة مهمة الحفاظ على كود 100KLOC C++ الذي تم فيه تعريف جميع الأساليب والأعضاء على أنهم عامون. لقد استغرق الأمر ثلاثة أيام لتنظيف هذه التعريفات، وفي هذه العملية، قمت بتقليل عدد الأخطاء بشكل كبير وتحسين قابلية الصيانة. لماذا؟ لأنه بدون التحكم في الوصول، من المستحيل معرفة كيفية استخدام الكائنات لكائنات أخرى، ومن المستحيل إجراء أي تغييرات دون معرفة العوائق التي يجب التغلب عليها. مع C++، على الأقل لا يزال لدي المترجم متاحًا. PHP لا يأتي مع مترجم، لذلك يصبح هذا النوع من التحكم في الوصول أكثر أهمية.
البرمجة التعاقدية
الميزة المهمة التالية التي يجب الاستفادة منها عند الترحيل من PHP V4 إلى PHP V5 هي دعم البرمجة التعاقدية من خلال الواجهات والفئات المجردة والأساليب. تعرض القائمة 6 نسخة من فئة التكوين حيث حاول مبرمجو PHP V4 إنشاء واجهة أساسية دون استخدام الكلمة الأساسية للواجهة على الإطلاق.
القائمة 6.interface.php4
<?php
تكوين فئة I
{
الحصول على وظيفة (مفتاح $) { }
}
يمتد تكوين الفئة إلى IConfiguration
{
var $_items = array();
function Configuration() {
$هذا->تحميل();
}
تحميل الوظيفة () { }
الحصول على الدالة(مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
تعمل فئة DBConfiguration على توسيع التكوين
{
تحميل الوظيفة () {
$this->_items[ 'imgpath' ] = 'images';
}
}
$c = new DBConfiguration();
echo( $c->get( 'imgpath' )."n" );
?>
تبدأ القائمة بفئة IConfiguration صغيرة تحدد جميع الواجهات التي توفرها فئة Configuration أو الفئات المشتقة. ستحدد هذه الواجهة العقد بين الفصل وجميع مستخدميه. ينص العقد على أن جميع الفئات التي تطبق IConfiguration يجب أن تكون مجهزة بطريقة get() وأن جميع مستخدمي IConfiguration يجب أن يصروا على استخدام طريقة get() فقط.
يتم تشغيل الكود أدناه في PHP V5، ولكن من الأفضل استخدام نظام الواجهة المقدم كما هو موضح أدناه.
القائمة 7.interface1.php5
<?php
واجهة IConfiguration
{
وظيفة الحصول على(مفتاح $);
}
يقوم تكوين الفئة بتنفيذ IConfiguration
{
...
}
تعمل فئة DBConfiguration على توسيع التكوين
{
...
}
$c = new DBConfiguration();
echo( $c->get( 'imgpath' )."n" );
?>
من ناحية، يمكن للقراء فهم حالة التشغيل بشكل أكثر وضوحًا؛ ومن ناحية أخرى، يمكن لفئة واحدة تنفيذ واجهات متعددة. توضح القائمة 8 كيفية توسيع فئة التكوين لتنفيذ واجهة Iterator، وهي الواجهة الداخلية لـ PHP.
القائمة 8.interface2.php5
<?php
واجهة التكوين {
...
}
يقوم تكوين الفئة بتنفيذ IConfiguration، Iterator
{
خاص $_items = array();
وظيفة عامة __construct() {
$هذا->تحميل();
}
تحميل الوظيفة المحمية () { }
إضافة وظيفة محمية (مفتاح $، قيمة $) {
$this->_items[ $key ] = $value;
}
الحصول على الوظيفة العامة (مفتاح $) {
إرجاع $this->_items[ $key ];
}
وظيفة عامة الترجيع () { إعادة تعيين($this->_items });
الوظيفة العامة الحالية () {إرجاع التيار($this->_items });
مفتاح الوظيفة العامة () {مفتاح الإرجاع($this->_items });
الوظيفة العامة التالية() { العودة التالية($this->_items });
الوظيفة العامة صالحة () {return ( $this->current()!== false });
}
فئة DBConfiguration تمتد التكوين {
...
}
$c = new DBConfiguration();
foreach( $c as $k => $v ) { echo( $k." = ".$v."n" });
?>
تتيح واجهة Iterator لأي فئة أن تظهر وكأنها مجموعة من عملائها. كما ترون في نهاية البرنامج النصي، يمكنك استخدام عامل التشغيل foreach لتكرار كافة عناصر التكوين في كائن التكوين. لا يحتوي PHP V4 على هذه الوظيفة، ولكن يمكنك استخدام هذه الوظيفة بطرق مختلفة داخل التطبيق الخاص بك.
وتتمثل ميزة آلية الواجهة في إمكانية تجميع العقود معًا بسرعة دون الحاجة إلى تنفيذ أي طرق. المرحلة النهائية هي تنفيذ الواجهة، حيث يجب عليك تنفيذ جميع الطرق المحددة. ميزة جديدة مفيدة أخرى في PHP V5 هي الفئات المجردة، والتي تجعل من السهل تنفيذ الجزء الأساسي من الواجهة باستخدام فئة أساسية ثم استخدام تلك الواجهة لإنشاء فئات الكيانات.
الاستخدام الآخر للفئات المجردة هو إنشاء فئة أساسية لفئات مشتقة متعددة لا يتم فيها إنشاء مثيل للفئة الأساسية مطلقًا. على سبيل المثال، عند وجود DBConfiguration وConfiguration في نفس الوقت، يمكن استخدام DBConfiguration فقط. فئة التكوين هي مجرد فئة أساسية - فئة مجردة. لذلك، يمكنك فرض هذا السلوك باستخدام الكلمة الأساسية المجردة كما هو موضح أدناه.
القائمة 9. Abstract.php5
<?php
تكوين فئة مجردة
{
محمية $_items = array();
وظيفة عامة __construct() {
$هذا->تحميل();
}
تحميل وظيفة محمية مجردة () ؛
الحصول على الوظيفة العامة (مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
تعمل فئة DBConfiguration على توسيع التكوين
{
تحميل الوظيفة المحمية () {
$this->_items[ 'imgpath' ] = 'images';
}
}
$c = new DBConfiguration();
echo( $c->get( 'imgpath' )."n" );
?>
الآن، كل محاولات إنشاء كائن من النوع Configuration ستحدث خطأ لأن النظام يعتبر الفئة مجردة وغير كاملة.
الأساليب والأعضاء الثابتة
ميزة جديدة مهمة أخرى في PHP V5 هي دعم الأعضاء والأساليب الثابتة في الفئات. باستخدام هذه الوظيفة، يمكنك استخدام النمط المفرد الشائع. يعد هذا النمط مثاليًا لفئة التكوين لأن التطبيق يجب أن يحتوي على كائن تكوين واحد فقط.
تعرض القائمة 10 إصدار PHP V5 لفئة التكوين كنسخة مفردة.
القائمة 10. static.php5
<?php
تكوين الطبقة
{
خاص $_items = array();
static Private $_instance = null;
الحصول على وظيفة عامة ثابتة () {
إذا (الذات::$_instance == فارغة)
self::$_instance = new Configuration();
إرجاع الذات::$_instance;
}
وظيفة خاصة __construct() {
$this->_items[ 'imgpath' ] = 'images';
}
الوظيفة العامة __get(مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
echo( Configuration::get()->{ 'imgpath' }."n" );
?>
الكلمة الأساسية الثابتة لها العديد من الاستخدامات. فكر في استخدام هذه الكلمة الأساسية عندما تحتاج إلى الوصول إلى بعض البيانات العامة لجميع الكائنات من نوع واحد.
الطريقة السحرية
ميزة جديدة كبيرة أخرى في PHP V5 وهي دعم الأساليب السحرية، والتي تسمح للكائنات بتغيير واجهة الكائن بسرعة - على سبيل المثال، إضافة متغيرات الأعضاء لكل عنصر تكوين في كائن التكوين. ليست هناك حاجة لاستخدام طريقة get()، ما عليك سوى البحث عن عنصر معين ومعاملته كمصفوفة، كما هو موضح أدناه.
القائمة 11.magic.php5
<?php
تكوين الطبقة
{
خاص $_items = array();
وظيفة __construct() {
$this->_items[ 'imgpath' ] = 'images';
}
وظيفة __الحصول على(مفتاح $) {
إرجاع $this->_items[ $key ];
}
}
$c = التكوين الجديد();
echo( $c->{ 'imgpath' }."n" );
?>
في هذا المثال، قمت بإنشاء طريقة __get() جديدة يتم استدعاؤها عندما يبحث المستخدم عن متغير عضو في الكائن. سيستخدم الكود الموجود داخل الطريقة مصفوفة العناصر للعثور على القيمة وإرجاع تلك القيمة كما لو كان هناك متغير عضو هناك خصيصًا لتلك الكلمة الرئيسية. بافتراض أن الكائن عبارة عن مصفوفة، يمكنك أن ترى في نهاية البرنامج النصي أن استخدام كائن التكوين أمر بسيط مثل العثور على قيمة imgpath.
عند الترحيل من PHP V4 إلى PHP V5، يجب أن تكون على دراية بميزات اللغة هذه غير المتوفرة تمامًا في PHP V4، ويجب عليك إعادة التحقق من صحة الفئات لمعرفة كيفية استخدامها.
الاستثناءات
هذه المقالة أخيرًا من خلال تقديم آلية الاستثناء الجديدة في PHP V5. توفر الاستثناءات طريقة جديدة تمامًا للتفكير في معالجة الأخطاء. جميع البرامج تؤدي حتماً إلى حدوث أخطاء - لم يتم العثور على الملف، أو نفاد الذاكرة، وما إلى ذلك. إذا لم يتم استخدام الاستثناءات، فيجب إرجاع رمز الخطأ. يرجى إلقاء نظرة على كود PHP V4 أدناه.
القائمة 12. file.php4
<?php
الدالة parseLine($l)
{
// ...
صفيف الإرجاع ("خطأ" => 0،
البيانات => المصفوفة () // البيانات هنا
);
}
وظيفة قراءة التكوين( $path )
{
إذا كان ($path == null) يُرجع -1؛
$fh = fopen( $path, 'r' );
if ( $fh == null ) return -2;
while( !feof( $fh ) ) {
$l = fgets( $fh );
$ec = parseLine( $l );
if ( $ec['error'] != 0 ) return $ec['error'];
}
فكلوز( $fh );
العودة 0؛
}
$e = readConfig( 'myconfig.txt' );
إذا ($e != 0)
echo("حدث خطأ ("".$e.")n");
?>
سيقوم رمز الإدخال/الإخراج القياسي للملف بقراءة الملف واسترداد بعض البيانات وإرجاع رمز خطأ في حالة مواجهة أي أخطاء. لدي سؤالين حول هذا السيناريو. الأول هو رمز الخطأ. ماذا تعني رموز الخطأ هذه؟ لمعرفة ما تعنيه رموز الخطأ هذه، يجب عليك إنشاء نظام آخر لتعيين رموز الأخطاء هذه في سلاسل ذات معنى. المشكلة الثانية هي أن نتيجة إرجاع parseLine معقدة للغاية. أنا فقط بحاجة إليها لإرجاع البيانات، ولكن في الواقع يجب عليها إرجاع رمز الخطأ والبيانات. غالبًا ما يتكاسل معظم المهندسين (وأنا منهم) ويعيدون البيانات ويتجاهلون الأخطاء لأنه من الصعب إدارة الأخطاء.
توضح القائمة 13 مدى وضوح الكود عند استخدام الاستثناءات.
القائمة 13. file.php5
<?php
الدالة parseLine($l)
{
// التحليل والرمي والاستثناء عندما يكون غير صالح
إرجاع المصفوفة () ؛ // البيانات
}
وظيفة قراءة التكوين( $path )
{
إذا (مسار $ == فارغ)
طرح استثناء جديد ("وسيطة سيئة" );
$fh = fopen( $path, 'r' );
إذا ($fh == فارغ)
طرح استثناء جديد( "تعذر فتح الملف");
while( !feof( $fh ) ) {
$l = fgets( $fh );
$ec = parseLine( $l );
}
فكلوز( $fh );
}
يحاول {
قراءة التكوين( 'myconfig.txt' );
} التقاط (استثناء $e) {
صدى($e);
}
?>
لا داعي للقلق بشأن رموز الخطأ لأن الاستثناء يحتوي على نص وصفي للخطأ. لا يتعين علي أيضًا التفكير في كيفية تعقب رمز الخطأ الذي تم إرجاعه من parseLine لأن الوظيفة ستلقي خطأً في حالة حدوثه. يمتد المكدس إلى أقرب كتلة محاولة/التقاط، الموجودة في الجزء السفلي من البرنامج النصي.
ستحدث الاستثناءات ثورة في طريقة كتابة التعليمات البرمجية. بدلاً من إدارة مشكلة رموز الأخطاء والتعيينات، يمكنك التركيز على الأخطاء التي تريد معالجتها. من السهل قراءة مثل هذه التعليمات البرمجية وصيانتها، وأود أن أقول إنني أشجعك على إضافة معالجة الأخطاء، لأنها عادةً ما تؤتي ثمارها.
الاستنتاج
توفر الميزات الجديدة الموجهة للكائنات وإضافة معالجة الاستثناءات أسبابًا قوية لترحيل التعليمات البرمجية من PHP V4 إلى PHP V5. كما ترون، عملية الترقية ليست صعبة. يبدو بناء الجملة الذي يمتد إلى PHP V5 تمامًا مثل PHP. نعم، تأتي تركيبات الجملة هذه من لغات مثل روبي، لكنني أعتقد أنها تعمل معًا بشكل جيد جدًا. وتعمل هذه اللغات على توسيع نطاق PHP من لغة برمجة نصية للمواقع الصغيرة إلى لغة يمكن استخدامها لإكمال التطبيقات على مستوى المؤسسة.