Menu
flag Ar iconالعربيةdown icon

حلقة foreach في PHP: المفتاح والقيمة والفهرس والمرجع

تزور foreach ($array as $value) كل عنصر في مصفوفة، وتعطيك foreach ($array as $key => $value) المفتاح أيضًا. يتناول الدرس الحصول على الفهرس، وتغيير القيم بالمرجع ومشكلة unset()، وbreak وcontinue، والمصفوفات المتداخلة، وlist() في foreach، وبناء HTML.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

تنفّذ foreach ($array as $value) الكتلة مرة لكل عنصر، مع ضبط $value على العنصر الحالي. وللحصول على المفتاح أيضًا، اكتب foreach ($array as $key => $value).

تعمل foreach على أي مصفوفة، أيًّا كانت مفاتيحها، ولا تدير فيها عدادًا ولا تفحص طولًا. إنها الحلقة التي ستكتبها أكثر من غيرها في PHP.

المرور على المفاتيح والقيم

في $key => $value، الأسماء من اختيارك: $name => $age أو $id => $user أو $k => $v. في القائمة، المفاتيح هي المواضع 0, 1, 2. وفي المصفوفة الترابطية، هي المفاتيح النصية التي عرّفتها.

تُظهر الحلقة الأخيرة تفصيلًا يفاجئ الناس: المفتاح النصي الذي يشبه عددًا صحيحًا، مثل "1"، يُخزَّن على أنه العدد الصحيح 1. أما "01" فليس عددًا صحيحًا بصيغته القياسية، لذا يبقى نصًا.

الحصول على الفهرس في foreach

في القائمة، المفتاح هو الفهرس، لذا فإن foreach ($items as $i => $item) كل ما تحتاجه. وفي المصفوفة الترابطية لا يوجد موضع رقمي، فاحتفظ بعداد. ولمعاملة العنصر الأول أو الأخير معاملة مختلفة، قارن المفتاح بـ array_key_first() أو array_key_last().

تطبع الحلقة الأخيرة فاصلة بين الأسماء لكن ليس بعد آخرها. لهذه المهمة تحديدًا تكون implode(', ', array_keys($scores)) أقصر؛ أما فحص array_key_last() فهو لحين تحتاج الدورة الأخيرة إلى منطق مختلف، لا إلى فاصل مختلف فقط.

تغيير قيم المصفوفة في foreach (بالمرجع)

$value نسخة. الإسناد إليها لا يغيّر شيئًا في المصفوفة. لتغيير المصفوفة، إما أن تمر بالمرجع باستخدام &$value، أو تكتب عبر المفتاح.

كلاهما يعمل. لا يترك أسلوب المفتاح حالة مخفية بعد الحلقة، ولهذا تفضله فرق كثيرة. ولبناء مصفوفة جديدة بدل تغيير مصفوفة قائمة، array_map() خيار آخر.

سؤال ذو صلة: ماذا يحدث إذا أضفت عناصر أثناء المرور؟ تمر foreach العادية على المصفوفة كما كانت عند بدء الحلقة، لذا لا تُنشئ $prices[] = ... داخلها دورات إضافية. أما الحلقة بالمرجع فتمر على المصفوفة الحية وتزور العناصر الجديدة.

مشكلة unset() مع foreach بالمرجع

بعد foreach ($arr as &$v)، يبقى المتغير $v مرجعًا إلى آخر عنصر في المصفوفة. وإذا أعدت لاحقًا استخدام الاسم $v في حلقة عادية، فإن كل دورة تكتب في ذلك العنصر الأخير. شغّل هذا وانظر إلى العنصر الأخير:

تُسند الحلقة الثانية A، ثم B، ثم قيمة العنصر الأخير نفسه إلى $letters[2]، وفي الدورة الأخيرة تكون تلك الخانة تحمل B أصلًا. والإصلاح سطر واحد: ضع unset($v); مباشرة بعد كل foreach بالمرجع.

break وcontinue في foreach

تغادر break الحلقة، وتقفز continue إلى العنصر التالي. ومن الأنماط الشائعة البحث: مرّ حتى تجد ما تحتاجه، ثم break حتى لا تُفحص بقية المصفوفة.

في الحلقات المتداخلة، تغادر break 2 الحلقة الداخلية والحلقة المحيطة بها، وتقفز continue 2 إلى الدورة التالية من الحلقة الخارجية.

المصفوفات المتداخلة وforeach مع list()

صفوف البيانات مصفوفات داخل مصفوفة. مرّ على الصفوف، ثم على كل صف، أو استخرج الحقول مباشرة في سطر foreach بتفكيك المصفوفة: [$a, $b] للقوائم، و['key' => $var] للصفوف الترابطية. وlist($a, $b) هي الكتابة الأقدم لـ [$a, $b].

في صفحة التفكيك مزيد عن صيغة [...] =، بما في ذلك تخطي العناصر والأنماط المتداخلة.

بناء قائمة أو جدول HTML باستخدام foreach

في القالب، تُبقي صيغة النقطتين foreach (...): مع endforeach; الحلقة مقروءة بين الوسوم. تبني هذه الكتلة جدولًا، وعناوين الأعمدة روابط: انقر على أحدها في تبويب Page فيعمل السكربت نفسه مرة أخرى مع ضبط $_GET['sort']، فتعود الصفوف بترتيب جديد.

عادتان تستحقان النسخ من هذه الكتلة: قيمة sort القادمة من الرابط تُفحص مقابل قائمة بالأعمدة المسموحة قبل استخدامها، وكل قيمة تُطبع في HTML وقد تحتوي نصًا من المستخدم تمر عبر htmlspecialchars().

foreach على null أو مصفوفة فارغة أو كائن

المصفوفة الفارغة لا مشكلة فيها: لا يُنفَّذ الجسم أبدًا. أما null أو النص أو العدد فلا: تطبع PHP تحذيرًا وتتخطى الحلقة. مع $tags = null; foreach ($tags as $tag) تطبع:

Warning: foreach() argument must be of type array|object, null given in /var/www/html/index.php on line 4

يحدث هذا أكثر ما يحدث مع بيانات تغيب أحيانًا، مثل حقل اختياري في JSON بعد فك ترميزه. ارجع إلى مصفوفة فارغة باستخدام ??:

foreach ($data['tags'] ?? [] as $tag) {
    echo $tag;
}

كلمة object في تلك الرسالة حقيقية: تزور foreach على كائن خصائصه المرئية من مكان تشغيل الحلقة (العامة منها خارج الصنف)، مع اسم الخاصية مفتاحًا. أما الأصناف التي تنفّذ Iterator أو IteratorAggregate، والمولّدات، فتقرر بنفسها ما تراه foreach.

foreach مقابل for مقابل array_map

الاستخداممتى
foreachتريد كل عنصر، مع مفتاحه أو دونه. تعمل على أي مصفوفة، قائمة أو ترابطية.
forتعدّ (من 1 إلى 100، كل عنصر ثانٍ) أو تحتاج إلى الجيران بالفهرس ($a[$i - 1]). راجع حلقة for.
array_map()تبني مصفوفة جديدة بتحويل كل عنصر، غالبًا في سطر واحد مع fn.
array_filter()تُبقي فقط العناصر التي تجتاز اختبارًا.

طريقة سريعة للحسم: إذا كان جسم الحلقة يحسب قيمة جديدة لكل عنصر فقط، فإن array_map(fn($x) => $x * 2, $a) تقول ذلك في سطر واحد. وإذا كانت له آثار جانبية (طباعة، حفظ، عدّ عدة أشياء معًا) أو يحتاج إلى break، فاكتب foreach.

الأسئلة الشائعة

كيف أحصل على المفتاح والقيمة في حلقة foreach في PHP؟

استخدم صيغة =>: foreach ($array as $key => $value) { echo "$key: $value"; }. في القائمة العادية يكون المفتاح هو الفهرس (0 و1 و2)؛ وفي المصفوفة الترابطية يكون المفتاح النصي، مثل 'name'.

كيف أحصل على الفهرس في حلقة foreach في PHP؟

في القائمة، المفتاح هو الفهرس أصلًا: foreach ($items as $i => $item). وفي المصفوفة الترابطية، احتفظ بعداد خاص بك: اضبط $i = 0; قبل الحلقة و$i++ في نهاية كل دورة. وتخبرك array_key_first() وarray_key_last() بأول مفتاح وآخر مفتاح.

كيف أعدّل قيم المصفوفة داخل foreach في PHP؟

مرّ بالمرجع باستخدام &: foreach ($prices as &$price) { $price *= 2; } unset($price);. أو اكتب عبر المفتاح: foreach ($prices as $key => $price) { $prices[$key] = $price * 2; }. أما $price = ... العادية فلا تغيّر إلا نسخة.

لماذا تكرر foreach بالمرجع في PHP العنصر الأخير؟

بعد foreach ($arr as &$v)، تبقى $v مرجعًا إلى العنصر الأخير. ثم تكتب foreach ($arr as $v) ثانية كل قيمة في تلك الخانة الأخيرة، فتنتهي بتكرار القيمة قبل الأخيرة. استدعِ unset($v); مباشرة بعد حلقة المرجع.

كيف أخرج من حلقة foreach في PHP؟

توقف break; الحلقة فورًا وتقفز continue; إلى العنصر التالي. وفي الحلقات المتداخلة، تغادر break 2; الحلقتين الداخلية والخارجية.

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن