الفرق بين المراجعتين لصفحة: «PHP/OOP»

من موسوعة حسوب
< PHP
ط استبدال النص - 'PHP/OOP/changelog' ب'PHP/OOP'
تعديل رابط صفحة التحميل التلقائي
 
(22 مراجعة متوسطة بواسطة مستخدم واحد آخر غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:البرمجة كائنية التوجه في PHP}}</noinclude>بدءًا من الإصدار الخامس من اللغة، أعيدت كتابة نموذج الكائنات للحصول على أداء أفضل وإضافة المزيد من الميزات، وقد كان هذا من التغييرات الكبيرة في اللغة، إذ قدّم الإصدار الخامس نموذج مكتملًا للكائنات.
<noinclude>{{DISPLAYTITLE:البرمجة كائنية التوجه في PHP}}</noinclude>بدءًا من الإصدار الخامس من اللغة، أعيدت كتابة نموذج الكائنات للحصول على أداء أفضل وإضافة المزيد من الميزات، وقد كان هذا من التغييرات الكبيرة في اللغة، إذ قدّم الإصدار الخامس نموذج مكتملًا للكائنات.


ومن الميزات التي قدّمها الإصدار الخامس [[PHP/OOP/visibility|قابلية الرؤية]] (visibility)، [[PHP/abstract|الأصناف والتوابع المجرّدة]] (abstract) [[PHP/OOP/final|والنهائية]] (final)، المزيد من [[PHP/OOP/magic|التوابع السحرية]] (magical methods)، [[PHP/OOP/interfaces|الواجهات]] (interfaces)، [[PHP/OOP/cloning|الاستنساخ]] (cloning) [[PHP/OOP/typehinting|والإشارة إلى الأنواع]] (typehinting).
ومن الميزات التي قدّمها الإصدار الخامس [[PHP/properties visibility|قابلية الرؤية]] (visibility)، [[PHP/abstract|الأصناف والتوابع المجرّدة]] (abstract) [[PHP/final|والنهائية]] (final)، المزيد من [[PHP/magic|التوابع السحرية]] (magical methods)، [[PHP/interfaces|الواجهات]] (interfaces)، [[PHP/cloning objects|الاستنساخ]] (cloning) [[PHP/typehinting|والإشارة إلى الأنواع]] (typehinting).


تعامل PHP الكائنات معاملة المراجع (references) أو المقابض (handles)، بمعنى أنّ كلّ متغيّر يتضمن كائنًا مرجعيًا وليس نسخة من الكائن كلّه. انظر [[PHP/OOP/references|الكائنات والمراجع]].
تعامل PHP الكائنات معاملة المراجع (references) أو المقابض (handles)، بمعنى أنّ كلّ متغيّر يتضمن كائنًا مرجعيًا وليس نسخة من الكائن كلّه. انظر [[PHP/objects references|الكائنات والمراجع]].


نصيحة: راجع أيضًا [[PHP/Userland Naming|دليل تسمية Userland]].
نصيحة: راجع أيضًا [[PHP/Userland Naming|دليل تسمية Userland]].


== [[PHP/OOP|الأساسيات]] ==
== الأساسيات ==
===الصنف===
تبدأ الصيغة البسيطة للتعريف عن الصنف بالكلمة المفتاحية class، يتبعها اسم الصنف ويتبعه زوج من الأقواس المعقوفة التي تحيط بالعبارات المسؤولة عن تعريف الخصائص والتوابع المُنتمية إلى الصنف.
تبدأ الصيغة البسيطة للتعريف عن الصنف بالكلمة المفتاحية class، يتبعها اسم الصنف ويتبعه زوج من الأقواس المعقوفة التي تحيط بالعبارات المسؤولة عن تعريف الخصائص والتوابع المُنتمية إلى الصنف.


يمكن أن يحمل الصنف أي اسم بشرط أن لا يكون كلمةً محجوزةً في PHP. يبدأ اسم الصنف النظامي بحرف أو شرطة سفلية، تتبعها أيّ عددٍ من الحروف أو الأرقام أو الشرطات السفلية. ويمكن التعبير عن هذه الصيغة باستخدام التعابير النمطية بالصورة التالية: ‎<code>^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$‎</code>.
يمكن أن يحمل الصنف أي اسم بشرط أن لا يكون كلمةً محجوزةً في PHP. يبدأ اسم الصنف النظامي بحرف أو شرطة سفلية، تتبعها أيّ عددٍ من الحروف أو الأرقام أو الشرطات السفلية. ويمكن التعبير عن هذه الصيغة باستخدام التعابير النمطية بالصورة التالية: ‎<code>^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$‎</code>.


يمكن أن يحتوي الصنف على <nowiki/>[[PHP/Variables|ثوابت]] و<nowiki/>[[PHP/constants|متغيرات]] (تسمّى "خصائص" [properties]) ودوالّ (تسمى "توابع" [methods]) خاصة به.
يمكن أن يحتوي الصنف على [[PHP/variables|ثوابت]] و<nowiki/>[[PHP/constants|متغيرات]] (تسمّى "خصائص" [properties]) ودوالّ (تسمى "توابع" [methods]) خاصة به.


== [[PHP/OOP/properties|الخاصيات]] ==
المثال 1: مثال عن تعريف بسيط للصنف<syntaxhighlight lang="php">
 
<?php
class SimpleClass
{
    // التصريح عن الخاصّية
    public $var = 'a default value';
 
    // التصريح عن التابع
    public function displayVar() {
        echo $this->var;
    }
}
?>
</syntaxhighlight>يكون المتغيّر الزائف <code>‎$this</code> متاحًا عند استدعاء التابع من داخل سياق الكائن. يعدّ <code>‎$this</code> مرجعًا للكائن المستدعي (عادة ما يكون الكائن الذي ينتمي إليه التابع، ولكن قد يكون كائنًا آخر، وذلك عندما تستدعى الدالة [[PHP/static|سكونيّاً]] [statically] ضمن سياق خاصّ بكائن آخر). منذ الإصدار 7.0.0 من اللغة يؤدي الاستدعاء الساكن لتابع غير ساكن يؤدي إلى عدم التعرّف على ‎$this داخل التابع. منذ الإصدار 5.6.0 من اللغة أصبحت عملية الاستدعاء الساكن لتابع غير ساكن من سياق غير متوافق عملية مهملة. أما في الإصدار 7.0.0 فقد أصبحت عملية الاستدعاء الساكن لتابغ غير ساكن مهملة بصورة عامّة (حتى لو استدعي التابع من سياق متوافق). يؤدي هذا النوع من الاستدعاء إلى إطلاق ملاحظة من نوع strict في الإصدارات السابقة للإصدار 5.6.0.
 
المثال 2: بعض الأمثلة على المتغير الزائف <code>‎$this</code>
 
سنفترض في هذا المثال أنّ خاصية الإبلاغ عن الأخطار <code>error_reporting</code> معطّلة، وإلا ستطلق الشيفرة التالية ملاحظات من نوع deprecated و strict على التوالي، حسب إصدار اللغة المستخدم.<syntaxhighlight lang="php">
 
<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this is not defined.\n";
        }
    }
}
 
class B
{
    function bar()
    {
        A::foo();
    }
}
 
$a = new A();
$a->foo();
 
A::foo();
$b = new B();
$b->bar();
 
B::bar();
?></syntaxhighlight>تعطي الشيفرة السابقة النتيجة التالية في الإصدار 5 من اللغة:<syntaxhighlight lang="php">
 
$this is defined (A)
$this is not defined.
$this is defined (B)
$this is not defined.
</syntaxhighlight>أما الإصدار 7 من اللغة فيعطي النتائج التالية:<syntaxhighlight lang="php">
 
$this is defined (A)
$this is not defined.
$this is not defined.
$this is not defined.
</syntaxhighlight>
===الكلمة المفتاحية new===
لإنشاء نسخة (instance) من الصنف يجب استخدام الكلمة المفتاحية new، ودائمًا ما يتمّ إنشاء الكائن إلا إذا كان يمتلك دالة بانية constructor ترمي استثناءً عند وقوع خطأ ما. يستحسن تعريف الأصناف قبل تهيئتها instantiation (وفي بعض الأحيان يكون الأمر مطلوبًا).
 
في حال استخدام سلسلة نصّية تحتوي اسم أحد الأصناف مع الكلمة المفتاحية <code>new</code>، فإن اللغة تنشئ نسخة جديدة من ذلك الصنف، وإن كان الصنف ضمن مجال أسماء معيّن، فيجب استخدام اسمه المؤهّل بالكامل (fully qualified name).
 
المثال 3: إنشاء نسخة من الصنف<syntaxhighlight lang="php">
 
<?php
$instance = new SimpleClass();
 
// يمكن القيام بهذا ضمن متغيّر
$className = 'SimpleClass';
$instance = new $className(); // new SimpleClass()
?>
</syntaxhighlight>من الممكن إنشاء كائن جديد ضمن سياق الصنف وذلك باستخدام العبارتين <code>new self</code> و <code>new parent</code>.
 
عند إسناد نسخة من الصنف إلى متغيّر جديد يصبح بمقدور المتغير الوصول إلى النسخة ذاتها كما هو حال الكائن الذي أُسند إليه، وتسلك عملية تمرير النسخ إلى الدوالّ السلوك ذاته. يمكن إنشاء نسخة من عنصر تمّ إنشاؤه مسبقًا عن طريق استنساخه.
 
المثال 4: إسناد الكائنات<syntaxhighlight lang="php">
 
 
<?php
 
$instance = new SimpleClass();
 
$assigned  =  $instance;
$reference  =& $instance;
 
$instance->var = '$assigned will have this value';
 
$instance = null; // $instance and $reference become null
 
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
</syntaxhighlight>يعطي المثال السابق النتيجة التالية:<syntaxhighlight lang="php">
 
NULL
NULL
object(SimpleClass)#1 (1) {
  ["var"]=>
    string(30) "$assigned will have this value"
}
</syntaxhighlight>قدّم الإصدار 5.3.0 من اللغة طريقتين جديدتين لإنشاء نسخ من الكائنات:
 
المثال 5: إنشاء كائنات جديدة<syntaxhighlight lang="php">
 
<?php
class Test
{
    static public function getNew()
    {
        return new static;
    }
}
 
class Child extends Test
{}
 
$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);
 
$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);
 
$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>
</syntaxhighlight>تعطي الشيفرة السابقة المخرجات التالية:<syntaxhighlight lang="php">
 
bool(true)
bool(true)
bool(true)
</syntaxhighlight>قدّم الإصدار 5.4.0 من اللغة إمكانية الوصول إلى أحد أعضاء (أي الخصائص أو التوابع) الكائنات الجديدة باستخدام تعبير واحد:
 
المثال 6: الوصول إلى أحد أعضاء كائن جديد<syntaxhighlight lang="php">
 
<?php
echo (new DateTime())->format('Y');
?>
</syntaxhighlight>تعطي الشيفرة السابقة المخرجات التالية:<syntaxhighlight lang="php">
 
2016
</syntaxhighlight>
===الخصائص والتوابع===
تستقرّ خصائص وتوابع الصنف في مجال أسماء منفصل؛ لذا يمكن أن يحمل صنف وتابع الاسم ذاته. تقدّم اللغة صيغة واحدة للوصول إلى الخصائص أو التوابع، وتعتمد هذه العملية على السياق فقط، بمعنى أنّه هل أن طريقة الاستخدام هي الوصول إلى متغير أو استدعاء دالة.
 
المثال 7: الوصول إلى خاصية مقابل استدعاء تابع<syntaxhighlight lang="php">
 
<?php
class Foo
{
    public $bar = 'property';
   
    public function bar() {
        return 'method';
    }
}
 
$obj = new Foo();
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;
</syntaxhighlight>يعطي المثال السابق النتائج التالية:<syntaxhighlight lang="php">
 
property
method
</syntaxhighlight>هذا يعني أنّه ليس بالإمكان استدعاء [[PHP/anonymous functions|دالة مجهولة]] مُسندة إلى خاصية بصورة مباشرة، بل يجب إسناد الخاصية إلى متغير في البداية على سبيل المثال. أما في الإصدار 7.0.0 فقد أصبح بالإمكان استدعاء مثل هذه الخاصّية مباشرة وذلك بإحاطتها بالأقواس.
 
المثال 8: استدعاء دالة مجهولة مخزّنة في خاصّية<syntaxhighlight lang="php">
 
<?php
class Foo
{
    public $bar;
   
    public function __construct() {
        $this->bar = function() {
            return 42;
        };
    }
}
 
$obj = new Foo();
 
// منذ الإصدار
// PHP 5.3.0:
$func = $obj->bar;
echo $func(), PHP_EOL;
 
// يمكن استخدام هذه الصيغة في الإصدار
// PHP 7.0.0:
echo ($obj->bar)(), PHP_EOL;
</syntaxhighlight>تعطي الشيفرة السابقة النتيجة التالية:<syntaxhighlight lang="php">
42
</syntaxhighlight>
===الكلمة المفتاحية <code>extends</code>===
يمكن للصنف أن يرث توابع وخصائص صنف آخر باستخدام الكلمة المفتاحية <code>extends</code> عند التصريح عن الصنف، ولا تتيح اللغة الوراثة من أكثر من صنف واحد.
 
يمكن تجاوز التوابع والخصائص الموروثة عن طريق إعادة التصريح عنها باستخدام نفس الأسماء التي تحملها في الصنف الأب. ولكن إن كان أحد التوابع معرّفًا في الصنف الأب باستخدام الكلمة المفتاحية <code>[[PHP/final|final]]</code>، فلا يمكن حينئذٍ تجاوز ذلك التابع. يمكن الوصول إلى التوابع المُتجاوز عليها أو الخصائص الساكنة في الصنف الأب عن طريق <code>[[PHP/scope operator|parent::]]</code>‎.
 
يجب أن لا يتغير توقيع المعامل [parameter signature] عند تجاوز (override، أي إعادة تعريف) التوابع، وإلا ستطلق اللغة خطأً من المستوى E_STRICT، ولكن لا ينطبق هذا على الدالة البانية والتي تسمح بالتجاوز باستخدام معاملات مختلفة.
 
المثال 9: وراثة الأصناف<syntaxhighlight lang="php">
 
<?php
class ExtendClass extends SimpleClass
{
    // إعادة تعريف التابع الذي ينتمي للصنف الأب
    function displayVar()
    {
        echo "Extending class\n";
        parent::displayVar();
    }
}
 
$extended = new ExtendClass();
$extended->displayVar();
?>
</syntaxhighlight>تعطي الشيفرة السابقة النتيجة التالية:<syntaxhighlight lang="php">
 
Extending class
a default value
</syntaxhighlight>
===الكلمة المفتاحية ‎::class===
أصبح بالإمكان استخدام الكلمة المفتاحية <code>class</code> في الإصدار 5.5 من اللغة للحصول على اسم الصنف. يمكن الحصول على سلسلة نصّية تتضمن الاسم المؤهّل بالكامل للصنف وذلك باستخدام الصيغة <code>ClassName::class</code>، وهذه الميزة مفيدة جدًّا عند التعامل مع الأصناف المنتمية إلى [[PHP/namespaces|مجالات أسماء]] مختلفة.
 
المثال 10: الحصول على اسم الصنف<syntaxhighlight lang="php">
 
<?php
namespace NS {
    class ClassName {
    }
   
    echo ClassName::class;
}
?>
</syntaxhighlight>تعطي الشيفرة السابقة النتيجة التالية:<syntaxhighlight lang="php">
 
NS\ClassName
</syntaxhighlight><span> </span>
 
ملاحظة: تجري عملية الحصول على اسم الصنف باستخدام <code>‎::class</code> في وقت التصريف. هذا يعني أنّه عند إنشاء السلسلة النصّية التي تحمل اسم الصنف فإنّ عملية التحميل التلقائي (autoloading) لم تحدث بعد، ونتيجة لذلك، تتوسّع أسماء الأصناف حتى لو كانت الصنف غير معرّفًا، ولن يحدث أيّ خطأً في هذه الحالة.
== [[PHP/properties|الخاصيات]] ==
تطلق تسمية "الخاصيات properties" على المتغيّرات المعرّفة ضمن الأصناف، وهناك تسميات أخرى مثل "المعاملات" أو "الحقول"، ولكن سنستخدم التسمية الأولى "الخاصيات" في هذا الدليل. تعرّف الخاصيات باستخدام إحدى الكلمات المفتاحية public، أو protected، أو private تتبعها عبارة تصريح عن متغير اعتيادي. يمكن أن يتضمّن هذا التصريح عملية تهيئة initialization، ولكن يجب أن تكون هذه التهيئة ذات قيمة ثابتة، بمعنى أنّه يجب أن تكون قابلة للمعالجة في وقت التصريف ويجب أن لا تعتمد على المعلومات المتاحة في وقت التشغيل لغرض المعالجة.
تطلق تسمية "الخاصيات properties" على المتغيّرات المعرّفة ضمن الأصناف، وهناك تسميات أخرى مثل "المعاملات" أو "الحقول"، ولكن سنستخدم التسمية الأولى "الخاصيات" في هذا الدليل. تعرّف الخاصيات باستخدام إحدى الكلمات المفتاحية public، أو protected، أو private تتبعها عبارة تصريح عن متغير اعتيادي. يمكن أن يتضمّن هذا التصريح عملية تهيئة initialization، ولكن يجب أن تكون هذه التهيئة ذات قيمة ثابتة، بمعنى أنّه يجب أن تكون قابلة للمعالجة في وقت التصريف ويجب أن لا تعتمد على المعلومات المتاحة في وقت التشغيل لغرض المعالجة.


== [[PHP/OOP/constants|ثوابت الأصناف]] ==
== [[PHP/class constants|ثوابت الأصناف]] ==
يمكن تعريف قيم ثابتة لا يمكن تعديلها ولكل صنفٍ على حدة. تختلف الثوابت عن المتغيرات الاعتيادية في عدم استخدام العلامة <code>$</code> للتصريح عنها أو استخدامها. تمتلك ثوابت الأصناف قابلية رؤية من نوع public.
يمكن تعريف قيم ثابتة لا يمكن تعديلها ولكل صنفٍ على حدة. تختلف الثوابت عن المتغيرات الاعتيادية في عدم استخدام العلامة <code>$</code> للتصريح عنها أو استخدامها. تمتلك ثوابت الأصناف قابلية رؤية من نوع public.


== [[PHP/autoload|التحميل التلقائي للأصناف]] ==
== [[PHP/autoloading|التحميل التلقائي للأصناف]] ==
يُنشئ أغلب المطوّرين الذي يكتبون تطبيقات كائنية التوجه ملف PHP واحد لكل صنف. وهنا تظهر مشكلة مزعجة للغاية، وهي الحاجة إلى كتابة قائمة طويلة بالأصناف التي يجب تضمينها للبدء بتنفيذ الشيفرة (قائمة لكل صنف).
يُنشئ أغلب المطوّرين الذي يكتبون تطبيقات كائنية التوجه ملف PHP واحد لكل صنف. وهنا تظهر مشكلة مزعجة للغاية، وهي الحاجة إلى كتابة قائمة طويلة بالأصناف التي يجب تضمينها للبدء بتنفيذ الشيفرة (قائمة لكل صنف).


لم يعد هذا الأمر ضروريًا في الإصدار الخامس من اللغة، إذ تسجّل الدالة <code>spl_autoload_register()</code>‎‎ عددًا غير محدّدٍ من المحمّلات التلقائية لتتيح إمكانية التحميل التلقائي للأصناف والواجهات غير المعرّفة في ملف الشيفرة. يمنح تسجيلُ المحمّلات التلقائية اللغةَ فرصة أخيرة لتحميل الصنف أو الواجهة قبل أن تتوقف الشيفرة عن العمل وتطلق خطأً.
لم يعد هذا الأمر ضروريًا في الإصدار الخامس من اللغة، إذ تسجّل الدالة <code>spl_autoload_register()</code>‎‎ عددًا غير محدّدٍ من المحمّلات التلقائية لتتيح إمكانية التحميل التلقائي للأصناف والواجهات غير المعرّفة في ملف الشيفرة. يمنح تسجيلُ المحمّلات التلقائية اللغةَ فرصة أخيرة لتحميل الصنف أو الواجهة قبل أن تتوقف الشيفرة عن العمل وتطلق خطأً.


== [[PHP/OOP/decon|التوابع البانية والهادمة]] ==
== [[PHP/decon|التوابع البانية والهادمة]] ==
تتيح لغة PHP للمطورين التصريح عن تابع بانٍ في الأصناف. كل صنف يمتلك تابعًا بانيًا يستدعي هذا التابع مع كل كائن جديد يُنشأ من ذلك الصنف؛ لهذا يعد هذا التابع ملائمًا لعمليات التهيئة التي قد يحتاج لها الكائن قبل استخدامه.
تتيح لغة PHP للمطورين التصريح عن تابع بانٍ في الأصناف. كل صنف يمتلك تابعًا بانيًا يستدعي هذا التابع مع كل كائن جديد يُنشأ من ذلك الصنف؛ لهذا يعد هذا التابع ملائمًا لعمليات التهيئة التي قد يحتاج لها الكائن قبل استخدامه.


تقدّم PHP 5 مفهوم الدوال الهادمة وهو مفهوم شائع في لغات البرمجة كائنية التوجّه مثل C++‎. تُستدعى الدالة الهادمة عندما لا يكون هناك أي مرجع لكائن معين.
تقدّم PHP 5 مفهوم الدوال الهادمة وهو مفهوم شائع في لغات البرمجة كائنية التوجّه مثل C++‎. تُستدعى الدالة الهادمة عندما لا يكون هناك أي مرجع لكائن معين.


== [[PHP/OOP/visibility|قابلية الرؤية]] ==
== [[PHP/properties visibility|قابلية الرؤية]] ==
يمكن تعريف قابلية رؤية خاصية أو تابع أو (بدءًا من الإصدار 7.1.0 من اللغة) ثابت بأنّها إلحاق صيغة التصريح بإحدى الكلمات المفتاحية public، أو protected، أو private. يتيح التصريح من نوع public الوصول إلى أعضاء الصنف من أي مكان، ويتيح التصريح من نوع protected الوصول إلى الأعضاء من داخل الصنف نفسه أو الأصناف التي ترث الصنف أو تورّثه، أما التصريح من نوع private فيتيح الوصول إلى الأعضاء من داخل الصنف الذي عرِّف فيه ذلك العضو حصرًا.
يمكن تعريف قابلية رؤية خاصية أو تابع أو (بدءًا من الإصدار 7.1.0 من اللغة) ثابت بأنّها إلحاق صيغة التصريح بإحدى الكلمات المفتاحية public، أو protected، أو private. يتيح التصريح من نوع public الوصول إلى أعضاء الصنف من أي مكان، ويتيح التصريح من نوع protected الوصول إلى الأعضاء من داخل الصنف نفسه أو الأصناف التي ترث الصنف أو تورّثه، أما التصريح من نوع private فيتيح الوصول إلى الأعضاء من داخل الصنف الذي عرِّف فيه ذلك العضو حصرًا.


== [[PHP/OOP/inheritance|وراثة الكائنات]] ==
== [[PHP/class inheritance|وراثة الكائنات]] ==
وراثة الكائنات من المبادئ المعروفة في البرمجة كائنية التوجه وتستخدمه PHP في نموذج الكائنات الخاصّ بها. يؤثّر هذا المبدأ على العلاقة التي تربط بين الأصناف والكائنات.
وراثة الكائنات من المبادئ المعروفة في البرمجة كائنية التوجه وتستخدمه PHP في نموذج الكائنات الخاصّ بها. يؤثّر هذا المبدأ على العلاقة التي تربط بين الأصناف والكائنات.


== [[PHP/OOP/scope-operator|عامل تحليل النطاق (::)]] ==
== [[PHP/scope operator|عامل تحليل النطاق (::)]] ==
يسمح عامل تحليل النطاق (Scope Resolution Operator) بالوصول إلى الخاصيات والتوابع من نوع static، أو المتجاوز عليها أو الثوابت الخاصة بصنف معين.
يسمح عامل تحليل النطاق (Scope Resolution Operator) بالوصول إلى الخاصيات والتوابع من نوع static، أو المتجاوز عليها أو الثوابت الخاصة بصنف معين.


== [[PHP/OOP/static|الكلمة المفتاحية Static]] ==
== [[PHP/static|الكلمة المفتاحية Static]] ==
يمكن استخدام static أيضًا لتعريف <nowiki/>[[PHP/Variables/scope|المتغيرات الساكنة]] و<nowiki/>[[PHP/OOP/late-static-bindings|الروابط الساكنة اللاحقة]] (late static bindings).
يمكن استخدام static أيضًا لتعريف <nowiki/>[[PHP/variables scope|المتغيرات الساكنة]] و<nowiki/>[[PHP/late static bindings|الروابط الساكنة اللاحقة]] (late static bindings).


== [[PHP/abstract|تجريد الأصناف]] ==
== [[PHP/abstract|تجريد الأصناف]] ==
يقدّم الإصدار الخامس من اللغة الأصناف والتوابع المجرّدة. لا يمكن تهيئة الأصناف المجرّدة، وإذا احتوى الصنف على تابع مجرّد واحدٍ على الأقل فيجب أن يكون الصنف مجردًا أيضًا. تصرّح الأصناف المجرّدة ببساطة عن توقيع التابع (method's signature)، ولا يمكنها تعريف الاستخدام (implementation).
يقدّم الإصدار الخامس من اللغة الأصناف والتوابع المجرّدة. لا يمكن تهيئة الأصناف المجرّدة، وإذا احتوى الصنف على تابع مجرّد واحدٍ على الأقل فيجب أن يكون الصنف مجردًا أيضًا. تصرّح الأصناف المجرّدة ببساطة عن توقيع التابع (method's signature)، ولا يمكنها تعريف الاستخدام (implementation).


== [[PHP/OOP/interfaces|واجهات الكائنات]] ==
== [[PHP/interfaces|واجهات الكائنات]] ==
تتيح واجهات الكائنات إنشاء شيفرة تحدّد التوابع التي يجب أن يتضمّنها الصنف دون الحاجة إلى تعريف آلية التحكّم في هذه التوابع.
تتيح واجهات الكائنات إنشاء شيفرة تحدّد التوابع التي يجب أن يتضمّنها الصنف دون الحاجة إلى تعريف آلية التحكّم في هذه التوابع.


تعرّف الواجهات بنفس طريقة تعريف الأصناف، ولكن باستخدام الكلمة المفتاحية interface بدل الكلمة المفتاحية class ودون تعريف محتوى أيّ تابعٍ في الواجهة.
تعرّف الواجهات بنفس طريقة تعريف الأصناف، ولكن باستخدام الكلمة المفتاحية interface بدل الكلمة المفتاحية class ودون تعريف محتوى أيّ تابعٍ في الواجهة.


== [[PHP/OOP/traits|السمات]] ==
== [[PHP/traits|السمات]] ==
تعدّ السمات طريقة لإعادة استخدام الشيفرة في اللغات التي لا تدعم الوراثة المتعددة مثل PHP. وتهدف السمات إلى إزالة بعض القيود التي تفرضها الوراثة المفردة وذلك بتمكين المطوّر من استخدام مجموعة من التوابع بحرية في عدد من الأصناف المستقلة عن بعضها في هيكلية أصناف مختلفة. وتحمل كلّ من السمات والأصناف دلالات تهدف إلى التقليل من التعقيد وتجنب المشاكل الشائعة التي ترتبط بالوراثة المتعددة والدوال المساعدة Mixins.
تعدّ السمات طريقة لإعادة استخدام الشيفرة في اللغات التي لا تدعم الوراثة المتعددة مثل PHP. وتهدف السمات إلى إزالة بعض القيود التي تفرضها الوراثة المفردة وذلك بتمكين المطوّر من استخدام مجموعة من التوابع بحرية في عدد من الأصناف المستقلة عن بعضها في هيكلية أصناف مختلفة. وتحمل كلّ من السمات والأصناف دلالات تهدف إلى التقليل من التعقيد وتجنب المشاكل الشائعة التي ترتبط بالوراثة المتعددة والدوال المساعدة Mixins.


سطر 56: سطر 304:
أضيف دعم الأصناف المجهولة إلى الإصدار السابع من PHP، وهذا النوع من الأصناف مفيد عند الحاجة إلى إنشاء نسخة واحدة بسيطة من الصنف.
أضيف دعم الأصناف المجهولة إلى الإصدار السابع من PHP، وهذا النوع من الأصناف مفيد عند الحاجة إلى إنشاء نسخة واحدة بسيطة من الصنف.


== [[PHP/OOP/overloading|التحميل الزائد]] ==
== [[PHP/overloading|التحميل الزائد]] ==
تقديم ميزة التحميل الزائد في PHP القدرة على إنشاء الخصائص والتوابع بصورة ديناميكية، وتعالج هذه العناصر الديناميكية بواسطة التوابع السحرية (magic methods) التي يمكن استخدامها في الصنف لأداء العديد من الوظائف.
تقديم ميزة التحميل الزائد في PHP القدرة على إنشاء الخصائص والتوابع بصورة ديناميكية، وتعالج هذه العناصر الديناميكية بواسطة التوابع السحرية (magic methods) التي يمكن استخدامها في الصنف لأداء العديد من الوظائف.


== [[PHP/OOP/iterations|Object Iteration]] ==
== [[PHP/object iteration|Object Iteration]] ==
يقدّم الإصدار الخامس من اللغة طريقة لتعريف العناصر ليكون بالإمكان المرور على قائمة من العناصر باستخدام العبارة <code>[[PHP/foreach|foreach]]</code> على سبيل المثال، وتستخدم جميع <nowiki/>[[PHP/OOP/visibility|الخصائص المرئية]] بصورة افتراضية لعملية المرور على العناصر.
يقدّم الإصدار الخامس من اللغة طريقة لتعريف العناصر ليكون بالإمكان المرور على قائمة من العناصر باستخدام العبارة <code>[[PHP/foreach|foreach]]</code> على سبيل المثال، وتستخدم جميع <nowiki/>[[PHP/properties visibility|الخصائص المرئية]] بصورة افتراضية لعملية المرور على العناصر.


== [[PHP/OOP/magic|التوابع السحرية]] ==
== [[PHP/magic|التوابع السحرية]] ==
التوابع السحرية في أصناف PHP هي <code>‎__construct()</code>‎ و <code>‎__destruct()</code>‎ و <code>‎__call()</code>‎ و <code>‎__callStatic()</code>‎ و <code>‎__get()</code>‎ و <code>‎__set()‎</code> و ‎<code>__isset()</code>‎ و ‎<code>__unset()‎‎</code> و<code>‎__sleep()</code>‎ و ‎<code>__wakeup()</code>‎ و <code>‎__toString()‎</code> و ‎<code>__invoke()‎</code> و ‎<code>_‎_set_state()‎</code> و ‎<code>__clone()</code>‎ و <code>‎__debugInfo()</code>‎. ولا يمكنك استخدام دوالّ تحمل هذه الأسماء في أي صنف ما لم تكن ترغب في الاستفادة من الوظيفة السحرية التي تتمتّع بها.
التوابع السحرية في أصناف PHP هي <code>‎__construct()</code>‎ و <code>‎__destruct()</code>‎ و <code>‎__call()</code>‎ و <code>‎__callStatic()</code>‎ و <code>‎__get()</code>‎ و <code>‎__set()‎</code> و ‎<code>__isset()</code>‎ و ‎<code>__unset()‎‎</code> و<code>‎__sleep()</code>‎ و ‎<code>__wakeup()</code>‎ و <code>‎__toString()‎</code> و ‎<code>__invoke()‎</code> و ‎<code>_‎_set_state()‎</code> و ‎<code>__clone()</code>‎ و <code>‎__debugInfo()</code>‎. ولا يمكنك استخدام دوالّ تحمل هذه الأسماء في أي صنف ما لم تكن ترغب في الاستفادة من الوظيفة السحرية التي تتمتّع بها.


== [[PHP/OOP/final|الكلمة المفتاحية final]] ==
== [[PHP/final|الكلمة المفتاحية final]] ==
قدّم الإصدار الخامس من اللغة الكلمة المفتاحية final والتي تمنع الأصناف الأبناء من التجاوز على توابع الصنف الأب وذلك بإضافة الكلمة المفتاحية قبل عبارة تعريف التابع. إذا استُخدمت الكلمة المفتاحية <code>final</code> في تعريف الصنف فإنّه يصبح غير قابل للتوسع.
قدّم الإصدار الخامس من اللغة الكلمة المفتاحية final والتي تمنع الأصناف الأبناء من التجاوز على توابع الصنف الأب وذلك بإضافة الكلمة المفتاحية قبل عبارة تعريف التابع. إذا استُخدمت الكلمة المفتاحية <code>final</code> في تعريف الصنف فإنّه يصبح غير قابل للتوسع.


== [[PHP/OOP/cloning|استنساخ الكائنات]] ==
== [[PHP/cloning objects|استنساخ الكائنات]] ==
أي نسخ الكائن مع خاصياته كلها.
أي نسخ الكائن مع خاصياته كلها.


== [[PHP/OOP/object-comparison|مقارنة الكائنات]] ==
== [[PHP/object comparison|مقارنة الكائنات]] ==
يمكن إجراء مقارنة بسيطة بين متغيرات الكائنات باستخدام عامل المقارنة (==)، وتكون نسختا الكائن متساويتين إن كانتا تملكان نفس المعاملات ونفس القيم (تقارن القيم باستخدام ==) وكانتا نسختين لنفس الصنف.
يمكن إجراء مقارنة بسيطة بين متغيرات الكائنات باستخدام عامل المقارنة (==)، وتكون نسختا الكائن متساويتين إن كانتا تملكان نفس المعاملات ونفس القيم (تقارن القيم باستخدام ==) وكانتا نسختين لنفس الصنف.


عند استخدام عامل التطابق (===) تكون متغيرات الكائنات متطابقة عندما تشير فقط وفقط إذا إلى النسخة نفسها من الصنف نفسه.
عند استخدام عامل التطابق (===) تكون متغيرات الكائنات متطابقة عندما تشير فقط وفقط إذا إلى النسخة نفسها من الصنف نفسه.


== [[PHP/OOP/typehinting|التلميح عن الأنواع]] ==
== [[PHP/typehinting|التلميح عن الأنواع]] ==
تسمح خاصية التصريح عن الأنواع للدوال بطلب النوع المحدّد من المعاملات في وقت الاستدعاء، وإن كانت القيمة المستدعاة ذات نوع مغاير، تطلق اللغة خطأ من نوع recoverable fatal في الإصدار 5، أما في الإصدار 7 فترمي اللغة استثناءً من نوع <code>TypeError</code>.
تسمح خاصية التصريح عن الأنواع للدوال بطلب النوع المحدّد من المعاملات في وقت الاستدعاء، وإن كانت القيمة المستدعاة ذات نوع مغاير، تطلق اللغة خطأ من نوع recoverable fatal في الإصدار 5، أما في الإصدار 7 فترمي اللغة استثناءً من نوع <code>TypeError</code>.


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


== [[PHP/OOP/late-static-bindings|الروابط الساكنة المتأخرة]] ==
== [[PHP/late static bindings|الروابط الساكنة المتأخرة]] ==
تضمن الإصدار 5.3.0 من PHP خاصية تدعى بالروابط الساكنة المتأخرة (late static bindings) والتي يمكن استخدامها للإشارة إلى الصنف المستدعى في سياق وراثة ساكنة.
تضمن الإصدار 5.3.0 من PHP خاصية تدعى بالروابط الساكنة المتأخرة (late static bindings) والتي يمكن استخدامها للإشارة إلى الصنف المستدعى في سياق وراثة ساكنة.


== [[PHP/OOP/references|الكائنات والمراجع]] ==
== [[PHP/objects references|الكائنات والمراجع]] ==
المرجع في PHP هو اختصار يتيح لمتغيرين مختلفين الكتابة إلى القيمة ذاتها. ومنذ الإصدار الخامس من اللغة، لم يعد متغير الكائن يتضمّن الكائن نفسه كقيمة على الإطلاق، بل يتضمّن فقط معرّفًا للكائن يتيح الوصول إلى الكائن الحقيقي. وعند تمرير الكائن كمعامل أو إعادته أو إسناده إلى متغير آخر، لا تكون هذه المتغيرات أسماء بديلة (aliases) بل تحمل نسخة من المعرّف الذي يشير إلى الكائن نفسه.
المرجع في PHP هو اختصار يتيح لمتغيرين مختلفين الكتابة إلى القيمة ذاتها. ومنذ الإصدار الخامس من اللغة، لم يعد متغير الكائن يتضمّن الكائن نفسه كقيمة على الإطلاق، بل يتضمّن فقط معرّفًا للكائن يتيح الوصول إلى الكائن الحقيقي. وعند تمرير الكائن كمعامل أو إعادته أو إسناده إلى متغير آخر، لا تكون هذه المتغيرات أسماء بديلة (aliases) بل تحمل نسخة من المعرّف الذي يشير إلى الكائن نفسه.


== ‎[[PHP/OOP/serialization|سَلسَلة الكائن]] ==
== ‎[[PHP/serialization|سَلسَلة الكائن]] ==
تعيد الدالة <code>serialize()‎‎</code> سلسلة نصية تتضمّن تمثيلًا لتدفق البايتات لأي قيمة يمكن تخزينها في PHP، ويمكن للدالة <code>unseriazlie()‎</code> استخدام هذه السلسلة النصية لإعادة إنشاء القيمة الأصلية للمتغيّر. يؤدي تطبيق الدالة <code>serialize()‎</code> على كائن ما لحفظ جميع المتغيرات الخاصة بذلك الكائن، أما التوابع فلا تحفظ وإنّما يحفظ اسم الصنف فقط.
تعيد الدالة <code>serialize()‎‎</code> سلسلة نصية تتضمّن تمثيلًا لتدفق البايتات لأي قيمة يمكن تخزينها في PHP، ويمكن للدالة <code>unseriazlie()‎</code> استخدام هذه السلسلة النصية لإعادة إنشاء القيمة الأصلية للمتغيّر. يؤدي تطبيق الدالة <code>serialize()‎</code> على كائن ما لحفظ جميع المتغيرات الخاصة بذلك الكائن، أما التوابع فلا تحفظ وإنّما يحفظ اسم الصنف فقط.


== [[PHP/OOP|سجل التغييرات]] ==
== سجل التغييرات ==
تعرض الصفحة سجلّ التغييرات الحاصلة على نموذج البرمجة كائنية التوجه في الإصدار الخامس من اللغة.
يعرض الجدول التالي سجلّ التغييرات الحاصلة على نموذج البرمجة كائنية التوجه في الإصدار الخامس من اللغة. يمكنك أن تجد التفاصيل والملاحظات المتعلّقة بهذه الميزات في الأقسام الخاصة بالبرمجة كائنية التوجّه في هذا الدليل.
 
{| class="wikitable"
!الإصدار
!الوصف
|-
|7.0.0
|لا يتسبب تعريف الخواص (المتوافقة) في سمتين مستخدمتين في إطلاق خطأ.
|-
|5.6.0
|إضافة التابع <code>‎__debugInfo()‎</code>
|-
|5.5.0
|إضافة الثابت السحري <code>‎::class</code>
|-
|5.5.0
|إضافة الكلمة المفتاحية <code>finally</code> للتعامل مع الاستثناءات
|-
|5.4.0
|إضافة السمات (traits).
|-
|5.4.0
|تعديل: إنْ عرّفَ صنفٌ مجردٌ توقيعًا للدالة البانية constructor فإنّها ستفرض الآن.
|-
|5.3.3
|تعديل: لا تعامل التوابع التي تحمل نفس اسم العنصر الأخير لصنف ينتمي إلى مجال أسماء كدالة بانية. لا يؤثر هذا التعديل على الأصناف غير المنتمية إلى مجال أسماء.
|-
|5.3.0
|تعديل: لم تعد الأصناف التي تطبق واجهات مع توابع تمتلك قيمًا افتراضية في النموذج الأولي مطلوبة لمطابقة القيمة الافتراضية للواجهة.
|-
|5.3.0
|تعديل: أصبح بالإمكان الإشارة إلى صنف بواسطة متغير (مثال <code>echo $classname::constant;</code>‎‎). لا يمكن أن تكون قيمة المتغير هذا كلمة مفتاحية (مثل <code>self</code>، أو <code>parent</code>، أو <code>static</code>).
|-
|5.3.0
|تعديل: ينطلق خطأ من نوع E_WARNING عند تعريف توابع إعادة التعريف السحرية كتوابع ساكنة static. كذلك تصبح قابلية الرؤية من نوع public أمرًا إلزاميًا.
|-
|5.3.0
|تعديل: قبل هذا الإصدار لم تكن الاستثناءات المرمية في دالة ‎<code>__autoload()</code>‎‎ تلتقط في كتلة <code>catch</code>، وكانت تؤدي إلى حدوث خطأ من نوع fatal. أصبحت الاستثناءات المرمية في دالة ‎<code>__autoload</code> تلتقط في كتلة <code>catch</code> بشرط واحد. في حال رمي استثناء خاص، فإنّ صنف الاستثناء الخاص يجب أن يكون معرّفًا. يمكن استخدام الدالة ‎<code>__autoload</code> تعاوديًا لتحميل صنف الاستثناء الخاص تلقائيًا.
|-
|5.3.0
|إضافة التابع ‎<code>__callStatic</code>.
|-
|5.3.0
|إضافة دعم كتلة heredoc و nowdoc في تعريف ثوابت وخواص الأصناف.
ملاحظة: يجب أن تتبع قيم heredoc نفس القواعد المفروضة على السلاسل النصّية المحاطة بعلامات اقتباس مزدوجة (مثل عدم استخدام المتغيرات).
|-
|5.3.0
|إضافة الروابط الساكنة اللاحقة
|-
|5.3.0
|إضافة التابع ‎<code>__invoke()‎</code>
|-
|5.2.0
|تعديل: كان التابع ‎<code>__toString()</code>‎ يستدعى فقط عند دمجه مباشرة مع <code>[[PHP/echo|echo]]</code> أو <code>[[PHP/print|print]]</code>. ولكن أصبح بالإمكان الآن استدعاؤه ضمن أي سياق نصّي (مثال: <code>[[PHP/printf|printf()‎]]</code> مع المعدِّل <code>‎%s</code>) ولكن ليس ضمن أي سياق من نوع آخر (مثال: المعدّل <code>‎%d</code>). منذ الإصدار 5.2.0 من اللغة يؤدي تحويل كائن لا يتضمّن التابع ‎<code>__toString</code> إلى سلسلة نصية إلى إطلاق خطأ من المستوى E_RECOVERABLE_ERROR.
|-
|5.1.3
|تعديل: أهملت الإصدارات السابقة للإصدار الخامس من اللغة استخدام الكلمة المفتاحية <code>var</code>، ويؤدي استخدامها إلى إطلاق خطأ من المستوى E_STRICT. لم يعد استخدام هذه الكلمة مهملًا في هذا الإصدار ولن يؤدي استخدامها إلى إطلاق خطأ.
|-
|5.1.0
|تعديل: يستدعى التابع الساكن ‎<code>__set_state()</code>‎ للأصناف المصدّرة بواسطة الدالة <code>[[PHP/var export|var_export()‎]]</code>.
|-
|5.1.0
|إضافة التابعين ‎<code>__isset()‎</code> و ‎<code>__unset()‎</code>
|}
== مصادر ==
== مصادر ==
* [http://php.net/manual/en/language.oop5.php صفحة OOP في توثيق PHP الرسمي.]
* [http://php.net/manual/en/language.oop5.php صفحة OOP في توثيق PHP الرسمي.]

المراجعة الحالية بتاريخ 14:28، 6 يونيو 2018

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

ومن الميزات التي قدّمها الإصدار الخامس قابلية الرؤية (visibility)، الأصناف والتوابع المجرّدة (abstract) والنهائية (final)، المزيد من التوابع السحرية (magical methods)، الواجهات (interfaces)، الاستنساخ (cloning) والإشارة إلى الأنواع (typehinting).

تعامل PHP الكائنات معاملة المراجع (references) أو المقابض (handles)، بمعنى أنّ كلّ متغيّر يتضمن كائنًا مرجعيًا وليس نسخة من الكائن كلّه. انظر الكائنات والمراجع.

نصيحة: راجع أيضًا دليل تسمية Userland.

الأساسيات

الصنف

تبدأ الصيغة البسيطة للتعريف عن الصنف بالكلمة المفتاحية class، يتبعها اسم الصنف ويتبعه زوج من الأقواس المعقوفة التي تحيط بالعبارات المسؤولة عن تعريف الخصائص والتوابع المُنتمية إلى الصنف.

يمكن أن يحمل الصنف أي اسم بشرط أن لا يكون كلمةً محجوزةً في PHP. يبدأ اسم الصنف النظامي بحرف أو شرطة سفلية، تتبعها أيّ عددٍ من الحروف أو الأرقام أو الشرطات السفلية. ويمكن التعبير عن هذه الصيغة باستخدام التعابير النمطية بالصورة التالية: ‎^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$‎.

يمكن أن يحتوي الصنف على ثوابت ومتغيرات (تسمّى "خصائص" [properties]) ودوالّ (تسمى "توابع" [methods]) خاصة به.

المثال 1: مثال عن تعريف بسيط للصنف

<?php
class SimpleClass
{
    // التصريح عن الخاصّية
    public $var = 'a default value';

    // التصريح عن التابع
    public function displayVar() {
        echo $this->var;
    }
}
?>

يكون المتغيّر الزائف ‎$this متاحًا عند استدعاء التابع من داخل سياق الكائن. يعدّ ‎$this مرجعًا للكائن المستدعي (عادة ما يكون الكائن الذي ينتمي إليه التابع، ولكن قد يكون كائنًا آخر، وذلك عندما تستدعى الدالة سكونيّاً [statically] ضمن سياق خاصّ بكائن آخر). منذ الإصدار 7.0.0 من اللغة يؤدي الاستدعاء الساكن لتابع غير ساكن يؤدي إلى عدم التعرّف على ‎$this داخل التابع. منذ الإصدار 5.6.0 من اللغة أصبحت عملية الاستدعاء الساكن لتابع غير ساكن من سياق غير متوافق عملية مهملة. أما في الإصدار 7.0.0 فقد أصبحت عملية الاستدعاء الساكن لتابغ غير ساكن مهملة بصورة عامّة (حتى لو استدعي التابع من سياق متوافق). يؤدي هذا النوع من الاستدعاء إلى إطلاق ملاحظة من نوع strict في الإصدارات السابقة للإصدار 5.6.0.

المثال 2: بعض الأمثلة على المتغير الزائف ‎$this

سنفترض في هذا المثال أنّ خاصية الإبلاغ عن الأخطار error_reporting معطّلة، وإلا ستطلق الشيفرة التالية ملاحظات من نوع deprecated و strict على التوالي، حسب إصدار اللغة المستخدم.

<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this is not defined.\n";
        }
    }
}

class B
{
    function bar()
    {
        A::foo();
    }
}

$a = new A();
$a->foo();

A::foo();
$b = new B();
$b->bar();

B::bar();
?>

تعطي الشيفرة السابقة النتيجة التالية في الإصدار 5 من اللغة:

$this is defined (A)
$this is not defined.
$this is defined (B)
$this is not defined.

أما الإصدار 7 من اللغة فيعطي النتائج التالية:

$this is defined (A)
$this is not defined.
$this is not defined.
$this is not defined.

الكلمة المفتاحية new

لإنشاء نسخة (instance) من الصنف يجب استخدام الكلمة المفتاحية new، ودائمًا ما يتمّ إنشاء الكائن إلا إذا كان يمتلك دالة بانية constructor ترمي استثناءً عند وقوع خطأ ما. يستحسن تعريف الأصناف قبل تهيئتها instantiation (وفي بعض الأحيان يكون الأمر مطلوبًا).

في حال استخدام سلسلة نصّية تحتوي اسم أحد الأصناف مع الكلمة المفتاحية new، فإن اللغة تنشئ نسخة جديدة من ذلك الصنف، وإن كان الصنف ضمن مجال أسماء معيّن، فيجب استخدام اسمه المؤهّل بالكامل (fully qualified name).

المثال 3: إنشاء نسخة من الصنف

<?php
$instance = new SimpleClass();

// يمكن القيام بهذا ضمن متغيّر
$className = 'SimpleClass';
$instance = new $className(); // new SimpleClass()
?>

من الممكن إنشاء كائن جديد ضمن سياق الصنف وذلك باستخدام العبارتين new self و new parent.

عند إسناد نسخة من الصنف إلى متغيّر جديد يصبح بمقدور المتغير الوصول إلى النسخة ذاتها كما هو حال الكائن الذي أُسند إليه، وتسلك عملية تمرير النسخ إلى الدوالّ السلوك ذاته. يمكن إنشاء نسخة من عنصر تمّ إنشاؤه مسبقًا عن طريق استنساخه.

المثال 4: إسناد الكائنات

<?php

$instance = new SimpleClass();

$assigned   =  $instance;
$reference  =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance and $reference become null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

يعطي المثال السابق النتيجة التالية:

NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}

قدّم الإصدار 5.3.0 من اللغة طريقتين جديدتين لإنشاء نسخ من الكائنات: المثال 5: إنشاء كائنات جديدة

<?php
class Test
{
    static public function getNew()
    {
        return new static;
    }
}

class Child extends Test
{}

$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);

$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);

$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>

تعطي الشيفرة السابقة المخرجات التالية:

bool(true)
bool(true)
bool(true)

قدّم الإصدار 5.4.0 من اللغة إمكانية الوصول إلى أحد أعضاء (أي الخصائص أو التوابع) الكائنات الجديدة باستخدام تعبير واحد: المثال 6: الوصول إلى أحد أعضاء كائن جديد

<?php
echo (new DateTime())->format('Y');
?>

تعطي الشيفرة السابقة المخرجات التالية:

2016

الخصائص والتوابع

تستقرّ خصائص وتوابع الصنف في مجال أسماء منفصل؛ لذا يمكن أن يحمل صنف وتابع الاسم ذاته. تقدّم اللغة صيغة واحدة للوصول إلى الخصائص أو التوابع، وتعتمد هذه العملية على السياق فقط، بمعنى أنّه هل أن طريقة الاستخدام هي الوصول إلى متغير أو استدعاء دالة.

المثال 7: الوصول إلى خاصية مقابل استدعاء تابع

<?php
class Foo
{
    public $bar = 'property';
    
    public function bar() {
        return 'method';
    }
}

$obj = new Foo();
echo $obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;

يعطي المثال السابق النتائج التالية:

property
method

هذا يعني أنّه ليس بالإمكان استدعاء دالة مجهولة مُسندة إلى خاصية بصورة مباشرة، بل يجب إسناد الخاصية إلى متغير في البداية على سبيل المثال. أما في الإصدار 7.0.0 فقد أصبح بالإمكان استدعاء مثل هذه الخاصّية مباشرة وذلك بإحاطتها بالأقواس. المثال 8: استدعاء دالة مجهولة مخزّنة في خاصّية

<?php
class Foo
{
    public $bar;
    
    public function __construct() {
        $this->bar = function() {
            return 42;
        };
    }
}

$obj = new Foo();

// منذ الإصدار
// PHP 5.3.0:
$func = $obj->bar;
echo $func(), PHP_EOL;

// يمكن استخدام هذه الصيغة في الإصدار
// PHP 7.0.0:
echo ($obj->bar)(), PHP_EOL;

تعطي الشيفرة السابقة النتيجة التالية:

42

الكلمة المفتاحية extends

يمكن للصنف أن يرث توابع وخصائص صنف آخر باستخدام الكلمة المفتاحية extends عند التصريح عن الصنف، ولا تتيح اللغة الوراثة من أكثر من صنف واحد.

يمكن تجاوز التوابع والخصائص الموروثة عن طريق إعادة التصريح عنها باستخدام نفس الأسماء التي تحملها في الصنف الأب. ولكن إن كان أحد التوابع معرّفًا في الصنف الأب باستخدام الكلمة المفتاحية final، فلا يمكن حينئذٍ تجاوز ذلك التابع. يمكن الوصول إلى التوابع المُتجاوز عليها أو الخصائص الساكنة في الصنف الأب عن طريق parent::‎.

يجب أن لا يتغير توقيع المعامل [parameter signature] عند تجاوز (override، أي إعادة تعريف) التوابع، وإلا ستطلق اللغة خطأً من المستوى E_STRICT، ولكن لا ينطبق هذا على الدالة البانية والتي تسمح بالتجاوز باستخدام معاملات مختلفة.

المثال 9: وراثة الأصناف

<?php
class ExtendClass extends SimpleClass
{
    // إعادة تعريف التابع الذي ينتمي للصنف الأب
    function displayVar()
    {
        echo "Extending class\n";
        parent::displayVar();
    }
}

$extended = new ExtendClass();
$extended->displayVar();
?>

تعطي الشيفرة السابقة النتيجة التالية:

Extending class
a default value

الكلمة المفتاحية ‎::class

أصبح بالإمكان استخدام الكلمة المفتاحية class في الإصدار 5.5 من اللغة للحصول على اسم الصنف. يمكن الحصول على سلسلة نصّية تتضمن الاسم المؤهّل بالكامل للصنف وذلك باستخدام الصيغة ClassName::class، وهذه الميزة مفيدة جدًّا عند التعامل مع الأصناف المنتمية إلى مجالات أسماء مختلفة.

المثال 10: الحصول على اسم الصنف

<?php
namespace NS {
    class ClassName {
    }
    
    echo ClassName::class;
}
?>

تعطي الشيفرة السابقة النتيجة التالية:

NS\ClassName

ملاحظة: تجري عملية الحصول على اسم الصنف باستخدام ‎::class في وقت التصريف. هذا يعني أنّه عند إنشاء السلسلة النصّية التي تحمل اسم الصنف فإنّ عملية التحميل التلقائي (autoloading) لم تحدث بعد، ونتيجة لذلك، تتوسّع أسماء الأصناف حتى لو كانت الصنف غير معرّفًا، ولن يحدث أيّ خطأً في هذه الحالة.

الخاصيات

تطلق تسمية "الخاصيات properties" على المتغيّرات المعرّفة ضمن الأصناف، وهناك تسميات أخرى مثل "المعاملات" أو "الحقول"، ولكن سنستخدم التسمية الأولى "الخاصيات" في هذا الدليل. تعرّف الخاصيات باستخدام إحدى الكلمات المفتاحية public، أو protected، أو private تتبعها عبارة تصريح عن متغير اعتيادي. يمكن أن يتضمّن هذا التصريح عملية تهيئة initialization، ولكن يجب أن تكون هذه التهيئة ذات قيمة ثابتة، بمعنى أنّه يجب أن تكون قابلة للمعالجة في وقت التصريف ويجب أن لا تعتمد على المعلومات المتاحة في وقت التشغيل لغرض المعالجة.

ثوابت الأصناف

يمكن تعريف قيم ثابتة لا يمكن تعديلها ولكل صنفٍ على حدة. تختلف الثوابت عن المتغيرات الاعتيادية في عدم استخدام العلامة $ للتصريح عنها أو استخدامها. تمتلك ثوابت الأصناف قابلية رؤية من نوع public.

التحميل التلقائي للأصناف

يُنشئ أغلب المطوّرين الذي يكتبون تطبيقات كائنية التوجه ملف PHP واحد لكل صنف. وهنا تظهر مشكلة مزعجة للغاية، وهي الحاجة إلى كتابة قائمة طويلة بالأصناف التي يجب تضمينها للبدء بتنفيذ الشيفرة (قائمة لكل صنف).

لم يعد هذا الأمر ضروريًا في الإصدار الخامس من اللغة، إذ تسجّل الدالة spl_autoload_register()‎‎ عددًا غير محدّدٍ من المحمّلات التلقائية لتتيح إمكانية التحميل التلقائي للأصناف والواجهات غير المعرّفة في ملف الشيفرة. يمنح تسجيلُ المحمّلات التلقائية اللغةَ فرصة أخيرة لتحميل الصنف أو الواجهة قبل أن تتوقف الشيفرة عن العمل وتطلق خطأً.

التوابع البانية والهادمة

تتيح لغة PHP للمطورين التصريح عن تابع بانٍ في الأصناف. كل صنف يمتلك تابعًا بانيًا يستدعي هذا التابع مع كل كائن جديد يُنشأ من ذلك الصنف؛ لهذا يعد هذا التابع ملائمًا لعمليات التهيئة التي قد يحتاج لها الكائن قبل استخدامه.

تقدّم PHP 5 مفهوم الدوال الهادمة وهو مفهوم شائع في لغات البرمجة كائنية التوجّه مثل C++‎. تُستدعى الدالة الهادمة عندما لا يكون هناك أي مرجع لكائن معين.

قابلية الرؤية

يمكن تعريف قابلية رؤية خاصية أو تابع أو (بدءًا من الإصدار 7.1.0 من اللغة) ثابت بأنّها إلحاق صيغة التصريح بإحدى الكلمات المفتاحية public، أو protected، أو private. يتيح التصريح من نوع public الوصول إلى أعضاء الصنف من أي مكان، ويتيح التصريح من نوع protected الوصول إلى الأعضاء من داخل الصنف نفسه أو الأصناف التي ترث الصنف أو تورّثه، أما التصريح من نوع private فيتيح الوصول إلى الأعضاء من داخل الصنف الذي عرِّف فيه ذلك العضو حصرًا.

وراثة الكائنات

وراثة الكائنات من المبادئ المعروفة في البرمجة كائنية التوجه وتستخدمه PHP في نموذج الكائنات الخاصّ بها. يؤثّر هذا المبدأ على العلاقة التي تربط بين الأصناف والكائنات.

عامل تحليل النطاق (::)

يسمح عامل تحليل النطاق (Scope Resolution Operator) بالوصول إلى الخاصيات والتوابع من نوع static، أو المتجاوز عليها أو الثوابت الخاصة بصنف معين.

الكلمة المفتاحية Static

يمكن استخدام static أيضًا لتعريف المتغيرات الساكنة والروابط الساكنة اللاحقة (late static bindings).

تجريد الأصناف

يقدّم الإصدار الخامس من اللغة الأصناف والتوابع المجرّدة. لا يمكن تهيئة الأصناف المجرّدة، وإذا احتوى الصنف على تابع مجرّد واحدٍ على الأقل فيجب أن يكون الصنف مجردًا أيضًا. تصرّح الأصناف المجرّدة ببساطة عن توقيع التابع (method's signature)، ولا يمكنها تعريف الاستخدام (implementation).

واجهات الكائنات

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

تعرّف الواجهات بنفس طريقة تعريف الأصناف، ولكن باستخدام الكلمة المفتاحية interface بدل الكلمة المفتاحية class ودون تعريف محتوى أيّ تابعٍ في الواجهة.

السمات

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

الأصناف المجهولة

أضيف دعم الأصناف المجهولة إلى الإصدار السابع من PHP، وهذا النوع من الأصناف مفيد عند الحاجة إلى إنشاء نسخة واحدة بسيطة من الصنف.

التحميل الزائد

تقديم ميزة التحميل الزائد في PHP القدرة على إنشاء الخصائص والتوابع بصورة ديناميكية، وتعالج هذه العناصر الديناميكية بواسطة التوابع السحرية (magic methods) التي يمكن استخدامها في الصنف لأداء العديد من الوظائف.

Object Iteration

يقدّم الإصدار الخامس من اللغة طريقة لتعريف العناصر ليكون بالإمكان المرور على قائمة من العناصر باستخدام العبارة foreach على سبيل المثال، وتستخدم جميع الخصائص المرئية بصورة افتراضية لعملية المرور على العناصر.

التوابع السحرية

التوابع السحرية في أصناف PHP هي ‎__construct()‎ و ‎__destruct()‎ و ‎__call()‎ و ‎__callStatic()‎ و ‎__get()‎ و ‎__set()‎ و ‎__isset()‎ و ‎__unset()‎‎ و‎__sleep()‎ و ‎__wakeup()‎ و ‎__toString()‎ و ‎__invoke()‎ و ‎_‎_set_state()‎ و ‎__clone()‎ و ‎__debugInfo()‎. ولا يمكنك استخدام دوالّ تحمل هذه الأسماء في أي صنف ما لم تكن ترغب في الاستفادة من الوظيفة السحرية التي تتمتّع بها.

الكلمة المفتاحية final

قدّم الإصدار الخامس من اللغة الكلمة المفتاحية final والتي تمنع الأصناف الأبناء من التجاوز على توابع الصنف الأب وذلك بإضافة الكلمة المفتاحية قبل عبارة تعريف التابع. إذا استُخدمت الكلمة المفتاحية final في تعريف الصنف فإنّه يصبح غير قابل للتوسع.

استنساخ الكائنات

أي نسخ الكائن مع خاصياته كلها.

مقارنة الكائنات

يمكن إجراء مقارنة بسيطة بين متغيرات الكائنات باستخدام عامل المقارنة (==)، وتكون نسختا الكائن متساويتين إن كانتا تملكان نفس المعاملات ونفس القيم (تقارن القيم باستخدام ==) وكانتا نسختين لنفس الصنف.

عند استخدام عامل التطابق (===) تكون متغيرات الكائنات متطابقة عندما تشير فقط وفقط إذا إلى النسخة نفسها من الصنف نفسه.

التلميح عن الأنواع

تسمح خاصية التصريح عن الأنواع للدوال بطلب النوع المحدّد من المعاملات في وقت الاستدعاء، وإن كانت القيمة المستدعاة ذات نوع مغاير، تطلق اللغة خطأ من نوع recoverable fatal في الإصدار 5، أما في الإصدار 7 فترمي اللغة استثناءً من نوع TypeError.

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

الروابط الساكنة المتأخرة

تضمن الإصدار 5.3.0 من PHP خاصية تدعى بالروابط الساكنة المتأخرة (late static bindings) والتي يمكن استخدامها للإشارة إلى الصنف المستدعى في سياق وراثة ساكنة.

الكائنات والمراجع

المرجع في PHP هو اختصار يتيح لمتغيرين مختلفين الكتابة إلى القيمة ذاتها. ومنذ الإصدار الخامس من اللغة، لم يعد متغير الكائن يتضمّن الكائن نفسه كقيمة على الإطلاق، بل يتضمّن فقط معرّفًا للكائن يتيح الوصول إلى الكائن الحقيقي. وعند تمرير الكائن كمعامل أو إعادته أو إسناده إلى متغير آخر، لا تكون هذه المتغيرات أسماء بديلة (aliases) بل تحمل نسخة من المعرّف الذي يشير إلى الكائن نفسه.

سَلسَلة الكائن

تعيد الدالة serialize()‎‎ سلسلة نصية تتضمّن تمثيلًا لتدفق البايتات لأي قيمة يمكن تخزينها في PHP، ويمكن للدالة unseriazlie()‎ استخدام هذه السلسلة النصية لإعادة إنشاء القيمة الأصلية للمتغيّر. يؤدي تطبيق الدالة serialize()‎ على كائن ما لحفظ جميع المتغيرات الخاصة بذلك الكائن، أما التوابع فلا تحفظ وإنّما يحفظ اسم الصنف فقط.

سجل التغييرات

يعرض الجدول التالي سجلّ التغييرات الحاصلة على نموذج البرمجة كائنية التوجه في الإصدار الخامس من اللغة. يمكنك أن تجد التفاصيل والملاحظات المتعلّقة بهذه الميزات في الأقسام الخاصة بالبرمجة كائنية التوجّه في هذا الدليل.

الإصدار الوصف
7.0.0 لا يتسبب تعريف الخواص (المتوافقة) في سمتين مستخدمتين في إطلاق خطأ.
5.6.0 إضافة التابع ‎__debugInfo()‎
5.5.0 إضافة الثابت السحري ‎::class
5.5.0 إضافة الكلمة المفتاحية finally للتعامل مع الاستثناءات
5.4.0 إضافة السمات (traits).
5.4.0 تعديل: إنْ عرّفَ صنفٌ مجردٌ توقيعًا للدالة البانية constructor فإنّها ستفرض الآن.
5.3.3 تعديل: لا تعامل التوابع التي تحمل نفس اسم العنصر الأخير لصنف ينتمي إلى مجال أسماء كدالة بانية. لا يؤثر هذا التعديل على الأصناف غير المنتمية إلى مجال أسماء.
5.3.0 تعديل: لم تعد الأصناف التي تطبق واجهات مع توابع تمتلك قيمًا افتراضية في النموذج الأولي مطلوبة لمطابقة القيمة الافتراضية للواجهة.
5.3.0 تعديل: أصبح بالإمكان الإشارة إلى صنف بواسطة متغير (مثال echo $classname::constant;‎‎). لا يمكن أن تكون قيمة المتغير هذا كلمة مفتاحية (مثل self، أو parent، أو static).
5.3.0 تعديل: ينطلق خطأ من نوع E_WARNING عند تعريف توابع إعادة التعريف السحرية كتوابع ساكنة static. كذلك تصبح قابلية الرؤية من نوع public أمرًا إلزاميًا.
5.3.0 تعديل: قبل هذا الإصدار لم تكن الاستثناءات المرمية في دالة ‎__autoload()‎‎ تلتقط في كتلة catch، وكانت تؤدي إلى حدوث خطأ من نوع fatal. أصبحت الاستثناءات المرمية في دالة ‎__autoload تلتقط في كتلة catch بشرط واحد. في حال رمي استثناء خاص، فإنّ صنف الاستثناء الخاص يجب أن يكون معرّفًا. يمكن استخدام الدالة ‎__autoload تعاوديًا لتحميل صنف الاستثناء الخاص تلقائيًا.
5.3.0 إضافة التابع ‎__callStatic.
5.3.0 إضافة دعم كتلة heredoc و nowdoc في تعريف ثوابت وخواص الأصناف.

ملاحظة: يجب أن تتبع قيم heredoc نفس القواعد المفروضة على السلاسل النصّية المحاطة بعلامات اقتباس مزدوجة (مثل عدم استخدام المتغيرات).

5.3.0 إضافة الروابط الساكنة اللاحقة
5.3.0 إضافة التابع ‎__invoke()‎
5.2.0 تعديل: كان التابع ‎__toString()‎ يستدعى فقط عند دمجه مباشرة مع echo أو print. ولكن أصبح بالإمكان الآن استدعاؤه ضمن أي سياق نصّي (مثال: printf()‎ مع المعدِّل ‎%s) ولكن ليس ضمن أي سياق من نوع آخر (مثال: المعدّل ‎%d). منذ الإصدار 5.2.0 من اللغة يؤدي تحويل كائن لا يتضمّن التابع ‎__toString إلى سلسلة نصية إلى إطلاق خطأ من المستوى E_RECOVERABLE_ERROR.
5.1.3 تعديل: أهملت الإصدارات السابقة للإصدار الخامس من اللغة استخدام الكلمة المفتاحية var، ويؤدي استخدامها إلى إطلاق خطأ من المستوى E_STRICT. لم يعد استخدام هذه الكلمة مهملًا في هذا الإصدار ولن يؤدي استخدامها إلى إطلاق خطأ.
5.1.0 تعديل: يستدعى التابع الساكن ‎__set_state()‎ للأصناف المصدّرة بواسطة الدالة var_export()‎.
5.1.0 إضافة التابعين ‎__isset()‎ و ‎__unset()‎

مصادر