اذهب إلى المحتوى

المراجع (references) في PHP


سارة محمد2

الإسناد بالمرجعية (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

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...