Archive for category php

الميزات الجديدة للبرمجة غرضية التوجه المدعومة في الإصدار php5 الحلقة الأولى

السلام عليكم ورحمة الله وبركاته

إليكم فيما يلي ترجمتي لمقالة رهيبة تتحدث عن ميزات اللغة الجديدة في الإصدار الخامس من php  ,لقد رأيت هذه المقالة رائعة بل أكثر من رائعة واستفدت منها كثيرا , وهي تتحدث عن البرمجة غرضية التوجه , وتطبيقها فعليا في الإصدار الخامس من لغة php 5  , وقد استفدت منن هذه المقالة , لذلك احببت أن تشاركوني الفائدة منها , قد قمت بتجزئها على حلقات نظراً لطول الموضوع ولضيق وقتي راجية لكم الإستفادة , وأن تقوموا عبر تعليقاتكم الكريمة بالمساهمة في إغناء الموضوع , أو الإشارة إلى النواحي التي تحتاج إلى شرح مفصل أكثر حتى نصل عبر نقدكم البناء إلى عموم الفائدة للجميع .

لن أطيل عليكم بالمقدمة وإليكم التفاصيل

مقدمة :

فقط مع الوقت سوف تدرك بأن php5  أفضل بكثير من الإصدارات السابقة لها.

إن كل من الميزات والتغيرات الجديدة المحدثة على الإصدار الجديد ل php5  كلها تهدف إلى التخلص من نقط الضعف التي كانت موجودة سابقاً في الإصدارات السابقة.وبذلك نسعى دوما أن تكون لغة php دوماً في الصدارة بالنسبة للغات الويب بشكل عام.

تغطي هذه المقالة كل من php5  والميزات الجديدة المدرجة فيها بشكل مسهب وموسع, بالنسبة لأولئك الأشخاص المعتادين على الإصدار السابق php4  , ومتشوقون لمعرفة الجديد في php5 فإن هذا الجزء مخصصاً لهم.

سوف يغطي هذا الجزء كل من ا لنقاط التالية:

  • الميزات الجديدة المدرجة في اللغة
  • التمديدات المهمة المضافة إلى php – new concerning php extensions
  • بعض التغيرات الطفيفة التي تم إجرائها في الإصدار الجديد ولم تكن موجودة في الإصدار القديم.

ميزات اللغة

النموذج غرضي التوجه new object oriented model

لقد تم فعليا من الإصدارات السابقة وتحديداً من php3 إضافة مفاهيم البرمجة غرضية التوجه إلى اللغة لكنها لم تكن مدعومة بشكل جيد .

وبالرغم من أن النموذج غرضي التوجه في ذلك الوقت كان يملك كثير من المحدوديات , إلا أنه قد تم استخدامه بشكل واسع وعلى نطاق واسع في العالم.

إن هذا الاستخدام الواسع النطاق  للبرمجة غرضية التوجه الموجودة في php4  بالرغم من ضعفها جعلها من أهم النقاط التي وجب التركيز عليها في الإصدار الحديث من php  أي في  php5.

من أهم نقاط الضغف التي كانت موجودة في النموذج القديم غرضي التوجه تكمن فيمايلي :

عندما نشير إلى غرض ما كانت علمية نسخ كاملة لهذا الغرض تتم في الخلف , مما يؤدي بشكل أو بآخر إلى إضعاف الأداء بالإضافة إلى حدوث عدد من الأخطاء الخفية التي كانت تتم في التطبيق, لأن بهذا السلوك فإن عدد من المطورين يعتقدون بأنهم يشيرون إلى نفس الغرض , لكن فعليا على أرض الواقع ليست هذه هي الحالة. لأنهم فعليا يشيرون إلى عدة نسخ من نفس الغرض, وتغيير أحداها لن يغير الأخرى.

على سبيل المثال :

في الإصدار الرابع من php  ستكون النتيجة Andi . وذلك لأننا قد مررنا الغرض بالقيمة وليس بالمرجع ( عبر التابع changeName() ) , ولذلك فعليا سيتم نسخ نسخة مستقلة من ا لغرض والعمل عليها , وبالتالي فإن تأثير ا لتابع سيكون محصور فقط على نسخة من الغرض $person.

حيث أن السلوك المتبع فعليا في اللغة ليس سلوكاً بديهياً مثلما يتوقع أغلب المبرمجين الذين يتبعون أسلوب البرمجة غرضية التوجه – مثل مبرمجي جافا- حيث أنه في جافا يتم فعليا رصد مرجع – مؤشر – إلى ذلك الغرض , ولذلك فعندما يتم نسخه فإن المؤشر فقط هو الذي سيتم نسخه.

هنالك عدد من مستخدمي لغة البرمجة php 4  الذين كانوا مدركين لواقع هذه المشكلة ومتنبهين لها , ولكن كان في المقابل عدد اخر من المبرمجين غير منتبهين لهذه المشكلة  فتسببت لهم بالكثير من الارهاق وهم يحاولون البحث عن الأخطاء في زمازهم تلك الاخطاء التي لم يكونوا يعرفون مصدرها , وفي الواقع مصدرها كان تلك الثغرة في php 4

أما في php 5  فقد تمت عملية إعادة كتابة البنية التحتية للنموذج الغرضي ليتعامل مع مقابض الأغراض object handles  . أي اصبحنا نتعامل مع الأغراض باستخدام مؤشرات تشير اليها دون الحاجة إلى نسخ الغرض بشكل كامل من أجل العمل عليه , باستثناء الحالة التي نقوم بها بصراحة باستخدام الكلمة المفتاحية clone  التي نحصل بنتيجتها وباتباع عمليات معينة على نسخة مستقلة عن الغرض الأصلي الذي نتعامل معه.

في php 5  لا توجد حاجة إلى تمرير الأغراض بالمرجع أ و إسنادهم بالمرجع.

ملاحظة:

لا تزال كل من عمليتي إسناد الأغراض بالمرجع أو تمريرهم بالمرجع مدعومة في php 5  وذلك في الحالة التي ترغب فيها فعلياً بتغير محتوى المتحول ( سواء كان غرض أو نمط).

بعض الميزات الغرضية التوجه الجديدة.

إن عدد الميزات غرضية التوجه الجديدة التي تم إضافتها واسع جداً , لذلك فيما يلي سنقوم فقط بتعداد قائمة بالميزات الأساسية الجديدة فقط :

1 : معدلات النفاذ public / private /protected   بالمستخدمة بالنسبة لكل من الطرائق methods  والخواص properties .

مثال

2 : الباني __construct()

فبدلاً من أن يكون اسم الباني هو نفسه اسم الصف , فيجب التصريح عنه الآن بالكلمة __construct() ,

3: دعم تعريف عملية هدم الغرض عبر تعريف طريقة الهادم __destructor() method

تمكننا من تعريف الهادم الذي يعمل عندما يتم تهديم الغرض

4: الواجهات interfaces

مما يمكن الصف من تحقيق أكثر من علاقة واحدة من نمط is_a  .

حيث أن الصف يستطيع أن يرث من صف واحد فقط , ولكنه يستطيع أن يقوم بتحقيق implement  أكثر من واجهة واحدة.

5: عملية نسخة من instnaceof operator :

إن مستوى اللغة هنا يمكننا من القيام بالتحقق من العلاقات التي من النمط is_a   . حيث أن التابع  is_a() الذي كان مستخدما في php 4  قد تم شجبه الآن لتحل العملية التالية بداله:

وبهدا القدر ننهي الحلقة الأولى على أن نتابع لاحقا إن شاء الله

وإلى ذلك الحين نستودعكم الله والسلام عليكم ورحمة الله وبركاته

Advertisements

, , , ,

أضف تعليق

البرمجة غرضية التوجه مع php و mysql

 

السلام عليكم ورحمة الله وبركاته

عملياً وبشكل أساسي أستخدم البرمجة غرضية التوجه أثناء برمجتي لمواقع الوب , فإذا ما اطلعتم على الكود البرمجي الخاص بأحد المواقع التي برمجتها لوجتموه بشكل أساسي مؤلف من مجموعة من الصفوف الخاصة بالتعامل مع الكتل الأساسية في الموقع , وقبل عدة أيام كنت أبحث عن بعض المواضيع المتقدمة في البرمجة غرضية التوجه وبشكل خاص بالنسبة ل php  , فوقعت يداي على بعض المواقع الرائعة التي تتحدث عن هذا الموضوع وتطبقه بشكل فعلي , وقد قمت بقرائتها بشكل مفصل وأعجبتني كثيراً , وجعلتني أغير كودي البرمجي الذي استخدمه في العادة بنسبة 80% ووفرت علي الكثير من الوقت والجهد, لذا فقد ارتأيت بأنه من واجبي أن أترجم لكم هذه المواضيع التي قرأتها , عسى ولعل أن يستفيد منها أحد غيري.

الموضوع السابق كان يتحدث عن البرمجة غرضية التوجه المتقدمة في php  , أما الموضوع الحالي فيتحدث عن تطبيق هام جداً يخدم البرمجة غرضية التوجه في التعامل مع قاعدة المعطيات mysql , وقد قمت فعليا في برامجي بالاستفادة من الافكار المطروحة في المقالتين عبر الدمج بينهما.

لن أطيل عليكم في المقدمة وسأبدأ بطرح المقالة التي قمت بترجمتها وصياغتها , مع خالص تمنياتي لكم بالفائدة.

 

المقالة:

هنالك على الوب الكثير من المقالات التي تتحدث عن البرمجة غرضية التوجه وتطرح الكثير من الأمثلة الشهيرة عليها مثل (مثال الدراجة …وغيره), ولكننا هنا فضلنا أن نشرح البرمجة غرضية التوجه في php   و mysql عبر عدد من الأمثلة التطبيقية الواقعية المفيدة للمبرمج بشكل فعلي ومباشر.

يقوم المثال المفيد الذي سنطرحه بإنشاء صف ذو علاقة بالعمليات الأساسية التي تنفذ على قاعدة المعطيات mysql ويدعى هذا الصف CRUD class (create,read,update,delete) حيث يقوم هذا الصف بتنفيذ عملية الإنشاء والقراءة والتعديل والحذف على مداخل السجلات الموجودة في قاعدة المعطيات, وذلك بغض النظر عن كيفية تصميم قاعدة المعطيات .

كخطوة أولى سنقوم بإنشاء الهيكل الأساسي لهذا الصف , ومن خلاله نستطيع أن نستشف الأمور التي نحتاجها.

في البداية نحن بحاجة للتأكد من قدرتنا على تنفيذ التوابع الأساسية في mysql . وحتى نستطيع القيام بذلك , نحتاج إلى كل من التوابع التالية:

 وإليكم الشكل العام للصف الذي يقوم بتنجيز- تحقيق – كل من هذه التوابع الأساسية:

selInserD

لاحظوا بأنني حرصت على أن تسبق هذه التوابع المعرفة بالكلمة المفتاحية public

dbclass

التابع function connect()

يعتبر هذا التابع بمثابة تابع function أساسي , وعملية تنجيزه – تحققه- ستكون بسيطة وسهلة , لكن في البداية نحن بحاجة إلى إنشاء وتعريف عدد من المتحولات variables. وحتى نضمن بأن لا يتم النفاذ لهذه المتحولات من خارج هذا الصف class, سنقوم بإسباق كل من هذه المتحولات بمعرف النفاذ private  وبذلك نضمن بأن فضاء رؤية هذه المتحولات أصبح محصوراً ضمن فضاء الصف الذي نقوم بتعريفه.

ستستخدم هذه المتحولات من أجل حفظ قيم كل من : المضيف host, اسم المستخدم username, كلمة المرور password, وقاعدة المعطيات database , هذه المعلومات المستخدمة بشكل أساسي من أجل إنشاء الإتصال مع قاعدة المعطيات.

وبما أن المتحولات السابقة , عملياً لا تتغير قيمها ,فنحن لسنا بحاجة إلى إنشاء توابع معدلة لقيم هذه المتحولات سابقة الذكر.

ومن ثم نحن بحاجة فقط إلى إنشاء عبارة اتصال بسيطة بلغة تقوم بربطنا مع قاعدة المعطيات mysql .

وبسبب طبيعتنا كمبرمجين , فنحن نفضل التحقق من كل شيء – أحياناً تكون بعض التحققات سخيفة ولكن مع ذلك نقوم بها- فمثلاً في بداية تنجيز تابع الاتصال سنقوم بالتحقق من أن الاتصال قد تم إنشاءه من قبل أم لا , حيث عندها لا يكون هنالك داعي لإعادة إنشاء الاتصال مرة أخرى , وإلا سنقوم بإنشاء الاتصال مع قاعدة المعطيات.

 connect  

 وكما نر فإنه يستخدم بعض التوابع الأساسية الخاصة ب mysql , وبعض الكود الخاص بالتحقق من الخطأ , من أجل التأكد بأن كل شيء يسير على مايرام وفق الخطة المرسومة.

في حال تم الاتصال بقاعدة المعطيات , فسيعيد التابع (تابع الاتصال ) القيمة المنطقية true  وإلا false .

وكنقطة إضافة سيقوم بتغير قيمة متحول الاتصال إلى القيمة true  في حال نجاح الاتصال.

 تابع فصل الاتصال public function disconnect()

يقوم هذا التابع ببساطة باختبار متحول الاتصال للتحقق من كونه يحمل القيمة المنطقية true وبالتالي بأن هذا يعني بأن الاتصال قائم مع قاعدة المعطيات , وبالتالي يقوم هذا التابع عندئذ بقطع الاتصال ويعيد القيمة المنطقية true  التي تدل على نجاح عملية قطع الاتصال , وإلا , في حال عدم وجود اتصال على الإطلاق , عندها لا يوجد ما نستطيع القيام به فعلياً.

public function disconnect()   

 disconnect    

تابع الاختيار public function select()

مع هذا التابع سنلاحظ بأن الأمور لن تعود ببساطة تعريفات التوابع السابقة , وستصبح أكثر تعقيداً.

سنتعامل الآن مع معاملات المستخدم التي سيمررها , ونعيد النتيجة بشكل مناسب.

وبما أننا لسنا مضطرين إلى لاستخدام النتيجة بشكل مباشر   , لذلك سنقوم بتعريف متحول يدعى result  يتم تخزين النتيجة فيه .

بالإضافة لما سبق , سنقوم بتعريف تابع يقوم بالتحقق من وجود جدول معين في قاعدة المعطيات أم لا . وبما أن أغلب التوابع المعرفة ضمن هذا الصف ستقوم باستخدام هذا التابع , لذلك سنقوم بإنشاءه بشكل مستقل , بدلا من وضعه ضمن أحد التوابع المعرفة , بهذه الطريقة نكون ضربنا أكثر من عصفور بحجر واحد – إن جازالتعبير – حيث نكون قد وفرنا الكثير من إعادة كتابة الرماز – الكود – وسيكون بإمكاننا أمثلة الأمور بشكل أفضل لاحقاً.

سنعرض فيما يلي الكود – الرماز – الخاص بتعريف المتحول الخاص بالنتيجة , بالإضافة إلى الكود الخاص بتعريف تابع التحقق من تواجد جدول ما في قاعدة المعطيات

 table exists  

ببساطة يقوم هذا التابع بالتحقق من قاعدة المعطيات والتأكد من تواجد الجدول الممرر كمعامل دخل لهذا التابع .ويعيد هذا التابع القيمة المنطقية true  في حال تواجد الجدول , وإلا فإنه سيعيد القيمة المنطقية false .

select

للوهلة الأولى يبدو تعريف تابع الاختيار select function  مخيفاً قليلاً, ولكن عملياً , وإذا أمعنا النظر في الرماز , سنلاحظ بأنه بسيط , ويقوم بعدد من الخطوات . في البداية يتقبل هذا التابع 4 معاملات دخل  , الأول منهم مطلوب ولا يوجد له قيمة افتراضية , أم البقية فيوجد لهم قيم افتراضية . المعامل الأول , يمثل أسم الجدول. أما معامل rows فيحدد أسماء الأعمدة التي نريد احضارها من الجدول ضمن استعلامنا , أما المعامل where  فيفيد في وضع بعض الشروط على الاستعلام المطلوب تنفيذه على قاعدة المعطيات .

وكما هو واضح من الرماز , فقبل تنفيذ الاستعلام على قاعدة المعطيات , يتم التحقق من تواجد الجدول – المعامل الأول الممرر لهذه الاجرائية – في قاعدة المعطيات . في حال تواجده , عندها يتم تنفيذ الاستعلام , وإلا فنعيد عندها القيمة المنطقية false  التي تدل على الفشل.

أما القسم الثاني , فيمثل جزء من سحر البرمجة , حيث يقوم بجمع المعطيات والأعمدة التي تم طلبها من قاعدة المعطيات . ومن ثم يقوم بإسنادها لمتحول النتيجة الذي قمنا بتعريفه سابقاً. وحتى نسهل النتيجة على المستخدم , فقد تمت الاستفادة من أسماء الأعمدة الفعلية في تخزين النتائج في متحول النتائج , وذلك عوضاً عن استخدام العدادات.

في حال حصولك على أكثر من سجل – سطر-  نتيجة الاستعلام , عندها سيتم تخزين النتيجة في مصفوفة ثنائية الأبعاد, حيث يمثل المفتاح الأول فيها ترقيم لسطر النتيجة , والمفتاح الثاني يمثل اسم العمود.

أما في حال كانت النتيجة عبارة عن سجل وحيد – سطر واحد – عندها يقوم التابع بإعادة مصفوفة أحادية البعد (شعاع) تكون المفاتيح فيه عبارة عن أسماء أعمدة الجدول المطلوبة.

أما في حال عدم وجود أي نتيجة , عندها تسند القيمة الخالية null   إلى متحول النتيجة.

وأعود وأكرر مرة أخرى , بإنه التابع للوهلة الأولى يبدو مضللاً , ولكن ما إن نحلله لأجزاء ومقاطع بسيطة , يصبح عندها بإمكاننا فهم آلية عمله البسيطة وتصبح أمامنا سهلة جداً.

تابع الإضافة في قاعدة المعطيات public function insert()

هذا التابع أبسط بكثير من التابع المعرف سابقاً. وهو ببساطة يمكننا من إضافة المعلومات – السجلات – إلى قاعدة المعطيات.

بالنسبة لمعاملات الدخل الممررة , فإننا بالإضافة إلى اسم الجدول , نحن بحاجة إلى تمرير القيم المراد إدخالها إلى الجدول . بإمكاننا ببساطة فصل قيمة عن القيمة الأخرى عبر استخدام الفاصلة . ومن ثم كالعادة فحتى ننفذ الاستعلام , نحن بحاجة في البداية إلى التحقق من تواجد الجدول فعلياً في قاعدة المعطيات , ومن ثم نقوم بإنشاء وبناء الاستعلام المطلوب عبر تنظيم المعاملات الممررة في دخل هذا التابع لتشكل صيغة استعلام نظامية , ومن ثم ننفذ الاستعلام.

insert  

وكما تر, فإن هذا التابع اسهل بكثير من التابع المسؤول عن إنشاء تعليمة select .

كما أن التابع الذي يقوم بعملية الحذف من قاعدة المعطيات أسهل بكثير من كل ماسبق.

تابع الحذف من قاعدة المعطيات public function delete()

يقوم هذا التابع ببساطة إما بحذف كل سطور الجدول من قاعدة المعطيات , أو يقوم بحذف سطور محددة.

وكما اعتدنا سابقاً , فإننا نمرر اسم الجدول , وعبارة where وكما هو واضح فهي اختيارية.

إن عبارة where تمكننا من تحديد الأسطر التي نرغب في حذفها من الجدول ككل. في حال تمرير عبارة where , فإن كل السطور التي تحقق الشروط  المحددة في عبارة where يتم حذفها من قاعدة المعطيات. ومن ثم لا يتبق علينا سوى تنفيذ عبارة الحذف .

delete 

وأخيراً , وصلنا الآن إلى أخر تابع في جعبتنا.

تابع التعديل public update function

هذا التابع ببساطة يقوم بتعديل سطر – أو سطور – في قاعدة المعطيات بالمعلومات الجديدة الممررة له.

على كل الأحوال, بسبب طبيعة تعريف هذا التابع التي تحوي القليل من التعقيد , لذلك سيكون سرده أطول قليلاً , ومربك قليلاً.

ولكنه بالنهاية يملك الكثير من الأعراف المستخدمة في تعريف التوابع السابقة.في البداية , سنقوم باستخدام المعاملات الممررة لهذه الإجرائية بهدف تشكيل عبارة التعديل المطلوبة update statement.

وكما اعتدنا في تعريف التوابع السابقة , فإننا في البداية نتحقق من تواجد الجدول أصلاً في قاعدة المعطيات. في حال تواجده سنقوم عندها ببساطة بتعديل السطور المطلوبة . يكمن الجزء الأصعب ,في إنشاء عبارة التعديل المطلوبة وصياغتها بالشكل السليم .

عبارة where ببساطة تحوي على الشروط التي تحدد السطور التي من المطلوب إجراء التعديلات عليها.

سيقوم المقطع التالي بإنشاء الجزء من عبارة التعديل الذي يتعامل مع توضيع القيم المراد تعديلها في مكانها المناسب.

حيث تحوي المصفوفة $rows على القيم الجديدة , وبنية المصفوفة $rows هي على الشكل التالي : الأدلة فيها تمثل أسماء الأعمدة المراد تعديلها , أما القيم فتمثل القيم الجديدة لتلك الأعمدة الموافقة لها.

والرماز أدناه يوضح آلية صياغة جزء من عبارة التعديل , حيث يتم وضع الفواصل في الأماكن المناسبة لها.

getkeys

وسنعرض الآن التابع الذي يقوم بعملية التعديل بشكل كامل:   

 update

والآن وبعد أن انتهينا من تعريف آخر تابع , أصبح الصف الخاص بالعمليات الأساسية على قاعدة المعطيات مكتملاً الآن , وأصبح بإمكانك اعادة استخدامه أكثر من مرة وبذلك توفر الكثير من الوقت والرماز.وهنا تكمن روعة وسحر البرمجة غرضية التوجه.

وفي الختام , أتمنى للجميع الفائدة , وفي حال وجود أي تساؤلات عن الموضوع أرجو ألا تترددوا في طرحها حتى نناقشها سوية .

وإلى أن ألقاكم قريباً , استودعكم الله والسلام عليكم ورحمة الله وبركاته.

 

المرجع

http://net.tutsplus.com/tutorials/php/real-world-oop-with-php-and-mysql/

, ,

تعليق واحد

البرمجة غرضية التوجه المتقدمة في php

البرمجة غرضية التوجه المتقدمة في php

 

السلام عليكم ورحمة الله وبركاته

كثيراً ما نبحر بعيداً عن شطئاننا وأراضينا وقٌرانا , بحثاً عن عالم جديد وأفكار جديدة وأفق آخر , وقد تطول غربتنا عن أرضنا التي نعشق , ولكننا في النهاية نجد أنفسنا رهيني شوقنا لتلك الأرض , ولم نعد نطيق الابتعاد عنها أكثر من ذلك .

تمر بنا أحيان كثيرة ننكر فيها رغبتنا في العودة …ونتحدى أنفسنا ولهفتنا لذلك , ونكابر ونراهن على ذلك …في تلك اللحظات – التي قد تكون مصطنعة أو حالة راهنة واقعية – نعتقد بأن ما نقوله هو الذي سيتم فعليا ً. ولكن ما إن ينبض الشوق الحقيقي في عروقنا , حتى نجد أنفسنا تحترق بحرارة الشوق …شوق العودة , وتكسر كل القوانين والضوابط التي وضعتها سابقاً تحسباً من هكذا مرحلة ….

وهذا هو حالي مع تدوينتي هذه , فقد تأخذني فورة الحياة , وروتين العمل , وضيق الوقت بعيداً عن مدونتي التي أحب , ولكن ما ألبث أن أعود إليها وكلي شوق وحنين لأن أغنيها بما هو جديد , وبالأشياء التي علمتني إياها الحياة ,عسى ولعل أن يستفيد منها أحد آخر.

أما الآن , وبعد هذه المقدمة التي أستمتع دوماً بكتابتها في مقدمة أي موضوع , سنباشر الآن رحلتنا الممتعة في مجال البرمجة غرضية التوجه المتقدمة  و php  …

 

البرمجة غرضية التوجه مع مكتبة php  النظامية  SPL (standered php library )في الإصدار الخامس من php  

مقدمة :

تغطي هذه المقالة كل التوسعات المضافة إلى البرمجة غرضية التوجه في الإصدار الخامس من PHP بما فيها من SPL (مكتبة php  النظامية Standard PHP Library ) وكيفية استخدامهم في تطبيقاتنا الفعلية, وذلك حتى لا يبق الموضوع قيد الدراسة النظرية.

ملاحظة :

حتى تستطيع الاستفادة من قراءة هذه المقالة , يجب أن يكون لديك فكرة عن الصفوف classes, والواجهات interfaces , والأعضاء السكونين –الثابتين – static members , والمراجع references. أي باختصار يجب أن يكون لديك فكرة بشكل عام عن مفاهيم البرمجة غرضية التوجه.

كما يتوجب أن يكون لديك فكرة وفهم عن بعض قوالب التصميم الأساسية basic design patterns مثل قالب المعمل Factory.

سيتم استعراض هذه المفاهيم وشرحها من خلال استخدام طبقة قاعدة المعطيات المفاهيمية conceptual database layer.

 

غالباُ في برمجة تطبيقات الوب , يكون هنالك ميل كبير ونزعة لدى المبرمجين لكتابة وبرمجة طبقة مجردة ومنفصلة خاصة بقاعدة المعطيات , وذلك لأهداف تتعلق بسهولة نقل البرنامج – تطبيق الوب – من بيئة لأخرى database portability , وكمثال عليها PEAR::DB abstraction.

ولكن لسوء الحظ , فإن لا يمكن كتابة كود عام يتعامل مع كل قواعد المعطيات , وبالتالي فهو سيكون موافقاً للعمل مع قاعدة معطيات وحيدة .

والسؤال هنا هو التالي:

كيف بإمكاننا التخلص من هذه المحدودية ؟

الجواب يكمن في استخدام القوة التي يقدمها لنا الإصدار الخامس من PHP بما فيه من الواجهات والمكتبة النظامية الخاصة ب PHP Interfaces and SPL , التي تزودنا بقدر عالي من الأداء الأمثلي , وتمكننا من التمتع بخاصية توافق رمازنا – الكود – مع البيئات المختلفة portability (المحمولية) , وبذلك يصبح بإمكاننا- مع إجراء بعض التعديلات البسيطة – تشغيل تطبيقاتنا على قواعد معطيات مختلفة.

الواجهات في PHP5 PHP5 Interfaces in 

مع وجود عدد من الابتكارات المترافقة في PHP5 و SPL ( مكتبة PHP النظامية),أصبح الآن بإمكانك استخدام المفاهيم المتقدمة للبرمجة غرضية التوجه, مثل الصفوف classes, الواجهات interfaces, والدلائل indexers, والعدادات iterators, بطريقة لم تكن تحلم بها من قبل , ولم تكن متاحة أصلاً.

إن SPL ( اختصار لمكتبة PHP النظامية Standard PHP Library) هي بمثابة تمديد ل php , حيث تضيف لنواة php كل من الواجهات interfaces والصفوف classes والتوابع functions.

إن كل من التمديدات التي تم ذكرها , ولحد هذه اللحظة , لا تزال غير موثقة بشكل جيد , ولذلك سأحاول شرح استخدام الواجهات الثلاث الموجودة في  SPL والتي نحن بحاجة لاستخدامها حتى ننهي هذا المشروع.

الواجهات الثلاث هي التالية:

The ArrayAccess interface

The Countable interface

The Iterator interface

وسنبدأ ب

The ArrayAccess interface 

عندما تم تنجيز implement هذه الواجهة , فقد تم تمكين المبرمجين من استخدام الدلائل indexers عليها (أي استخدام عمليات دليل المصفوفة [])وذلك بالنسبة لأي غرض لا على التعينن ( أي بإمكاننا النظر إليها على أنها مصفوفة وعناصرها هي الأغرض وبالتالي بإمكاننا الوصول إلى هذه الأغراض عبر اسخدام العمليات المتاحة على الأدلة index operators []).

كل الأغراض المفهرسة indexed objects  في PHP تحتاج بشكل أساسي إلى 4 طرائق methods  حتى تستطيع التعامل معها كمصفوفة , ويجب أن تصرح على أنها تحقق الواجهة ArrayAccess (implement the ArrayAccess interface).

الطرائق الأربع التي يحتاجها كل غرض مفهرس هي التالية:

offsetExists($offset)

تستخدم هذه الطريقة لأخبار php عن وجود قيمة value   (أو عدم وجودها )بالنسبة للمفتاح key  المحدد عبر الإزاحة المعطاة والممرة كعنصر دخل لهذه الطريقة ($offset)

القيمة المرجعة من هذه الطريقة هي إما القيمة المنطقية true أو false.

offsetGet($offset)
تستخدم هذه الطريقة لإعادة القيمة value  المحددة عبر المعامل –المفتاح key – الممر كدخل لهذه الطريقة offset.

offsetSet($offset, $value)

تقوم هذه الطريقة بتوضيع القيمة value  الممرره كمعامل دخل لهذه الطريقة ضمن الغرض وذلك في المكان المحدد لها عبر المفتاح offset  الممرر أيضاً كمعامل دخل .

بالإمكان إطلاق استثناء من هذه الطريقة في حال كانت هذه المجموعة للقراءة فقط read-only collection, وبالتالي ليس بإمكانك تعديلها بكتابة قيم جديدة فيها.

offsetUnset($offset)
تستخدم هذه الطريقة في الحالات التي يتم فيها إزالة قيمة من المصفوفة , إما عن طريق unset() أو  عبر إسناد قيمة اللاشيء value of null إلى المفتاح key الخاص بقيمة ما.

في حالة المصفوفات العددية,لا يتوجب حذف المفتاح منها , ولا يتوجب إعادة فهرسة تلك المصفوفات ,إلا في حال كان ذلك لغاية مدروسة في نفسك.

 The Countable interface

تحاكي هذه الواجهة سلوك التابع الشهير count() , وبذلك تعيد حجم الغرض الذي قمت بتعريفه , وذلك بالاعتماد على الكود الذي ستقوم أنت بكتابته ضمن هذه الطريقة.

تعتمد هذه الواجهة على الإصدار PHP 5.1.

ملاحظة: حتى يقوم الصف الذي عرفته بتحقيق الواجهة Countable يتوجب عليك تعريف طريقة باسم count() تعيد عدد صحيح , ويجب أن يقوم الصف أيضاً بالإشارة بشكل صريح إلى تحقيق الواجهة Countable.

The Iterator interface 

تعتبر العدادات Iterators بمثالة أكثر الأجزاء أهمية في SPL , حيث تمكننا من أستخدام الأغراض ( التي نعرفها )ضمن الحلقات البرمجية loops.

قد تتسائل , لماذا لم تضمن الواجهة Iterator ضمن الواجهة ArrayAccess ؟

يعود السبب في ذلك بسبب عدم توفيرها للآلية مناسبة تخبر فيها PHP عن المفاتيح keys المحتملة وترتيبهم الموافق.

إذا كنت ترغب في الأستفادة من حلقات foreach loop في التعامل مع الأغراض التي قمت بتعريفها , يتوجب عليك القيام بتحقيق الواجهة Iterator. 

حتى تستطيع تحقيق implement الواجهة Iterator , تحتاج إلى كتابة كل من الطرق الخمس التالية:

current()

تعيد هذه الطريقة القيمة الموافقة للدليل الحالي current index’s value

أنت المسؤول الوحيد عن عملية تتبع الدليل الحالي , ولن تقوم الواجهة بتحقيق هذه العملية لك ما لم تعرفها أنت بنفسك.

key()

تقوم هذه الطريقة بإعادة القيمة الموافقةللمفتاح الحالي .

تعتبر هذه الطريقة مهمة جداً بالنسبة لحلقات foreach , حيث يصبح عندها باستطاعتنا الحصول على كل المفاتيح والقيم الحالية  المشار إليها في كل دورة من دورات الحلقة على الغرض الممرر لها.

next()

تقوم هذه الطريقة بتحريك الدليل الداخلي إلى الأمام بمقدار مدخل واحد (إذا نظرنا إلى غرضنا باعتباره عبارة عن سلسلة أو مصفوفة من المداخل المتتالية)

rewind()

تقوم هذه الطريقة بإعادة تهيئة الدليل الداخلي , وتوضيعه ليشير إلى العنصر الأول (المدخل الأول ضمن الغرض).

valid()
تقوم هذه الطريقة بإعادة إحدى القيمتين المنطقيتين true أو false , في حال وجود عنصر في المكان الذي نقف عنده الآن.

تستخدم هذه الطريقة عادة بعد استدعاء إحدا الطريقتين التاليتين rewind() أو next().

تجدر الإشارة إلى أن هنالك عدة أنماط من العدادات iterators التي تقدمها المكتبة النظامية في PHP, ولكننا سنقتصر في مثالنا المطروح على ذكر نمط واحد فقط  ألا وهو  Iterator  ونقوم بتحقيقه implement.

إنشاء وبرمجة أول واجهة خاصة بنا- أي من كودنا الخاص-

حتى تستطيع إنشاء تطبيق محمول portable application , يتوجب عليك في البداية تحديد الآلية التي سيتخاطب عبرها تطبيقك مع قاعدة المعطيات.

في الحل الذي سنطرحه هنا , سنقوم بإنشاء واجهة تؤمن لنا وسيلة تخاطب عامة بالنسبة للتطبيق , أي , مهما كانت قاعدة المعطيات التي تستخدمها , فإن الطرائق المعرفة لدينا ( والهادفة لتحقيق عملية التكامل مع قواعد البيانات المختلفة ) ستقوم بتوحيد واجهة التخاطب دوماً , وبالتالي ستقوم دوماً بأخذ نفس معاملات الدخل (من حيث المفهوم وليس القيمة ), وإعادة نفس القيم.

وكبداية , سنقوم بإنشاء ملف يدعى IDataBaseBindings.php.

ستبدو محتويات هذا الملف مشابهة للكود الموجود أدناه:

 

  

Listing 1 IDataBaseBindings.php
<?php    /**     * IDataBaseBindings interface     *

     * This interface contains the standarized implementation point for all

     * database methods.

     *

     */

 

    interface IDataBaseBindings

    {

        /**

         * getCustomerDetails

         *

         * Returns an UnbufferedAsociativeResultSet containing all

         * detailed information about a user from the userDetails table.

         *

         * @param   int     $userid     A user identification number like 12345

         * @return  UnbufferedAsociativeResultSet    All relevant data from userDetails

         * @throws  ReadOnlyException

         */

        public function getCustomerDetails($userid);

    }

?>

 

 

يقوم الرماز أعلاه بإنشاء واجهة تدعى IDataBaseBindings حيث سيقوم الصف المحقق لها بتعريف الطرائق المذكورة ضمنها .

عبر استخدام واجهة مثل هذه الواجهة , يصبح بإمكانك توفير عدد من الصفوف المختلفة التي تقوم بتحقيق هذه الواجهة , وذلك تبعاً لقاعدة المعطيات المراد استخدامها.

بالنسبة لقواعد معطيات PostgreSQL التي تحقق هذه الواجهة , فإنه بإمكانها استخدام CIDR كنمط معطيات , أما بالنسبة لقواعد معطيات MySQL فإنك ستستخدم القيم البوليانية الرياضية Boolean math من أجل تحديد المعلومات.

كان ذلك مجرد مثال بسيط جداً , ولكن هنالك حالات كثيرة تتطلب منك رفع قدرات قاعدة معطيات معينة لأسباب تتعلق بالإنجاز performance reasons, وبشكل خاص عند التعامل مع الإجرائيات المخزنة stored procedures, أو الإستعلامات المعدة مسبقاً , prepared queries والمعطيات ذات الحجوم الكبيرة .

تحقيق الواجهة IDataBaseBindings التي قمنا بتعريفها سابقاً:

حتى نستطيع القيام بتحقيق الواجهة المعرفة سابقاً , سوف نقوم بإنشاء ملف جديد يدعى PostgreSQL.php. ستبدو محتوياته على الشكل التالي:

 

 

   

Listing 2 PostgreSQL.php

<?php    /**     * PostgreSQL implementer for IDataBaseBindings.     *

     * Implements all members indicated by the interface and

     * optimizes queries for the PostgreSQL database.

     *

     * @author      Kevin McArthur

     * @depends     UnbufferedAssociativeResultSet, IDataBaseBindings

     * @implements  IDataBaseBindings

     */

    class PostgreSQL implements IDataBaseBindings

    {

        public function __construct() {

            // Create Database Connections

        }

 

        /**

         * getCustomerDetails

         *

         * Gets customer data from userDetails specified by userid

         *

         * @see IDatabaseBindings

         */

        public function getCustomerDetails($userid)

        {

            $queryResult = pg_query(‘select * from userDetails where userid = ‘. $userid . ‘;’);

            return new UnbufferedAssociativeResultSet($queryResult);

        }

 

        public function __destruct()

        {

            // Destroy Database Connections

        }

    }

?>

   

يقوم الرماز السابق بإنشاء صف class جديد يدعى PostgreSQL الذي يقوم بدوره بتحقيق implements الطريقة getCustomerDetails() المعرفة سابقاً- بشكل مجرد – ضمن الواجهة IDataBaseBindings التي نقوم بتحقيقها عبر هذا الصف.

يجب أن تكون هذه الطريقة مسؤولة عن القيام بكل الاستعلامات. القيام مباشرةً بوضع واستعادة القيم من قاعدة المعطيات.

إنشاء معمل خاص بقاعدة المعطيات Creating a Database Factory

قد تطرح في نفسك بعض التساؤلات: كيف تكون التعريفات السابقة قد قامت بوضع مفهوم مجرد للواجهة في حال قمنا بإنشاء أغراض جديدة مثل PostgreSQL  بشكل مباشرمنها؟

حتى نحل هذه المشكلة سنقوم باستخدام نموذج المعمل Factory Pattern , والذي يعرف بالشكل التالي:

Listing 3 DatabaseFactory.php
<?php    /**     * DatabaseFactory     *

     * Creates an IDataBaseBindings object for use from the application layer

     *

     * @depends    PostgreSQL, MySQL

     */

    class DatabaseFactory

    {

        /**

         * factory

         *

         * Returns an IDataBaseBindings compatible object based on the type of database

         * defined in $configuration[‘databasetype’]

         */

        public static function factory()

        {

            switch($configuration[‘databasetype’]) {

                case ‘PostgreSQL’:

                    return new PostgreSQL();

                    break;

                case ‘MySQL’:

                    return new MySQL();

                    break;

                default:

                    throw new Exception(‘Database implementer not found’);

            }

        }

    }

?>

 

يقوم الرماز أعلاه بتزويدنا بطريقة نفاذ موحدة تهدف لإنشاء واجهات لأغراض متوافقة ليتم استخدامها ضمن رماز التطبيق.

فعلياً نجد , ومن خلال الرمازالسابق بأن تطبيقك لا يعلم ولا يهتم حول قاعدة المعطيات التي سيتم استخدامها.وإنما فقط يهتم بتلبية المتطلبات المعرفة في الواجهة .

أي باختصار , توحيد واجهة التخاطب البرمجية – مع اختلاف قواعد المعطيات التي من الممكن التعامل معها – قد حل لنا مسألة المحمولية وجعلها متاحة وممكنة لأقصى الدرجات وعبر أكثر الوسائل البرمجية تقدماً (البرمجة غرضية التوجه)

التعامل مع المعطيات المعادة :

UnbufferedAssociativeResultSet 

ربما قد تكون – عبر قراءة الرماز المذكور سابقاً – قد لاحظت بأن الصف PostgreSQL لم يقم بإعادة نتائج الاستعلام بشكل مباشر. السبب في ذلك هو أن مثل هذه العملية (الإعادة المباشرة للنتيجة ) قد تقضي على الهدف المرجو من تعريف الواجهات , لأنه في PHP  لكل قاعدة معطيات طرائق مختلفة في ا لتعامل مع مصادر النتائج result resources التابعة لها .

فعلى سبيل المثال نجد بإن الصف PostgreSQL يستخدم الغرض UnbufferedAssociativeResultSet.

Listing 4 UnbufferedAssociativeResultSet.php 

<?php 
    /**
     * UnbufferedAssociativeResultSet
     *
     * Allows for unified access to a database result set
     *
     * @implements  ArrayAccess, Iterator, Countable
     * @remarks     If not using 5.1, implementing countable can be and count() used directly.
     * @see         SPL Documentation For Interface Declarations.
     */ 
    class UnbufferedAssociativeResultSet implements ArrayAccess, Iterator, Countable 
    { 
        private $currentIndex, $result;
 
        function __construct($result) 
        {
            $this->currentIndex = 0;
            $this->result = $result;
        }
         //Region ArrayAccess
        function offsetExists($offset)
        {
            switch($configuration['databasetype']) {
                case 'PostgreSQL':
                    if(pg_fetch_assoc($this->result, $offset)) {
                        return true;
                    } else {
                        return false;
                    }
                default:
                    throw new Exception("No Database Handler");
            }
        }
 
        function offsetGet($offset)
        {
            switch($configuration['databasetype']) {
                case 'PostgreSQL':
                    if($row = pg_fetch_assoc($this->result, $offset)) {
                        return $row;
                    } else {
                        throw new Exception("No row at ". $offset);
                    }
                default:
                    throw new Exception("No Database Handler");
            }
        }
         function offsetSet($offset,$value)
        {
            throw new Exception("This collection is read only.");
        }
         function offsetUnset($offset)
        {
            throw new Exception("This collection is read only.");
        }
        //EndRegion
         //Region Countable
        function count()
        {
            switch($configuration['databasetype']) {
                case 'PostgreSQL':
                    if($rows = pg_num_rows($this->result)) {
                        return $rows;
                    } else {
                        throw new Exception("Could not fetch the number of rows in resultset");
                    }
                default:
                    throw new Exception("No Database Handler");
            }
        }
        //EndRegion
         //Region Iterator
        function current()
        {
            return $this->offsetGet($this->currentIndex);
        }
         function key()
        {
            return $this->currentIndex;
        }
         function next()
        {
            return $this->currentIndex++;
        }
 
        function rewind()
        {
            $this->currentIndex = 0;
        }
         function valid()
        {
            if($this->offsetExists($this->currentIndex)) {
                return true;
            } else {
                return false;
            }
        }
         function append($value)
        {
            throw new Exception("This collection is read only");
        }
         function getIterator()
        {
            return $this;
        }
        //EndRegion
    }
?>

يقوم الغرض أعلاه بإنشاء مصفوفة من مجموعة النتائج دون أن يتطلب ذلك تحميل المعطيات إلا عند طلبها.

بإمكانك استخدام هذه المصفوفة وكأنها مصفوفة عددية , وكل دليل فيها سيقوم بإعادة المصفوفة المرافقة التي تحوي المفاتيح الموجودة في مجموعة النتائج.

ملاحظة:

1: من أجل الاختصار , قد قمت بإهمال كتابة التعليقات على هذا الصف , واستخدمت استثناءات exceptions  بسيطة.

2:أنت بحاجة لاستخدام الأغراض المشتقة من الصف Exception حتى تستطيع إطلاق استثناءات مثل الاستثناء ReadOnlyException.

يقوم هذا الصف باستخدام switch وذلك من أجل تحديد التوابع المستعملة في قاعدة المعطيات وذلك تبعاً لقاعدة المعطيات التي سيتم التعامل معها.

مثال تطبيقي:

Listing 5 listing-5.php

<?php
    $uid = 12345;
    $db = DatabaseFactory::factory();
    $ubars = $db->getCustomerDetails($uid);
 
    if($ubars[0]['property'] == "Name") {
    echo "The first property was 'name'";
    }
 
    foreach($ubars as $values) {
        foreach($values as $key=>$value) {
            echo $key . '=' . $value;
        }
    }
 
    $rows = count($ubars);
?>

 

الخلاصة :

إن استخدام عدد من مفاهيم البرمجة غرضية التوجه , يمكننا من إنشاء تجريد وتوسعة لقاعدة المعطيات المستخدمة في التطبيق, والذي يمكننا بدوره من استخدام الميزات الأساسية التي تميز قاعدة معطيات عن أخرى – وذلك بحسب الحاجة لها – وبذلك لا نربط انفسنا بقاعدة معطيات معينة , وإنما نربط بقاعدة المعطيات المناسبة أكثر للتطبيق الحالي الذي نقوم ببرمجته , فقاعدة المعطيات أصبحت بالنسبة لنا اشبه بالمتحول الذي نتحكم بالارتباط معه أو لا بحسب حاجتنا له.

وكل ما هو مطلوب منا برمجياً وفق إطار العمل المعرف سابقاً , هو كتابة الرماز المرتبط بالعمليات الخاصة بقاعدة معطيات معينة ليس إلا. وستكون تطبيقاتنا المعدة للانترنت تتميزبكونها قابلة للعمل على منصات التشغيل المختلفة .والتعامل مع قواعد معطيات مختلفة .

 

وبالختام أتمنى لكم الفائدة عبر هذه الترجمة لمقالة بعنوان البرمجة غرضية التوجه المتقدمة في PHP  

لقد استفت كثيرا بعد قرائتها , لذلك ارتأيت ألا تقف الفائدة عندي فقط , لذلك قمت بترجتها وإدراجها في مدونتي عسى ولعل أن ينتفع بها أحدهم.

في حال وجود أي من التساؤلات حول البرمجة غرضية التوجه , أرجو عدم التردد أبداً في طرحها.

وبعد فترة قليلة سأدرج مواضيع أخرى قيمة حول البرمجة غرضية التوجه في PHP   و mysql فقد قرأت منذ فترة قريبة مقالة رهيبة في هذا الصدد , وعلى أساسها وأساس الأفكار التي استوحتها منها فقد قمت بتغير أسلوبي البرمجي بشكل كامل عند التعامل مع قاعدة المعطيات .

وإلى ذلك الحين أسألكم الدعاء و استودعكم الله , والسلام عليكم ورحمة الله وبركاته.

 

المرجع :

http://www.phpriot.com/articles/oop-with-spl-php-5

 

   

 

, , , , ,

أضف تعليق