الإسناد بالمرجعية (reference)
هذه المرحلة الأولى للمراجع، عندما تُسند بالمرجعية فإنّك تسمح بمشاركة متغيرين لنفس القيمة.
$foo = &$bar;
$foo
و$bar
متساويان هنا ولا يشيران إلى بعضهما إنما يشيران إلى نفس المكان (القيمة).
يمكنك أيضًا الإسناد بالمرجعية ضمن بنية اللغة array()
بالرغم من أنه ليس إسناد بالمرجعية بشكلٍ دقيق.
$foo = 'hi'; $bar = array(1, 2); $array = array(&$foo, &$bar[0]);
لاحظ أنّ المراجع داخل المصفوفة قد تكون خطرة، القيام بإسناد عادي (ليس بالمرجعية) مع مرجع على الجانب الأيمن لا يحوّل الجانب الأيسر إلى مرجع، لكن يُحتفظ بالمراجع داخل المصفوفات في هذه الإسنادات العادية، يُطبّق هذا أيضًا على استدعاءات الدالة عندما تُمرّر المصفوفة بالقيمة.
لا يقتصر الإسناد بالمرجعية على المتغيرات والمصفوفات فقط إنما يمكن استخدامه للدوال وكل ارتباطات التمرير بالمرجعية.
function incrementArray(&$arr) { foreach ($arr as &$val) { $val++; } } function &getArray() { static $arr = [1, 2, 3]; return $arr; } incrementArray(getArray()); var_dump(getArray()); // array [2, 3, 4]
في الشيفرة السابقة الإسناد هو مفتاح ضمن تعريف الدالة. لا يمكنك تمرير تعبير بالمرجع ويمكنك تمرير قيمة/متغير فقط.
الإعادة بالمرجعية
قد تحتاج أحيانًا الإعادة بالمرجعية بشكلٍ ضمني، وتعدّ الإعادة بالمرجعية ضروريةً عندما تريد استخدام دالة لإيجاد المتغير المرتبط بمرجع ما، ولا يستخدم لتحسين الأداء إنما يقوم المحرك بفعل هذا بمفرده، استخدم الإعادة بالمرجعية عندما يكون لديك سببًا تقنيًا واضحًا للقيام بذلك.
يوجد عدة نماذج للإعادة بالمرجعية متضمنةً المثال التالي:
function parent(&$var) { echo $var; $var = "updated"; } function &child() { static $a = "test"; return $a; } parent(child()); // "test" parent(child()); // "updated"
لا تقتصر الإعادة بالمرجعية على الدوال، يمكنك أيضًا القيام بالاستدعاء الضمني:
function &myFunction() { static $a = 'foo'; return $a; } $bar = &myFunction(); $bar = "updated" echo myFunction();
لا يمكنك أن ترجع استدعاء دالة بشكلٍ مباشر إنما يجب إسنادها إلى متغير قبل استخدامها، يمكنك أن تجرّب ذلك بكتابة echo &myFunction();
.
ملاحظات:
-
يجب تحديد مرجع
(&)
في كِلا المكانين اللذين تريد استخدامه بهما، أي في تعريف الدالة:
(function &myFunction() {...)
وفي استدعاء المرجع:
(function callFunction(&$variable) {... or &myFunction();)
-
يمكنك أن ترجع متغير فقط بالمرجع لذا اُستنسخ المتغير
$a
في المثال السابق، أي أنّه لا يمكنك أن ترجع تعبيرًا وإلا سيُنشأ خطأE_NOTICE
:
(Notice: Only variable references should be returned by reference in ......)
- الإعادة بالمرجعية له حالات استخدام رسمية لكن يجب التحذير من أنّه يجب استخدامه بعد استكشاف جميع الخيارات المحتملة الأخرى لتحقيق نفس الهدف.
التمرير بالمرجعية
يسمح لك التمرير بالمرجعية أن تمرر متغيرًا بالمرجع إلى دالة أو عنصر وهذا يساعدك على تعديل المتغير الأصلي.
لا يقتصر التمرير بالمرجعية على المتغيرات فقط، يمكن تمرير ما يلي بالمرجع:
-
تعليمات
new
مثلfoo(new SomeClass)
. - المراجع المُعادة من الدوال
المصفوفات
الاستخدام الشائع للتمرير بالمرجعية هو أن تعدّل القيم الابتدائية ضمن مصفوفة دون أن تضطر لإنشاء مصفوفات جديدة أو تملأ فضاء الاسم الخاص بك، يمكنك أن تمرر بالمرجع بأن تضيف &
قبل المتغير.
إليك مثال لاستخدام عنصر من مصفوفة وإضافة 1 إلى قيمته الابتدائية ببساطة:
$arr = array(1, 2, 3, 4, 5); foreach($arr as &$num) { $num++; }
لاحظ أنّه عندما تستخدم أي عنصر من $arr
فإنّ العنصر الأصلي سيتغير مع زيادة المرجع يمكنك أن تتأكد بالشيفرة التالية:
print_r($arr); // Array ( [0] => 2 [1] => 3 [2] => 4 [3] => 5 [4] => 6 )
ملاحظة: يجب أن تلاحظ عند استخدام التمرير بالمرجع ضمن الحلقات، في الشيفرة السابقة في نهاية الحلقة سيحمل المتغير $num
مرجعًا إلى عنصر المصفوفة الأخير، يمكن إسنادها بعد انتهاء الحلقة لمعالجة عنصر المصفوفة الأخير، يمكنك التأكد من أن هذا لن يحصل باستخدام unset()
بعد الحلقة مباشرةً:
$myArray = array(1, 2, 3, 4, 5); foreach($myArray as &$num) { $num++; } unset($num);
سيضمن لك هذا عدم حدوث أيّة مشاكل، يمكنك الاطلاع على مشكلة متعلقة بهذا الموضوع من هنا.
الدوال
الاستخدام الشائع الآخر للتمرير بالمرجعية هو في الدوال إذ يصبح تعديل القيمة الأساسية بسيطًا:
$var = 5; // تعريف الدالة function add(&$var) { $var++; } // استدعاء الدالة add($var);
يمكنك التحقق بطباعة القيمة الأساسية:
echo $var; // 6
هناك قيود مختلفة حول الدوال وهي حسب توثيق PHP الرسمي:
-
لا توجد إشارة مرجعية عند استدعاء الدالة، فقط عند تعريف الدالة، إذ أنّ تعريفات الدالة وحدها كافية لتمرير الوسيط بالمرجع. ستحصل على التحذير
"call-time pass-by-reference" is deprecated
عند استخدام&
فيfoo(&$a);
بدءًا من PHP 5.3.0 والتحذيرcall-time pass-by-reference was removed
بدءًا من PHP 5.4.0 لذا فإنّ استخدام هذه الإشارة سيرمي خطأً فادحًا (fatal error).
ترجمة -وبتصرف- للفصل [References] من كتاب PHP Notes for Professionals book
اقرأ أيضًا
- المقال التالي: المصفوفات (Arrays) في PHP
- المقال السابق: أهم العوامل (operators) الموجودة في PHP
- تعلم PHP
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.