اگر میخواهید روی هر عنصر آرایهای که در حال foreach روی آن هستید عملیاتی انجام دهید، استفاده از مراجع (reference) مفید خواهد بود. به عنوان مثال:
$arr = array(1, 2, 3, 4); foreach ($arr as &$value) { $value = $value * 2; } // $arr is now array(2, 4, 6, 8)
مشکل این است که، اگر مراقب نباشید می تواند عوارض و عواقب نامطلوبی داشته باشد. در مثال بالا، پس از اجرای کد، $value در اسکوپ باقی میماند و به آخرین عنصر آرایه اشاره میکند. بنابراین اگر در ادامه از $value استفاده کنیم، ناخواسته آخرین عنصر آرایه را تغییر می یابد.
به یاد داشته باشید: حلقه foreach ، اسکوپ (محدوده) ایجاد نمی کند
$array = [1, 2, 3]; echo implode(',', $array), "\n" foreach ($array as &$value) {} // by reference echo implode(',', $array), "\n" foreach ($array as $value) {} // by value (i.e., copy) echo implode(',', $array), "\n"
کد بالا خروجی زیر را خواهد داشت:
1,2,3 1,2,3 1,2,2
آخرین مقدار در خط سوم در واقع 2 است، نه 3.
پس از اجرای اولین حلقه foreach، آرایه بدون تغییر باقی می ماند، اما، همانطور که در بالا توضیح داده شد، $value به عنوان یک dangling reference به آخرین عنصر در آرایه اشاره می کند و باقی می ماند (بعد از اتمام حلقه ، از بین نمی رود).
در نتیجه، هنگامی که حلقه دوم اجرا می شود، به نظر می رسد چیزهای عجیب و غریب اتفاق می افتد. از آنجایی که $value اکنون با مقدار (یعنی با کپی) دسترسی می یابد، foreach هر عنصر آرایه را توی $value در هر مرحله کپی می کند.
مرحله اول: مقدار array[0] یعنی عدد 1 کپی می شود به $value اما توجه داشته باشید که $value از اتمام حلقه قبلی به array[2] رفرنس شده است پس array[2] مقدار 1 را دریافت می کند. اکنون $array بدین صورت می شود [1, 2, 1]
مرحله دوم: مقدار array[1] یعنی عدد 2 کپی می شود به $value (که رفرنس شده به array[2]) پس array[2] الان مقدار 2 را دریافت می کند. اکنون $array بدین صورت می شود [2, 2, 1]
مرحله سوم: مقدار array[2] یعنی عدد 2 کپی می شود به $value (که رفرنس شده به array[2]) پس array[2] الان مقدار 2 را دریافت می کند. اکنون $array بدین صورت می شود [2, 2, 1]
برای اینکه reference در حلقههای foreach بدون این نوع مشکلات استفاده کنیم، باید تابع unset را روی متغیر، بلافاصله پس از حلقه فراخوانی کنیم تا reference حذف شود. به عنوان مثال:
$arr = array(1, 2, 3, 4); foreach ($arr as &$value) { $value = $value * 2; } unset($value); // $value no longer references $arr[3]