1. مقدمة
قد يكون تنفيذ أنواع الكائنات الإلزامية في PHP أمرًا مهمًا للغاية في بعض الأحيان. إذا كان مفقودًا، إما بسبب نقص المعرفة - بناءً على افتراضات برمجة غير صحيحة، أو ببساطة الكسل - فسترى نتائج في تطبيق الويب الخاص بك لا تتوقعها. خاصة عند البرمجة بلغة PHP 4، من السهل جدًا استخدام الدالة "is_a()" (على الرغم من وجود طرق أخرى) للتحقق من نوع الكائن الذي تعمل به. بالطبع، يمكن أيضًا استخدام أنواع الكائنات القسرية لتصفية كائنات الإدخال التي يجب تمريرها كمعلمات إلى فئات PHP الأخرى في نفس التطبيق.
ومع ذلك، لا يكشف PHP 4 عن بعض نقاط الضعف في نموذج الكائن الخاص به - فقد يتطلب أحيانًا كتابة تعليمات برمجية إضافية من أجل تنفيذ ميزات معينة موجودة في اللغات الموجهة للكائنات الناضجة. لقد كانت هذه الحقيقة معروفة لمجتمع PHP لفترة طويلة. ومع ذلك، مع إصدار PHP 5، تمت إضافة العديد من هذه الميزات القيمة للغاية كجزء من نموذج الكائن المحسن. سوف يساعدون في تنفيذ تطوير التعليمات البرمجية المستندة إلى الكائن بشكل أوثق - مما يسمح لك باستخدام خصائص كائن محددة.
في الحالة المذكورة أعلاه، يجب توخي الحذر بشكل خاص عندما يتعلق الأمر بإكراه نوع الكائن. في الواقع، يوفر PHP 5 للمطورين طريقتين على الأقل للتحقق من أنواع الكائنات أثناء تنفيذ تطبيق ويب - وهما عامل التشغيل "مثيل" وميزة "تلميح النوع". وبالانتقال الآن إلى الموضوع الرئيسي لهذه المقالة، سأقدم استخدام عامل التشغيل "instanceof" في PHP 5، وستجد قريبًا أنه قد يكون مناسبًا جدًا لتحديد ما إذا كان الكائن الذي تعمل معه ينتمي إلى نوع معين أم لا.
ستساعدك هذه المقالة على فهم كيفية تنفيذ أنواع الكائنات الإلزامية في PHP 5 من خلال بعض الأمثلة الموجهة للكائنات.
2. ما لا يجب عليك فعله
لإظهار كيفية تنفيذ الإكراه على نوع الكائن في PHP 5، سأستخدم فئة عنصر واجهة المستخدم (X)HTML، وفئة بسيطة لبناء الصفحات، مع تعديلات بسيطة لتناسب بيئة تطوير PHP 5.
يسرد المثال الأول الخاص بي بعض فئات عناصر واجهة مستخدم HTML (X) المشتقة من فئة أساسية مجردة "HTMLElement"، والتي تتخطى التحقق من نوع كائنات الإدخال الخاصة بها. الرجاء إلقاء نظرة على الفصل التالي أولاً:
// تحديد الفئة المجردة "HTMLElement"
فئة مجردة HTMLElement {
سمات $ المحمية؛
وظيفة محمية __construct($attributes){
إذا(!is_array($السمات)){
طرح استثناء جديد ("نوع السمة غير صالح")؛
}
$this->attributes=$attributes;
}
// مجردة طريقة 'getHTML ()' وظيفة مجردة محمية getHTML ()؛
}
// تحديد الفئة المحددة التي تمتد "Div" إلى HTMLElement
يمتد فئة Div HTMLElement {
خاص $output='<div';
بيانات $ الخاصة؛
الوظيفة العامة __construct($attributes=array(),$data){
الأصل::__construct($attributes);
$this->data=$data;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</div>';
إرجاع $this->output;
}
}
// تحديد الفئة الملموسة "Header1" - تمتد إلى HTMLElement
يمتد Class Header1 إلى HTMLElement{
خاص $output='<h1';
بيانات $ الخاصة؛
الوظيفة العامة __construct($attributes=array(),$data){
الأصل::__construct($attributes);
$this->data=$data;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</h1>';
إرجاع $this->output;
}
}
// تحديد فئة محددة "فقرة" - تمتد إلى HTMLElement
فئة الفقرة تمتد HTMLElement{
خاص $output='<p';
بيانات $ الخاصة؛
الوظيفة العامة __construct($attributes=array(),$data){
الأصل::__construct($attributes);
$this->data=$data;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</p>';
إرجاع $this->output;
}
}
// تحديد الفئة الملموسة "UnorderedList" - تمتد إلى HTMLElement
فئة UnorderedList تمتد HTMLElement{
خاص $output='<ul ';
خاص $items=array();
الوظيفة العامة __construct($attributes=array(), $items=array()){
الأصل::__construct($attributes);
إذا(!is_array($items)){
رمي استثناء جديد ("معلمة غير صالحة لعناصر القائمة")؛
}
$this->items=$items;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->العناصر كـ $item){
$this->output.='<li>'.$item.'</li>';
}
$this->output.='</ul>';
إرجاع $this->output;
}
}
كما ترون، تعتبر فئات عناصر واجهة المستخدم (X)HTML المذكورة أعلاه مفيدة جدًا لإنشاء عناصر محددة في الويب، لكنني قمت بكتابة التعليمات البرمجية لكل فئة عمدًا حتى لا تتمكن من التحقق من فعالية معلمات الإدخال. كما قد تتخيل، يتم تمرير معلمات الإدخال مباشرة إلى مُنشئ الفئة وتعيينها كخصائص. السؤال الذي يطرح نفسه: هل هناك خطأ في القيام بذلك؟ نعم، هناك. الآن، سأقوم بتعريف أبسط فئة منشئ الصفحات الخاصة بي وتغذيتها بعناصر واجهة مستخدم مثل هذه حتى تتمكن من رؤية كيفية خلط المدخلات إلى هذه الفئة مع الكائنات غير الصحيحة. هنا توقيع فئة منشئ الصفحة:
class PageGenerator{
خاص $output='';
عنوان خاص $؛
الوظيفة العامة __construct($title='الصفحة الافتراضية'){
$this->title=$title;
}
الوظيفة العامة doHeader(){
$this->output='<html><head><title>'.$this-
>العنوان.'</العنوان></الرأس><الجسم>';
}
الوظيفة العامة addHTMLElement($htmlElement){
$this->output.=$htmlElement->getHTML();
}
الوظيفة العامة doFooter(){
$this->output.='</body></html>';
}
الوظيفة العامة جلبHTML(){
إرجاع $this->output;
}
}
الآن، نبدأ في إنشاء مثيل لبعض كائنات عنصر واجهة المستخدم (X)HTML وتمريرها إلى فئات المولد المقابلة، كما هو موضح في المثال التالي:
حاول{
// إنشاء بعض عناصر HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
العنصر يذهب هنا');
$div=new Div(array('name'=>'div1','class'=>'divclass'),'محتوى عنصر Div
يذهب هنا');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'محتوى الفقرة
العنصر يذهب هنا');
$ul=new UnorderedList(array ('name'=>'list1', 'class'=>'listclass'), array
('item1'=>'value1', 'item2'=>'value2', 'item3'=>'value3'));
// إنشاء مثيل لفئة منشئ الصفحة $pageGen=new Page Generator();
$pageGen->doHeader();
// أضف كائن "HTMLElement" $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// عرض صفحة الويب echo $pageGen->fetchHTML();
}
قبض (استثناء $e) {
echo $e->getMessage();
مخرج()؛
}
بعد تشغيل كود PHP أعلاه، فإن النتيجة التي تحصل عليها هي صفحة ويب بسيطة - تحتوي على بعض كائنات (X)HTML التي تم إنشاؤها مسبقًا. في هذه الحالة، من السهل فهم ما سيحدث إذا تلقت فئة منشئ الصفحة لسبب ما كائنًا غير صحيح واستدعت الأسلوب "addHTML()" الخاص بها. لقد قمت هنا بإعادة صياغة حالة التعارض - باستخدام كائن عنصر واجهة مستخدم (X)HTML غير موجود. الرجاء إلقاء نظرة على الكود التالي مرة أخرى:
حاول{
// إنشاء بعض عناصر HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
العنصر يذهب هنا');
$div=new Div(array('name'=>'div1','class'=>'divclass'),'محتوى عنصر Div
يذهب هنا');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'محتوى الفقرة
العنصر يذهب هنا');
$ul=new UnorderedList(array ('name'=>'list1', 'class'=>'listclass'), array
('item1'=>'value1', 'item2'=>'value2', 'item3'=>'value3'));
// إنشاء مثيل لفئة منشئ الصفحة $pageGen=new Page Generator();
$pageGen->doHeader();
// أضف كائن "HTMLElement" $pageGen->addHTMLElement($fakeobj) // تمرير كائن غير موجود إلى هذه الطريقة $pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// عرض الصفحة echo $pageGen->fetchHTML();
}
قبض (استثناء $e) {
echo $e->getMessage();
مخرج()؛
}
في هذه الحالة، كما هو موضح في السطر التالي:
$pageGen->addHTMLlement($fakeobj)// تمرير كائن غير موجود إلى هذه الطريقة،
يتم تمرير كائن عنصر واجهة مستخدم (X)HTML غير موجود إلى فئة منشئ الصفحة، هذا سيؤدي إلى خطأ فادح:
خطأ فادح: استدعاء وظيفة عضو على غير الكائن
ماذا عن
المسار/إلى/الملف
؟هذه عقوبة مباشرة لعدم التحقق من نوع الكائن الذي تم تمريره إلى فئة المولد! لذا تأكد من وضع ذلك في الاعتبار عند كتابة النصوص الخاصة بك. لحسن الحظ، هناك حل بسيط لهذه المشاكل، وهنا تأتي قوة عامل التشغيل "instanceof". إذا كنت تريد أن ترى كيف يتم استخدام هذا العامل، تابع القراءة.
3. استخدم عامل التشغيل "instanceof"،
كما ترون، فإن استخدام عامل التشغيل "instanceof" بسيط جدًا. فهو يستخدم معلمتين لإكمال وظيفته. المعلمة الأولى هي الكائن الذي تريد التحقق منه، والمعلمة الثانية هي اسم الفئة (اسم الواجهة في الواقع) المستخدم لتحديد ما إذا كان الكائن هو مثيل للفئة المقابلة. بالطبع، لقد استخدمت المصطلحات المذكورة أعلاه عن قصد حتى تتمكن من معرفة مدى سهولة استخدام هذا العامل. بناء الجملة الأساسي الخاص به هو كما يلي:
إذا (كائن مثيل اسم الفئة) {
// افعل شيئًا مفيدًا
}
الآن بعد أن فهمت كيفية استخدام هذا العامل في PHP 5، دعنا نحدد فئة منشئ صفحات الويب المقابلة للتحقق من نوع الكائن الذي تم تمريره إلى طريقة "addHTMLElement()" الخاصة به. إليكم التوقيع الجديد لهذه الفئة والذي ذكرته سابقًا يستخدم عامل التشغيل "instanceof":
class PageGenerator{
خاص $output='';
عنوان خاص $؛
الوظيفة العامة __construct($title='الصفحة الافتراضية'){
$this->title=$title;
}
الوظيفة العامة doHeader(){
$this->output='<html><head><title>'.$this->title.'</title></head><body>';
}
الوظيفة العامة addHTMLElement($htmlElement){
إذا(!$htmlElement مثيل HTMLElement){
طرح استثناء جديد ("عنصر HTML (X) غير صالح")؛
}
$this->output.=$htmlElement->getHTML();
}
الوظيفة العامة doFooter(){
$this->output.='</body></html>';
}
الوظيفة العامة جلبHTML(){
إرجاع $this->output;
}
}
لاحظ، في الفئة أعلاه، كيفية تضمين عامل التشغيل "instanceof" في طريقة "addHTMLElement()" للتأكد من أن كافة الكائنات التي تم تمريرها هي مثيلات لفئة "HTMLELElement" المحددة مسبقًا. الآن، من الممكن إعادة بناء صفحة الويب التي شاهدتها سابقًا، وفي هذه الحالة تأكد من أن جميع كائنات الإدخال التي تم تمريرها إلى فئة منشئ صفحات الويب هي كائنات عناصر واجهة مستخدم HTML حقيقية (X). إليك المثال المقابل:
حاول{
// إنشاء بعض عناصر HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'يظهر هنا محتوى عنصر H1');
$div=new Div(array('name'=>'div1', 'class'=>'divclass'), 'محتوى عنصر Div يظهر هنا');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'محتوى عنصر الفقرة يظهر هنا');
$teststr='هذا ليس عنصر HTML';
// إنشاء مثيل لفئة منشئ الصفحة $pageGen=new Page Generator();
$pageGen->doHeader();
// أضف كائن "HTMLElement" $pageGen->addHTMLElement($teststr) // قم بتمرير سلسلة بسيطة إلى هذه الطريقة $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->doFooter();
// عرض صفحة الويب echo $pageGen->fetchHTML();
}
قبض (استثناء $e) {
echo $e->getMessage();
مخرج()؛
}
كما رأيت في المثال أعلاه، أقوم بتمرير سلسلة اختبار بسيطة (وليس كائن "HTMLELElement") إلى فئة منشئ الصفحة، والتي ستطرح استثناءً - تم اكتشافه بواسطة كتلة "catch" محددة، كما هو موضح أدناه:
عنصر HTML (X) غير صالح
في هذا الوقت، من أجل تحديد صحة كائن الإدخال، استخدمت عامل التشغيل "instanceof"، بحيث يمكن أن تكون صفحة الويب أعلاه، وآمل أن تقدر حقًا أهمية تصفية الإدخال إلى طرق فصلك لتجنب الأخطاء الدخيلة باستخدام عامل إدخال البيانات هذا.
بعد إظهار التنفيذ الصحيح لعامل التشغيل "instanceof" داخل فئة منشئ صفحة الويب، هناك المزيد مما يجب القيام به على غرار ما كتبته لـ PHP 4 في المقالة السابقة. (X) بالنسبة لفئات أدوات HTML، أود تضمين هذا العامل كجزء من طريقة "getHTML()"، مما يسمح بإنشاء صفحات ويب تولد عناصر HTML متداخلة (X).
4. قم بتوسيع استخدام عامل التشغيل "instanceof": تعد أدوات HTML المتداخلة (X)
جيدة. لقد رأيت أن عامل التشغيل "instanceof" يؤدي أداءً جيدًا في التحقق من كائنات الإدخال التي يتم إدخالها مباشرة في وظيفة منشئ الصفحة. الآن، سأذهب خطوة أخرى وأضيف روتين فحص إلى المُنشئ وطريقة "getHTML()" لفئة عناصر واجهة المستخدم (X)HTML حتى يتمكنوا من قبول عناصر واجهة المستخدم الأخرى كمعلمات إدخال. يرجى التحقق من التحسينات أدناه:
يمتد فئة Div HTMLElement {
خاص $output='<div';
بيانات $ الخاصة؛
الوظيفة العامة __construct($attributes=array(),$data){
إذا(!$مثيل بيانات HTMLElement&&!is_string($data)){
رمي استثناء جديد ("نوع المعلمة غير صالح")؛
}
الأصل::__construct($attributes);
$this->data=$data;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->مثيل بيانات HTMLElement)؟
$this->data->getHTML():$this->data;
$this->output.='</div>';
إرجاع $this->output;
}
}
يمتد Class Header1 إلى HTMLElement{
خاص $output='<h1';
بيانات $ الخاصة؛
الوظيفة العامة __construct($attributes=array(),$data){
إذا(!$مثيل بيانات HTMLElement&&!is_string($data)){
رمي استثناء جديد ("نوع المعلمة غير صالح")؛
}
الأصل::__construct($attributes);
$this->data=$data;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->مثيل بيانات HTMLElement)؟
$this->data->getHTML():$this->data;
$this->output.='</h1>';
إرجاع $this->output;
}
}
فئة الفقرة تمتد HTMLElement{
خاص $output='<p';
بيانات $ الخاصة؛
الوظيفة العامة __construct($attributes=array(),$data){
إذا(!$مثيل بيانات HTMLElement&&!is_string($data)){
رمي استثناء جديد ("نوع المعلمة غير صالح")؛
}
الأصل::__construct($attributes);
$this->data=$data;
}
// التنفيذ المحدد لطريقة "getHTML ()" public function getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->مثيل بيانات HTMLElement)؟
$this->data->getHTML():$this->data;
$this->output.='</p>';
إرجاع $this->output;
}
}
فئة UnorderedList تمتد HTMLElement{
خاص $output='<ul ';
خاص $items=array();
الوظيفة العامة __construct($attributes=array(), $items=array()){
الأصل::__construct($attributes);
إذا(!is_array($items)){
رمي استثناء جديد ("معلمة غير صالحة لعناصر القائمة")؛
}
$this->items=$items;
}
// التنفيذ المحدد لطريقة "getHTML ()".
الوظيفة العامة getHTML(){
foreach($this->السمات كـ $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->العناصر كـ $item){
$this->output.=($item exampleof
HTMLElement)?'<li>'.$item->getHTML().'</li>':'<li>'.$item.'</li>';
}
$this->output.='</ul>';
إرجاع $this->output;
}
}
كما هو موضح في الفئات أعلاه، من أجل السماح بتنفيذ عناصر HTML (X) المتداخلة عند إنشاء صفحات الويب المقابلة، قمت بإعادة هيكلة مُنشئاتها وطرق "getHTML()" على التوالي. لاحظ أنني قمت بتضمين الكتلة الشرطية التالية في مُنشئ كل فئة:
if(!$data مثيل HTMLElement&&!is_string($data)){
رمي استثناء جديد ("نوع المعلمة غير صالح")؛
}
في هذه المرحلة، ما أفعله بالفعل هو التأكد من السماح فقط لبيانات السلسلة والكائنات من النوع "HTMLELElement" كمعلمات إدخال لكل فئة. وإلا، فسيتم طرح استثناء بالطريقة المعنية وقد يتسبب في توقف التطبيق عن التنفيذ. لذلك، هذه هي عملية التحقق من البيانات المدخلة. الآن، دعونا نلقي نظرة على التوقيع الجديد للأسلوب "getHTML()"، والذي يستخدم أيضًا عامل التشغيل "instanceof":
$this->output.=($this->datainstanceof HTMLElement)?$this->data-
>getHTML():$this->data;
كما ترون، في هذه الحالة، يعد عامل التشغيل this مفيدًا جدًا للاستفادة من الميزات متعددة الأشكال لفئة عنصر واجهة المستخدم (X)HTML. إذا كانت السمة $data هي أيضًا عنصر واجهة مستخدم، فسيتم استدعاء أسلوب "getHTML()" الخاص بها بشكل صحيح، مما سيؤدي إلى عرض عنصر الويب المتداخل. من ناحية أخرى، إذا كانت مجرد سلسلة، فسيتم إضافتها مباشرة إلى جميع مخرجات الفئة الحالية.
في هذه المرحلة، ربما تكون قد فهمت استخدام عامل التشغيل "instanceof" في PHP 5 للتأكد من أن كائنات معينة تنتمي إلى نوع معين. كما ترون في هذه المقالة، فإن فرض أنواع الكائنات في PHP 5 هو في الواقع مهمة واضحة إلى حد ما. في الوقت الحالي، من الأفضل أن تقوم بتطوير مثال لاستخدام هذه الطريقة لتصفية الكائنات في تطبيق PHP الخاص بك لتعميق فهمك.
5. الملخص
في هذه المقالة، تعلمت كيفية استخدام عامل التشغيل "instanceof" في PHP 5 للتحقق من نوع كائن الإدخال الخاص بك، ومع ذلك، فإن الطريقة التي عرضتها لك ليست الوحيدة؛ في مقالة لاحقة، سأشرح لك كيفية تنفيذ ميزة "تلميح النوع" الرائعة في PHP 5، وهي طريقة أخرى لفرض كتابة الكائنات.
المؤلف: مترجم Zhu Xianzhong المصدر: Tianji Development