السبب في أن المقالات المختلفة تقول إن أشياء مختلفة هي أنهم يتحدثون عن أنواع مختلفة من المرجع.
الشيء الرئيسي الذي يحدد ما إذا كان ينبغي تمرير المعلمة بالرجوع إليه هو توقيع الوظيفة نفسه ، ولم تتغير أساسيات هذا منذ PHP 4. فكر في هذا المثال:
function foo( $by_value, &$by_reference ) { /* ... */ }
$a = 1; $b = 2;
foo( $a, $b );
هنا ، المتغير الخارجي $a
يتم تمريرها إلى الوظيفة بالقيمة ، كما لو تم تعيينها كـ $by_value = $a;
- تغيير الى $by_value
لا يمكن أن تؤثر $a
. المتغير $b
ومع ذلك يتم تمريرها بالتزكية; ؛ تماما مثل تعيين النموذج $by_reference =& $b;
هذا يعني أن هناك متغيرًا واحدًا يشير إليه اسمين ، وأي مهمة لأحدها ستكون بمثابة مهمة لكليهما.
إذا قمت بتمرير قيمة "عادية" (سلسلة أو رقم أو صفيف) حسب القيمة ، يتم نسخ قيمتها فقط إلى المتغير الجديد. اعتبارا من PHP 5: إذا قمت بتمرير كائن حسب القيمة ، فإن شيئًا مختلفًا قليلاً يحدث - "القيمة" المنقولة هي مجرد مؤشر إلى نفس الكائن. هذا يعني أنه إذا $a
كان كائنًا ، يمكنك الاتصال $by_value->some_property = 42;
و $a->some_property
سيكون أيضا 42
. ومع ذلك ، إذا قمت بتعيين بعض القيمة الجديدة ل $by_value
, ، لا يزال لا يؤثر $a
.
حتى PHP 5.4, ، كان هناك إضافي طريقة لتمرير المعلمة بالرجوع إليها ، والتي كانت "فرض" السلوك المرجعي في وقت الاتصال. هذا يعني أنه يمكنك الكتابة foo(&$a, &$b);
و "التقاط" التغييرات التي تم إجراؤها $by_value
داخل foo()
وظيفة. كان الاعتماد على هذا عمومًا فكرة سيئة ، وبالتالي تمت إزالته. (لقد هبط في 5.4 لأنه كان مخصصًا للإزالة في PHP 6 ، ولكن تم وضع هذا المشروع على عقد غير محدد ، مع التغييرات الأصغر في 5.3 و 5.4).
أخيرًا ، يمكن للوظائف إرجاع متغير بالرجوع إليه (كما ناقش في الدليل هنا). هذا أمر غامض بعض الشيء ، لأنه يتطلب منك بالفعل أن تضعه &
في اثنين الأماكن: في بداية إعلان الوظيفة ، ليقول ذلك return
يجب أن تعني "إرجاع هذا المرجع المتغير" وليس "إرجاع هذه القيمة" ؛ وفي الكود الذي يطلق عليه ، لتعيين متغير لهذا المرجع ، بدلاً من مجرد نسخ قيمته. إليك مثال سخيف يجمع بين معلمة مرجعية مع عائد مرجعي (لا يتعين على الاثنين أن يجتمعوا ، إنه مجرد مثال):
function &bar(&$some_param) { return $some_param; }
$a = 1;
$b =& bar($a);
// $b and $a now point at the same variable, not just the same value
// it was passed into and out of a function, and assigned to a new variable,
// but all those operations were by reference
لاحظ أن الكثير من الناس يعتقدون عن طريق الخطأ أن تمرير متغير بالرجوع سيمنحهم فائدة أداء ، وكان هذا في كثير من الأحيان سببهم الوحيد لاستخدام وقت الاتصال بالمرجع. عادة ما يكون هذا خطأً ، حيث أن محرك Zend الذي يعمل على تشغيل PHP يستخدم تقنية تسمى "نسخة على الكتابة" لترك متغيرات متعددة لها نفس القيمة التي تشير إلى نفس قطعة الذاكرة ، حتى لو لم تكن مرتبطة بـ المراجع. في الواقع ، المهمة المرجعية بشكل عام هزائم هذا التحسين ، نظرًا للطريقة التي يتتبع بها المحرك المتغيرات في حالة النسخ على الكتابة.