PHP 'foreach' සැබවින්ම ක්‍රියාත්මක වන්නේ කෙසේද?


2030

කුමක්ද foreach, කරන්නේ කුමක්ද සහ එය භාවිතා කරන්නේ කෙසේද යන්න මා දන්නා බව පවසමින් මෙය උපසර්ග කිරීමට මට ඉඩ දෙන්න . මෙම ප්‍රශ්නය බොනෙට් යටතේ එය ක්‍රියා කරන්නේ කෙසේද යන්න ගැන සැලකිලිමත් වන අතර, “ඔබ අරාව සමඟ ලූපයක් ලූප කරන්නේ කෙසේද” යන තේමාවෙන් මට පිළිතුරු අවශ්‍ය නොවේ foreach.


දීර් ar කාලයක් තිස්සේ මම සිතුවේ foreachඑය අරාව සමඟම වැඩ කරන බවයි. එය අරාවෙහි පිටපතක් සමඟ ක්‍රියා කරන බවට බොහෝ යොමු කිරීම් මට හමු වූ අතර, එතැන් සිට මෙය කතාවේ අවසානය යැයි මම උපකල්පනය කර ඇත්තෙමි. නමුත් මම මෑතකදී මේ පිළිබඳව සාකච්ඡාවකට අවතීර්ණ වූ අතර, කුඩා පරීක්ෂණයකින් පසුව මෙය 100% සත්‍ය නොවන බව සොයා ගත්තා.

මා අදහස් කරන දේ පෙන්වීමට මට ඉඩ දෙන්න. පහත දැක්වෙන පරීක්ෂණ අවස්ථා සඳහා, අපි පහත දැක්වෙන අරාව සමඟ කටයුතු කරන්නෙමු:

$array = array(1, 2, 3, 4, 5);

පරීක්ෂණ නඩුව 1 :

foreach ($array as $item) {
  echo "$item\n";
  $array[] = $item;
}
print_r($array);

/* Output in loop:    1 2 3 4 5
   $array after loop: 1 2 3 4 5 1 2 3 4 5 */

මෙයින් පැහැදිලිව පෙනෙන්නේ අපි ප්‍රභව අරාව සමඟ කෙලින්ම වැඩ නොකරන බවයි - එසේ නොමැතිනම් ලූපය සදහටම පවතිනු ඇත, මන්ද අපි ලූපය තුළ නිරන්තරයෙන් අයිතම අරාව වෙතට තල්ලු කරන බැවිනි. නමුත් මෙය එසේ බව සහතික කර ගැනීම සඳහා:

පරීක්ෂණ නඩුව 2 :

foreach ($array as $key => $item) {
  $array[$key + 1] = $item + 2;
  echo "$item\n";
}

print_r($array);

/* Output in loop:    1 2 3 4 5
   $array after loop: 1 3 4 5 6 7 */

මෙය අපගේ ආරම්භක නිගමනයට උපස්ථ වේ, අපි ලූපය අතරතුර ප්‍රභව අරාවෙහි පිටපතක් සමඟ වැඩ කරන්නෙමු, එසේ නොමැතිනම් ලූපය තුළ නවීකරණය කරන ලද අගයන් අපට පෙනෙනු ඇත. ඒත්...

අපි අත්පොතෙන් බැලුවහොත් , මෙම ප්‍රකාශය අපට හමු වේ:

Foreach මුලින් ක්‍රියාත්මක කිරීමට පටන් ගත් විට, අභ්‍යන්තර අරාව දර්ශකය ස්වයංක්‍රීයව අරාවේ පළමු අංගයට යලි සකසනු ලැබේ.

හරි ... මෙයින් ඇඟවෙන්නේ foreachප්‍රභව අරාවෙහි අරාව දර්ශකය මත රඳා පවතින බවයි. නමුත් අපි ඔප්පු කර තිබෙන්නේ අපි ප්‍රභව අරාව සමඟ වැඩ නොකරන බවයි , නේද? හොඳයි, සම්පූර්ණයෙන්ම නොවේ.

පරීක්ෂණ නඩුව 3 :

// Move the array pointer on one to make sure it doesn't affect the loop
var_dump(each($array));

foreach ($array as $item) {
  echo "$item\n";
}

var_dump(each($array));

/* Output
  array(4) {
    [1]=>
    int(1)
    ["value"]=>
    int(1)
    [0]=>
    int(0)
    ["key"]=>
    int(0)
  }
  1
  2
  3
  4
  5
  bool(false)
*/

එබැවින්, අපි ප්‍රභව අරාව සමඟ කෙලින්ම වැඩ නොකර සිටියද, අපි ප්‍රභව අරාව දර්ශකය සමඟ කෙලින්ම වැඩ කරන්නෙමු - ලූපය අවසානයේ අරාව අවසානයේ දර්ශකය ඇති බව මෙය පෙන්වයි. මෙය සත්‍යයක් විය නොහැකි නම් - එය එසේ නම්, පරීක්ෂණ අවස්ථාව 1 සදහටම ලූප වේ.

PHP අත්පොතෙහි ද මෙසේ සඳහන් වේ:

Foreach අභ්‍යන්තර අරාව දර්ශකය මත රඳා පවතින බැවින් එය ලූපය තුළ වෙනස් කිරීම අනපේක්ෂිත හැසිරීමට හේතු විය හැක.

හොඳයි, එම "අනපේක්ෂිත හැසිරීම" යනු කුමක්දැයි සොයා බලමු (තාක්ෂණික වශයෙන්, ඕනෑම හැසිරීමක් බලාපොරොත්තු නොවූ දෙයක් බැවින් මම බලාපොරොත්තු විය යුතු දේ තවදුරටත් නොදනිමි).

පරීක්ෂණ නඩුව 4 :

foreach ($array as $key => $item) {
  echo "$item\n";
  each($array);
}

/* Output: 1 2 3 4 5 */

පරීක්ෂණ නඩුව 5 :

foreach ($array as $key => $item) {
  echo "$item\n";
  reset($array);
}

/* Output: 1 2 3 4 5 */

... එහි අනපේක්ෂිත කිසිවක් නැත, ඇත්ත වශයෙන්ම එය "ප්‍රභවයේ පිටපත" න්‍යායට සහය දක්වන බව පෙනේ.


ප්රශ්නය

මෙහි කුමක් සිදුවේද? PHP ප්‍රභව කේතය දෙස බැලීමෙන් නිසි නිගමනයකට එළඹීමට මගේ C-fu ප්‍රමාණවත් නොවේ, යමෙකුට එය මා වෙනුවෙන් ඉංග්‍රීසි භාෂාවට පරිවර්තනය කළ හැකි නම් මම එය අගය කරමි.

අරාවෙහි පිටපතක්foreach සමඟ ක්‍රියා කරන බව මට පෙනේ , නමුත් ප්‍රභව අරාවෙහි අරාව දර්ශකය ලූපයෙන් පසුව අරාවේ අවසානයට සකසයි.

  • මෙය නිවැරදිද සහ සම්පූර්ණ කතාවද?
  • එසේ නොවේ නම්, එය ඇත්තටම කරන්නේ කුමක්ද?
  • අරාව දර්ශකය ( each(), reset()සහ වෙනත්) වෙනස් කරන ශ්‍රිත භාවිතා කිරීමෙන් foreachලූපයේ ප්‍රති come ලයට බලපෑම් කළ හැකි යම් තත්වයක් තිබේද?

6
AveDaveRandom මෙය බොහෝ විට යා යුතු php-Internals ටැගයක් ඇත, නමුත් අනෙක් ටැග් 5 න් ඕනෑම එකක් ප්‍රතිස්ථාපනය කළ යුතුද යන්න තීරණය කිරීමට මම එය ඔබට භාර දෙමි.
මයිකල් බර්කොව්ස්කි

5
මකාදැමීමේ
හසුරුවකින්

150
මුලදී මම හිතුවා »ගෝෂ්, තවත් අලුත් ප්‍රශ්නයක්. ලියකියවිලි කියවන්න… හ්ම්, පැහැදිලිව නිර්වචනය නොකළ හැසිරීම «. එවිට මම සම්පූර්ණ ප්‍රශ්නය කියවා, මම පැවසිය යුතුයි: මම එයට කැමතියි. ඔබ ඒ සඳහා සෑහෙන වෑයමක් දැරූ අතර සියලු පරීක්ෂණ පත්‍රිකා ලිවීය. ps. ටෙස්ට්කේස් 4 සහ 5 සමානද?
knittl

21
අරාව දර්ශකය ස්පර්ශ වන්නේ ඇයි දැයි යන්න ගැන මදක් සිතා බලන්න: PHP මුල් පිටුවේ මුල් අරාවෙහි අභ්‍යන්තර අරාව දර්ශකය නැවත සකස් කර ගෙන යා යුතුය, මන්ද පරිශීලකයාට වර්තමාන අගය ( foreach ($array as &$value)) - PHP මුල් පිටුවේ වර්තමාන පිහිටීම දැන සිටිය යුතුය.
නිකෝ

4
E සීන්: IMHO, මූලික භාෂා අංගයන්ගේ සූක්ෂ්ම විස්තර කිරීමේදී PHP ප්‍රලේඛනය ඇත්තෙන්ම නරක ය. නමුත් සමහර විට, බොහෝ තාවකාලික විශේෂ අවස්ථා භාෂාවට
පිළිස්සීම නිසා විය හැකිය

Answers:


1664

foreach විවිධ වර්ගයේ අගයන් තුනකට වඩා පුනරාවර්තනයට සහය දක්වයි:

  • අරා
  • සාමාන්‍ය වස්තු
  • Traversable වස්තු

පහත දැක්වෙන අවස්ථා වලදී, විවිධ අවස්ථා වලදී නැවත ක්‍රියා කරන ආකාරය හරියටම පැහැදිලි කිරීමට මම උත්සාහ කරමි. වඩාත්ම සරලම අවස්ථාව වන්නේ Traversableවස්තූන් වන අතර, මේවා foreachඅත්‍යවශ්‍යයෙන්ම මෙම රේඛා ඔස්සේ කේත සඳහා සින්ටැක්ස් සීනි පමණි:

foreach ($it as $k => $v) { /* ... */ }

/* translates to: */

if ($it instanceof IteratorAggregate) {
    $it = $it->getIterator();
}
for ($it->rewind(); $it->valid(); $it->next()) {
    $v = $it->current();
    $k = $it->key();
    /* ... */
}

අභ්‍යන්තර පංති සඳහා, Iteratorසී ඒ මට්ටමේ අතුරු මුහුණත පිළිබිඹු කරන අභ්‍යන්තර API භාවිතා කිරීමෙන් සත්‍ය ක්‍රම ඇමතුම් වළක්වා ගත හැකිය .

අරා සහ සරල වස්තූන් අනුකරණය කිරීම සැලකිය යුතු ලෙස සංකීර්ණ වේ. පළමුවෙන්ම, PHP හි “අරා” සැබවින්ම ඇණවුම් කරන ලද ශබ්දකෝෂ වන අතර ඒවා මෙම ඇණවුමට අනුව ගමන් කරනු ඇත (ඔබ ඇතුළු දෙයක් භාවිතා නොකළ තාක් කල් එය ඇතුළත් කිරීමේ අනුපිළිවෙලට ගැලපේ sort). යතුරු වල ස්වාභාවික අනුපිළිවෙල (වෙනත් භාෂාවල ලැයිස්තු බොහෝ විට ක්‍රියා කරන ආකාරය) හෝ කිසිසේත්ම නිශ්චිත අනුපිළිවෙලක් නොමැති වීම (වෙනත් භාෂාවල ශබ්දකෝෂ බොහෝ විට ක්‍රියා කරන ආකාරය) මගින් මෙය නැවත කිරීමට විරුද්ධ වේ.

වස්තු ගුණාංග වෙනත් (ඇණවුම් කරන ලද) ශබ්ද කෝෂයක් ලෙස දේපල නම් ඒවායේ අගයන්ට අනුරූපණය කිරීම සහ දෘශ්‍යතාව හැසිරවීම ලෙස දැකිය හැකි බැවින් එය වස්තු සඳහා ද අදාළ වේ. බොහෝ අවස්ථාවන්හීදී, වස්තු ගුණාංග ඇත්ත වශයෙන්ම මෙම අකාර්යක්ෂම ආකාරයෙන් ගබඩා නොවේ. කෙසේ වෙතත්, ඔබ වස්තුවක් හරහා නැවත යෙදීම ආරම්භ කරන්නේ නම්, සාමාන්‍යයෙන් භාවිතා වන ඇසුරුම් නිරූපණය සැබෑ ශබ්ද කෝෂයක් බවට පරිවර්තනය වේ. එම අවස්ථාවෙහිදී, සරල වස්තූන්ගේ පුනරාවර්තනය අරා වල ක්‍රියාකාරීත්වයට බොහෝ සෙයින් සමාන වේ (මේ නිසා මම මෙහි බොහෝ දුරට සරල-වස්තු පුනරාවර්තනය ගැන සාකච්ඡා නොකරමි).

මේ වනතෙක් ගොඩක් හොඳයි. ශබ්ද කෝෂයක් ගැන කතා කිරීම එතරම් අපහසු විය නොහැක, නේද? නැවත ආරම්භයේදී අරාව / වස්තුව වෙනස් විය හැකි බව ඔබ තේරුම් ගත් විට ගැටළු ආරම්භ වේ. මෙය සිදුවිය හැකි විවිධ ක්‍රම තිබේ:

  • ඔබ යොමුව භාවිතා කර foreach ($arr as &$v)නැවත යොමු කරන්නේ නම් $arrඑය යොමු කිරීමක් බවට පත් වන අතර ඔබට එය නැවත සිදුකිරීමේදී වෙනස් කළ හැකිය.
  • PHP 5 හි ඔබ අගය අනුව පුනරාවර්තනය කළත් එය අදාළ වේ, නමුත් අරාව කලින් යොමු කිරීමක් විය: $ref =& $arr; foreach ($ref as $v)
  • වස්තූන් සතුව හැසිරවීමේ අර්ථකථන ඇත, බොහෝ ප්‍රායෝගික අරමුණු සඳහා ඒවා යොමු දැක්වීම් මෙන් හැසිරේ. එබැවින් පුනරාවර්තනයේදී වස්තූන් සැමවිටම වෙනස් කළ හැකිය.

පුනරාවර්තනයේදී වෙනස් කිරීමට ඉඩ දීමේ ගැටළුව වන්නේ ඔබ දැනට සිටින මූලද්‍රව්‍යය ඉවත් කිරීමයි. ඔබ දැනට සිටින්නේ කුමන අරාවෙහි මූලද්‍රව්‍යයද යන්න නිරීක්ෂණය කිරීමට ඔබ දර්ශකයක් භාවිතා කරන බව පවසන්න. මෙම මූලද්‍රව්‍යය දැන් නිදහස් කර ඇත්නම්, ඔබට ඉතිරිව ඇත්තේ දර්ශක දර්ශකයක් පමණි (සාමාන්‍යයෙන් එහි ප්‍රති se ලයක් ලෙස සෙග්ෆෝල්ට්).

මෙම ගැටළුව විසඳීමට විවිධ ක්‍රම තිබේ. PHP 5 සහ PHP 7 මේ සම්බන්ධයෙන් සැලකිය යුතු ලෙස වෙනස් වන අතර මම පහත සඳහන් හැසිරීම් දෙකම විස්තර කරමි. සාරාංශය නම්, PHP 5 හි ප්‍රවේශය තරමක් ගොළු වූ අතර සියලු ආකාරයේ අමුතු අද්භූත ගැටළු වලට තුඩු දෙන අතර, PHP 7 හි වැඩි සම්බන්ධිත ප්‍රවේශයක් මඟින් වඩාත් පුරෝකථනය කළ හැකි හා ස්ථාවර හැසිරීම් ඇති කරයි.

අවසාන මූලික වශයෙන්, මතකය කළමනාකරණය කිරීම සඳහා PHP යොමු ගණන් කිරීම සහ පිටපත් මත ලිවීම භාවිතා කරන බව සැලකිල්ලට ගත යුතුය. මෙයින් අදහස් කරන්නේ ඔබ අගයක් "පිටපත්" කරන්නේ නම්, ඔබ ඇත්ත වශයෙන්ම පැරණි අගය නැවත භාවිතා කර එහි විමර්ශන ගණන (refcount) වැඩි කරන බවයි. ඔබ යම් ආකාරයක වෙනස් කිරීමක් කළ පසු පමණක් සත්‍ය පිටපතක් ("අනුපිටපතක්" ලෙස හැඳින්වේ) සිදු කෙරේ. බලන්න කියලා බොරු කරමින් ඔබ මෙම මාතෘකාව මත වඩාත් පුළුල් හඳුන්වා දීම සඳහා.

PHP 5

අභ්‍යන්තර අරාව දර්ශකය සහ හැෂ්පොයින්ටර්

PHP 5 හි ඇති අරා වලට එක් "අභ්‍යන්තර අරා පොයින්ටරයක්" (IAP) ඇත, එය නිවැරදිව වෙනස් කිරීම් සඳහා සහය දක්වයි: මූලද්‍රව්‍යයක් ඉවත් කළ විට, IAP මෙම මූලද්‍රව්‍යයට යොමු කරන්නේ දැයි පරීක්ෂා කරනු ලැබේ. එය එසේ නම්, එය ඒ වෙනුවට ඊළඟ අංගයට දියුණු වේ.

අතර foreachඑම IAP සකස් කරලා පාවිච්චි කරන, අතිරේක යුද්ධය නිමාකර ඇත: එක් IAP ඇත, නමුත් එක් මාලාවක් බහු කොටසක් විය හැකි foreachවළළු:

// Using by-ref iteration here to make sure that it's really
// the same array in both loops and not a copy
foreach ($arr as &$v1) {
    foreach ($arr as &$v) {
        // ...
    }
}

එක් අභ්‍යන්තර අරා පොයින්ටරයක් ​​සහිත එකවර ලූප දෙකකට සහය දැක්වීම foreachසඳහා, පහත දැක්වෙන ෂෙනානිගන් සිදු කරයි: ලූප් බොඩි ක්‍රියාත්මක foreachකිරීමට පෙර, වත්මන් මූලද්‍රව්‍යයට දර්ශකයක් සහ එහි හැෂ් එක පෙර-පුරෝකථනයකට උපස්ථ HashPointerකරයි. ලූප් බොඩි ධාවනය වූ පසු, IAP තවමත් පවතී නම් මෙම මූලද්‍රව්‍යය වෙත නැවත සැකසෙනු ඇත. කෙසේ වෙතත් මූලද්‍රව්‍යය ඉවත් කර ඇත්නම්, අපි දැනට IAP සිටින ඕනෑම තැනක භාවිතා කරමු. මෙම යෝජනා ක්‍රමය බොහෝ දුරට කාරුණික ආකාරයේ වැඩකි, නමුත් ඔබට එයින් මිදිය හැකි අමුතු හැසිරීම් රාශියක් ඇත, ඒවායින් සමහරක් මම පහත නිරූපණය කරමි.

අරාව අනුපිටපත් කිරීම

IAP යනු අරාවෙහි දෘශ්‍යමාන ලක්ෂණයකි ( currentශ්‍රිත පවුල හරහා නිරාවරණය වේ), IAP ගණනය කිරීම්වල එවැනි වෙනස්කම් පිටපත් මත ලිවීමේ අර්ථ නිරූපණය යටතේ වෙනස් කිරීම් ලෙස දැක්විය හැකිය. මෙය, අවාසනාවකට, එයින් අදහස් වන්නේ foreachඑය බොහෝ විට එය නැවත නැවතත් අරාව අනුපිටපත් කිරීමට බල කරන බවයි. නිශ්චිත කොන්දේසි:

  1. අරාව යොමු කිරීමක් නොවේ (is_ref = 0). එය සඳහන් වේ නම්, ඒ සඳහා වෙනස් වේ යැයි කියනු ප්රචාරය කිරීමට, එම නිසා එය නැවත කළ යුතු නොවේ.
  2. අරාවෙහි refcount> 1 ඇත. නම් refcount1, පසුව අරාවට හවුල් වී නැති අතර එය අපි කෙලින්ම එය වෙනස් කිරීමට නිදහස්.

අරාව අනුපිටපත් නොකළේ නම් (is_ref = 0, refcount = 1), එවිට එය පමණක් refcountවැඩි වේ (*). මීට අමතරව, foreachයොමු කිරීම මඟින් භාවිතා කරන්නේ නම්, (අනුපිටපත් කළ හැකි) අරාව යොමු කිරීමක් බවට පත් වේ.

අනුපිටපත් සිදු වන උදාහරණයක් ලෙස මෙම කේතය සලකා බලන්න:

function iterate($arr) {
    foreach ($arr as $v) {}
}

$outerArr = [0, 1, 2, 3, 4];
iterate($outerArr);

$arrIAP වෙනස්කම් $arrකාන්දු වීම වැළැක්වීම සඳහා මෙහි අනුපිටපත් කරනු ලැබේ $outerArr. ඉහත කොන්දේසි අනුව, අරාව යොමු කිරීමක් නොවේ (is_ref = 0) එය ස්ථාන දෙකක භාවිතා වේ (refcount = 2). මෙම අවශ්‍යතාවය අවාසනාවන්ත වන අතර උපපෝෂිත ක්‍රියාවට නැංවීමේ පුරාවස්තුවකි (මෙහි නැවත සිදුකිරීමේදී වෙනස් කිරීම ගැන කිසිදු තැකීමක් නොමැත, එබැවින් අපට මුලින් ම IAP භාවිතා කිරීම අවශ්‍ය නොවේ).

(*) එම Incrementing refcountමෙතන ඉතුරු ශබ්ද, නමුත් පිටපතක්-on-ලිවීම් (ගව) semantics උල්ලංඝනය: ගව ආඥාවන් වෙනස් කිරීම් පමණක් refcount = මත සිදු කළ හැකි බව වන අතර අප එය refcount = 2 අරාවක් IAP වෙනස් කිරීමට යන්නේ එම මෙම අදහස් අගයන් 1 යි. මෙම උල්ලං violation නය හේතුවෙන් පරිශීලකයාට දෘශ්‍යමාන හැසිරීම් වෙනසක් සිදු වේ (COW සාමාන්‍යයෙන් පාරදෘශ්‍ය වන අතර), නැවත සැකසූ අරාවෙහි IAP වෙනස නිරීක්ෂණය කළ හැකි වනු ඇත - නමුත් අරාවෙහි පළමු IAP නොවන වෙනස් කිරීම තෙක් පමණි. ඒ වෙනුවට, "වලංගු" විකල්ප තුන වනු ඇත්තේ අ) සැමවිටම අනුපිටපත් කිරීම, ආ) වැඩි නොකරන්න refcountසහ එමඟින් පුනරාවර්තී අරාව අත්තනෝමතික ලෙස ලූපයේ වෙනස් කිරීමට ඉඩ දීම හෝ ඇ) IAP කිසිසේත් භාවිතා නොකරන්න (PHP 7 විසඳුම).

ස්ථානගත කිරීමේ අනුපිළිවෙල

පහත දැක්වෙන කේත සාම්පල නිසි ලෙස අවබෝධ කර ගැනීම සඳහා ඔබ දැනුවත් විය යුතු අවසාන ක්‍රියාත්මක කිරීමේ විස්තරයක් ඇත. සමහර දත්ත ව්‍යුහයක් හරහා “සාමාන්‍ය” ලූපය ව්‍යාජ කේතයෙන් පෙනේ:

reset(arr);
while (get_current_data(arr, &data) == SUCCESS) {
    code();
    move_forward(arr);
}

කෙසේ වෙතත් foreach, තරමක් විශේෂ හිම පියල්ලක් වීම නිසා දේවල් තරමක් වෙනස් ලෙස කිරීමට තෝරා ගනී:

reset(arr);
while (get_current_data(arr, &data) == SUCCESS) {
    move_forward(arr);
    code();
}

එනම්, ලූප් බොඩි ධාවනය වීමට පෙර අරාව දර්ශකය ඉදිරියට ගෙනයනු ලැබේ. මෙයින් අදහස් කරන්නේ ලූප් බොඩි මූලද්‍රව්‍යය මත ක්‍රියා කරන $iඅතර IAP දැනටමත් මූලද්‍රව්‍යයේ පවතින $i+1බවයි. පුනරාවර්තනයේදී වෙනස් කිරීම් පෙන්වන කේත සාම්පල සෑම විටම unsetවත්මන් මූලද්‍රව්‍යයට වඩා ඊළඟ මූලද්‍රව්‍යය වීමට හේතුව මෙයයි .

උදාහරණ: ඔබේ පරීක්ෂණ අවස්ථා

ඉහත විස්තර කර ඇති අංශ තුන මඟින් foreachක්‍රියාවට නැංවීමේ මුග්ධත්වය පිළිබඳ පූර්ණ හැඟීමක් ඔබට ලබා දිය යුතු අතර අපට උදාහරණ කිහිපයක් සාකච්ඡා කිරීමට ඉදිරියට යා හැකිය.

මෙම අවස්ථාවෙහිදී ඔබේ පරීක්ෂණ අවස්ථා වල හැසිරීම පැහැදිලි කිරීම සරල ය:

  • පරීක්ෂණ අවස්ථා වලදී 1 සහ 2 $arrayආරම්භ වන්නේ refcount = 1 සමඟිනි, එබැවින් එය අනුපිටපත් නොකරනු ඇත foreach: වැඩි කරන්නේ පමණි refcount. ලූප් බොඩි පසුව අරාව වෙනස් කරන විට (එම අවස්ථාවේදී refcount = 2 ඇත), අනුපිටපත එම අවස්ථාවේදී සිදුවනු ඇත. Foreach හි නවීකරණය නොකළ පිටපතක් මත දිගටම වැඩ කරනු ඇත $array.

  • පරීක්ෂණ අවස්ථාව 3 හි, නැවත වරක් අරාව අනුපිටපත් නොකෙරේ, එමඟින් විචල්‍යයේ foreachIAP වෙනස් කරනු ඇත $array. පුනරාවර්තනය අවසානයේ, IAP යනු NULL වේ (එහි අර්ථය පුනරාවර්තනය සිදු කර ඇත), එය eachනැවත පැමිණීමෙන් පෙන්නුම් කරයි false.

  • 5 දෙකම ටෙස්ට් අවස්ථාවල දී 4 සහ eachසහ resetඅතුරු යොමු කාර්යයන් වේ. එය ඔවුන්ට $arrayලබා දෙන refcount=2විට එය ඇත, එබැවින් එය අනුපිටපත් කළ යුතුය. එනිසා foreachනැවත වෙනම අරාවකට වැඩ කරනු ඇත.

උදාහරණ: currentforeach හි බලපෑම්

විවිධ අනුපිටපත් හැසිරීම් පෙන්වීමට හොඳ ක්‍රමයක් current()නම් foreachලූපයක් තුළ ශ්‍රිතයේ හැසිරීම නිරීක්ෂණය කිරීමයි . මෙම උදාහරණය සලකා බලන්න:

foreach ($array as $val) {
    var_dump(current($array));
}
/* Output: 2 2 2 2 2 */

current()අරාව වෙනස් නොකළද එය අතුරු ref ශ්‍රිතයක් බව ඔබ සැබවින්ම දැනගත යුතුය (ඇත්ත වශයෙන්ම: කැමති-යොමු කරන්න). එය අනෙක් සියලුම කාර්යයන් සමඟ හොඳින් ක්‍රීඩා කිරීම සඳහා විය යුතුය next. විසින්-යොමු සම්මත අරාව මෙසේ වෙන් කිරීමට ඇති අතර බව එයින් ගම්ය $arrayහා foreach-arrayවෙනස් වේ. ඒ 2වෙනුවට ඔබට ලැබීමට හේතුවද 1ඉහත සඳහන් කර ඇත: පරිශීලක කේතය ධාවනය කිරීමට පෙරforeach අරාව දර්ශකය ඉදිරියට ගෙන යයි, පසුව නොවේ. කේතය පළමු මූලද්රව්යයේ වුවද, foreachදැනටමත් දර්ශකය දෙවන ස්ථානයට ගෙන ඇත.

දැන් කුඩා වෙනස් කිරීමක් කිරීමට උත්සාහ කරමු:

$ref = &$array;
foreach ($array as $val) {
    var_dump(current($array));
}
/* Output: 2 3 4 5 false */

මෙන්න අපට is_ref = 1 නඩුව ඇත, එබැවින් අරාව පිටපත් නොකෙරේ (ඉහත ආකාරයටම). නමුත් දැන් එය යොමු කිරීමක් බැවින්, අතුරු ref current()ශ්‍රිතය වෙත යන විට අරාව තවදුරටත් අනුපිටපත් කළ යුතු නොවේ . මේ අනුව current()සහ foreachඑම අරාවක් මත වැඩ. foreachදර්ශකය ඉදිරියට යන ආකාරය නිසා ඔබ තවමත් එක් එක් හැසිරීම දැක ඇත .

අතුරු-පුනරාවර්තනයක් සිදු කිරීමේදී ඔබට එකම හැසිරීමක් ලැබේ:

foreach ($array as &$val) {
    var_dump(current($array));
}
/* Output: 2 3 4 5 false */

මෙහිදී වැදගත් කොටස නම්, foreach විසින් $arrayඑය යොමු කිරීම මඟින් පුනරාවර්තනය වන විට is_ref = 1 බවට පත් කරනු ඇත, එබැවින් මූලික වශයෙන් ඔබට ඉහත තත්වය සමාන වේ.

තවත් කුඩා විචලනයක්, මෙවර අපි අරාව වෙනත් විචල්‍යයකට පවරමු:

$foo = $array;
foreach ($array as $val) {
    var_dump(current($array));
}
/* Output: 1 1 1 1 1 */

මෙන්න $arrayපුඩුවක් ආරම්භ කරන විට 2 හි පරාවර්තනය වේ, එබැවින් එක් වරක් අපට ඇත්ත වශයෙන්ම අනුපිටපත පෙරට ගෙන යා යුතුය. මේ අනුව $array, foreach විසින් භාවිතා කරන අරාව මුල සිටම සම්පූර්ණයෙන්ම වෙන් කරනු ඇත. ලූපයට පෙර කොතැනක සිටියත් ඔබට IAP හි පිහිටීම ලැබෙන්නේ එබැවිනි (මේ අවස්ථාවේ දී එය පළමු ස්ථානයේ විය).

උදාහරණ: පුනරාවර්තනය අතරතුර වෙනස් කිරීම

පුනරාවර්තනයේදී සිදුවන වෙනස් කිරීම් සඳහා ගණනය කිරීමට උත්සාහ කිරීම යනු අපගේ සියලු පුරෝකථන කරදර ඇති වූ ස්ථානයයි, එබැවින් මෙම නඩුව සඳහා උදාහරණ කිහිපයක් සලකා බැලීමට එය සේවය කරයි.

එකම අරාව හරහා මෙම කැදැලි වළළු සලකා බලන්න (එහිදී එය එකම එකක් බව තහවුරු කර ගැනීම සඳහා අතුරු-පුනරාවර්තනය භාවිතා කරයි):

foreach ($array as &$v1) {
    foreach ($array as &$v2) {
        if ($v1 == 1 && $v2 == 1) {
            unset($array[1]);
        }
        echo "($v1, $v2)\n";
    }
}

// Output: (1, 1) (1, 3) (1, 4) (1, 5)

මෙහි අපේක්ෂිත කොටස වන්නේ (1, 2)මූලද්‍රව්‍යය 1ඉවත් කළ නිසා ප්‍රතිදානයෙන් අස්ථානගත වීමයි . බොහෝ විට බලාපොරොත්තු නොවූ දෙය නම් පිටත ලූපය පළමු මූලද්‍රව්‍යයෙන් පසුව නතර වීමයි. ඇයි ඒ?

මෙයට හේතුව ඉහත විස්තර කර ඇති කැදැලි-ලූප් හැක් ය: ලූප් බොඩි ධාවනය වීමට පෙර, වර්තමාන IAP පිහිටීම සහ හැෂ් a ට උපස්ථ HashPointerවේ. ලූප් බොඩි පසු එය ප්‍රතිෂ් ored ාපනය වේ, නමුත් මූලද්‍රව්‍යය තවමත් පවතී නම් පමණි, එසේ නොමැතිනම් වත්මන් IAP පිහිටීම (එය කුමක් වුවත්) ඒ වෙනුවට භාවිතා වේ. ඉහත උදාහරණයේ හරියටම මෙයයි: පිටත පුඩුවේ වත්මන් මූලද්‍රව්‍යය ඉවත් කර ඇත, එබැවින් එය IAP භාවිතා කරනු ඇත, එය දැනටමත් අභ්‍යන්තර ලූපය විසින් අවසන් කර ඇති බව සලකුණු කර ඇත!

HashPointerඋපස්ථ + ප්‍රතිෂ් restore ාපන යාන්ත්‍රණයේ තවත් ප්‍රති consequ ලයක් වනුයේ IAP reset()ආදිය හරහා සිදුවන වෙනස්කම් සාමාන්‍යයෙන් බලපාන්නේ නැත foreach. උදාහරණයක් ලෙස, පහත කේතය reset()කිසිසේත්ම නොතිබූ ආකාරයට ක්‍රියාත්මක වේ :

$array = [1, 2, 3, 4, 5];
foreach ($array as &$value) {
    var_dump($value);
    reset($array);
}
// output: 1, 2, 3, 4, 5

හේතුව, reset()තාවකාලිකව IAP වෙනස් කරන අතරම , එය ලූප් ශරීරයෙන් පසු වත්මන් foreach මූලද්‍රව්‍යයට ප්‍රතිෂ් ored ාපනය වේ. ලූපයට බලපෑමක් reset()ඇති කිරීමට බල කිරීම සඳහා, ඔබට අතිරේකව වත්මන් මූලද්‍රව්‍යය ඉවත් කළ යුතුය, එවිට උපස්ථ / ප්‍රතිස්ථාපන යාන්ත්‍රණය අසමත් වේ:

$array = [1, 2, 3, 4, 5];
$ref =& $array;
foreach ($array as $value) {
    var_dump($value);
    unset($array[1]);
    reset($array);
}
// output: 1, 1, 3, 4, 5

එහෙත්, එම උදාහරණ තවමත් බුද්ධිමත් ය. සැබෑ විනෝදය ආරම්භ වන්නේ ප්‍රතිෂ් HashPointerrestore ාපනය මූලද්‍රව්‍යයට දර්ශකයක් සහ එහි හැෂ් භාවිතා කරන බව ඔබට මතක නම් එය තවමත් පවතීද යන්න තීරණය කරයි. නමුත්: හෑෂ් isions ට්ටන ඇති අතර, දර්ශක නැවත භාවිතා කළ හැකිය! මෙයින් අදහස් කරන්නේ, අරාව යතුරු පරිස්සමින් තෝරා ගැනීමෙන්, foreachඉවත් කරන ලද මූලද්‍රව්‍යයක් තවමත් පවතින බව අපට විශ්වාස කළ හැකි බැවින් එය කෙලින්ම එයට පනින බවයි. උදාහරණයක්:

$array = ['EzEz' => 1, 'EzFY' => 2, 'FYEz' => 3];
$ref =& $array;
foreach ($array as $value) {
    unset($array['EzFY']);
    $array['FYFY'] = 4;
    reset($array);
    var_dump($value);
}
// output: 1, 4

මෙහිදී අපි සාමාන්‍යයෙන් 1, 1, 3, 4කලින් නියමයන්ට අනුව ප්‍රතිදානය අපේක්ෂා කළ යුතුය . සිදුවන්නේ කෙසේද යන්න 'FYFY'ඉවත් කරන ලද මූලද්‍රව්‍යයට සමාන හැෂ් එකක් ඇති අතර, මූලද්‍රව්‍යය 'EzFY'ගබඩා කිරීම සඳහා එකම මතක ස්ථානය නැවත භාවිතා කිරීමට විබෙදන්නා සිදු වේ. එබැවින් foreach අවසන් වන්නේ අළුතින් ඇතුළු කරන ලද මූලද්‍රව්‍යයට කෙලින්ම පැනීමෙනි.

පුඩුවක් අතරතුර නැවත සැකසූ වස්තුව ආදේශ කිරීම

මා සඳහන් කිරීමට කැමති අවසාන අමුතුම අවස්ථාව නම්, ලූපය තුළදී නැවත සැකසූ වස්තුව ආදේශ කිරීමට PHP ඔබට ඉඩ සලසයි. එබැවින් ඔබට එක් අරාවකින් නැවත යෙදීම ආරම්භ කළ හැකි අතර පසුව එය වෙනත් අරාවකින් අඩක් ආදේශ කරන්න. නැතහොත් අරාව මත නැවත යෙදීම ආරම්භ කර එය වස්තුවකින් ආදේශ කරන්න:

$arr = [1, 2, 3, 4, 5];
$obj = (object) [6, 7, 8, 9, 10];

$ref =& $arr;
foreach ($ref as $val) {
    echo "$val\n";
    if ($val == 3) {
        $ref = $obj;
    }
}
/* Output: 1 2 3 6 7 8 9 10 */

මෙම අවස්ථාවේ දී ඔබට දැකිය හැකි පරිදි, ආදේශනය සිදු වූ වහාම PHP අනෙක් ආයතනය ආරම්භයේ සිටම නැවත ආරම්භ කිරීමට පටන් ගනී.

PHP 7

කඩිනම් අනුකාරක

ඔබට තවමත් මතක නම්, අරාව පුනරාවර්තනයේ ඇති ප්‍රධාන ගැටළුව වූයේ මූලද්‍රව්‍ය ඉවත් කිරීම හැසිරවිය යුතු ආකාරයයි. පීඑච්පී 5 මේ සඳහා තනි අභ්‍යන්තර අරාව දර්ශකයක් (අයිඒපී) භාවිතා කළ අතර එය තරමක් උපපෝෂිත විය, මන්දයත් එක් වර්‍ග දර්ශකයක් දිගු කළ යුතු වූ අතර එකවර එකවර පුරෝකථනය කළ හැකි ලූප සහ ඊටreset() ඉහළින් අන්තර්ක්‍රියා කිරීමට ය.

PHP 7 වෙනස් ප්‍රවේශයක් භාවිතා කරයි, එනම්, එය අත්තනෝමතික ලෙස බාහිර, ආරක්ෂිත හැෂ් ටේබල් ඉරේටරයක් ​​නිර්මාණය කිරීමට සහාය වේ. මෙම අනුකාරක අරාවෙහි ලියාපදිංචි කළ යුතු අතර, එතැන් සිට ඒවාට IAP හා සමාන අර්ථකථන ඇත: අරාව මූලද්‍රව්‍යයක් ඉවත් කළ හොත්, එම මූලද්‍රව්‍යය වෙත යොමු කරන සියලුම හැෂ් ටේබල් අනුකාරක ඊළඟ මූලද්‍රව්‍යය දක්වා ඉදිරියට යනු ඇත.

මේ මාර්ගයෙන් foreachතවදුරටත් IAP භාවිතා කරනු ඇත සියලු දී . මෙම foreachලූපය පරම ප්රතිඵල මත කිසිදු බලපෑමක් කරනු ඇත current()සහ ආදිය එහි ම හැසිරීම වැනි කාර්යයන් බලපෑමට නොවන්නේ ය reset()ආදිය

අරාව අනුපිටපත් කිරීම

PHP 5 සහ PHP 7 අතර තවත් වැදගත් වෙනසක් අරාව අනුපිටපත් කිරීම හා සම්බන්ධ වේ. දැන් IAP තවදුරටත් භාවිතා නොකෙරේ, අතුරු අගය අරාව නැවත කිරීම මඟින් සෑම අවස්ථාවකම refcountවර්ධකයක් (අරාව අනුපිටපත් කිරීම වෙනුවට) සිදු කරයි. foreachලූපය තුළ අරාව වෙනස් කර ඇත්නම් , එම අවස්ථාවේදී අනුපිටපතක් සිදුවනු ඇත (පිටපත් මත ලිවීමට අනුව) සහ foreachපැරණි අරාව මත දිගටම ක්‍රියා කරයි.

බොහෝ අවස්ථාවන්හීදී, මෙම වෙනස විනිවිද පෙනෙන අතර වඩා හොඳ කාර්ය සාධනයක් හැර වෙනත් බලපෑමක් නැත. කෙසේ වෙතත්, එය වෙනස් හැසිරීම් වල ප්‍රති results ලයක් වන එක් අවස්ථාවක් තිබේ, එනම් අරාව කලින් යොමු කිරීමක් වූ අවස්ථාව:

$array = [1, 2, 3, 4, 5];
$ref = &$array;
foreach ($array as $val) {
    var_dump($val);
    $array[2] = 0;
}
/* Old output: 1, 2, 0, 4, 5 */
/* New output: 1, 2, 3, 4, 5 */

මීට පෙර යොමු-අරා වල අගය අනුව නැවත යෙදීම විශේෂ අවස්ථා විය. මෙම අවස්ථාවෙහිදී, අනුපිටපතක් සිදු නොවූ අතර, පුනරාවර්තනයේදී අරාවෙහි සියලු වෙනස් කිරීම් ලූපය මගින් පිළිබිඹු වේ. PHP 7 හි මෙම විශේෂ අවස්ථාව අහෝසි වී ඇත: අරාවෙහි අතුරු-අගය නැවත සැකසීම සෑම විටම මුල් මූලද්‍රව්‍යයන් මත ක්‍රියා කරමින්, ලූපය තුළ සිදුවන වෙනස් කිරීම් නොසලකා හරිනු ඇත.

ඇත්ත වශයෙන්ම මෙය අතුරු විමර්ශන ක්‍රියාවලියට අදාළ නොවේ. ඔබ අතුරු-යොමු යොමු කරන්නේ නම්, සියලු වෙනස් කිරීම් ලූපය මගින් පිළිබිඹු වේ. සරල වස්තූන්ගේ අතුරු-අගය පුනරාවර්තනය සඳහා ද මෙය අදාළ වේ:

$obj = new stdClass;
$obj->foo = 1;
$obj->bar = 2;
foreach ($obj as $val) {
    var_dump($val);
    $obj->bar = 42;
}
/* Old and new output: 1, 42 */

මෙය වස්තූන්ගේ අතුරු හැසිරවීමේ අර්ථ නිරූපණය පිළිබිඹු කරයි (එනම් ඒවා අතුරු වටිනාකම් සන්දර්භය තුළ පවා යොමු දැක්වීම් මෙන් හැසිරේ).

උදාහරණ

ඔබගේ පරීක්ෂණ අවස්ථා වලින් ආරම්භ වන උදාහරණ කිහිපයක් සලකා බලමු:

  • පරීක්ෂණ අවස්ථා 1 සහ 2 එකම ප්‍රතිදානය රඳවා ගනී: අතුරු-අගය අරාව පුනරාවර්තනය සෑම විටම මුල් මූලද්‍රව්‍ය මත ක්‍රියා කරයි. (මෙම අවස්ථාවේ දී, ඒකාකාර refcountingහා අනුපිටපත් හැසිරීම PHP 5 සහ PHP 7 අතර හරියටම සමාන වේ).

  • පරීක්ෂණ අවස්ථාව 3 වෙනස් වේ: Foreachතවදුරටත් IAP භාවිතා නොකරයි, එබැවින් ලූපයට එය each()බලපාන්නේ නැත. එයට පෙර සහ පසු එකම ප්‍රතිදානය ඇත.

  • පරීක්ෂණ අවස්ථා 4 සහ 5 එකම මට්ටමක පවතී : each()සහ reset()IAP වෙනස් කිරීමට පෙර අරාව අනුපිටපත් කරනු ඇත, foreachතවමත් මුල් අරාව භාවිතා කරයි. (අරාව බෙදාගෙන තිබුණත් IAP වෙනස වැදගත් වනු ඇත.)

දෙවන උදාහරණ මාලාව current()විවිධ reference/refcountingවින්‍යාසයන් යටතේ හැසිරීම හා සම්බන්ධ විය . මෙය තවදුරටත් අර්ථවත් නොවේ, current()ලූපයට සම්පූර්ණයෙන්ම බලපාන්නේ නැති නිසා එහි ප්‍රතිලාභ අගය සැමවිටම එලෙසම පවතී.

කෙසේ වෙතත්, පුනරාවර්තනයේදී සිදුවන වෙනස් කිරීම් සලකා බැලීමේදී අපට සිත්ගන්නා සුළු වෙනස්කම් කිහිපයක් ලැබේ. නව හැසිරීම් සනීපාරක්ෂාව ඔබ සොයා ගනු ඇතැයි මම බලාපොරොත්තු වෙමි. පළමු උදාහරණය:

$array = [1, 2, 3, 4, 5];
foreach ($array as &$v1) {
    foreach ($array as &$v2) {
        if ($v1 == 1 && $v2 == 1) {
            unset($array[1]);
        }
        echo "($v1, $v2)\n";
    }
}

// Old output: (1, 1) (1, 3) (1, 4) (1, 5)
// New output: (1, 1) (1, 3) (1, 4) (1, 5)
//             (3, 1) (3, 3) (3, 4) (3, 5)
//             (4, 1) (4, 3) (4, 4) (4, 5)
//             (5, 1) (5, 3) (5, 4) (5, 5) 

ඔබට පෙනෙන පරිදි, පිටත පුඩුවක් පළමු පුනරාවර්තනයෙන් පසුව තවදුරටත් නතර නොවේ. හේතුව, ලූප දෙකම දැන් මුළුමනින්ම වෙනම හැෂ් ටේබල් ඉරේටරයන් ඇති අතර, හවුල් අයි.ඒ.පී හරහා ලූප දෙකේම හරස් දූෂණයක් තවදුරටත් නොමැත.

දැන් සවි කර ඇති තවත් අමුතු දාරයක්, එකම හැෂ් ඇති මූලද්‍රව්‍ය ඉවත් කර එකතු කළ විට ඔබට ලැබෙන අමුතු බලපෑමයි:

$array = ['EzEz' => 1, 'EzFY' => 2, 'FYEz' => 3];
foreach ($array as &$value) {
    unset($array['EzFY']);
    $array['FYFY'] = 4;
    var_dump($value);
}
// Old output: 1, 4
// New output: 1, 3, 4

මීට පෙර හැෂ්පොයින්ටර් ප්‍රතිස්ථාපන යාන්ත්‍රණය නව මූලද්‍රව්‍යයට දකුණට පැන්නේ එය ඉවත් කළ මූලද්‍රව්‍යයට සමාන බව පෙනෙන නිසා (හැෂ් හා පොයින්ටරය ගැටීමෙන්). අපි තවදුරටත් කිසිවක් සඳහා මූලද්‍රව්‍ය හැෂ් මත රඳා නොසිටින බැවින් මෙය තවදුරටත් ගැටළුවක් නොවේ.


4
Ab බාබා එය කරයි. එය $foo = $array
ශ්‍රිතයකට යොමු කිරීම ලූපයට

33
Zval යනු කුමක්දැයි ඔබ නොදන්නා අය සඳහා කරුණාකර සාරා ගොල්මන්ගේ blog.golemon.com/2007/01/youre-being-lied-to.html
shu zOMG chen

1
සුළු නිවැරදි කිරීම: ඔබ බාල්දිය ලෙස හඳුන්වන දෙය සාමාන්‍යයෙන් හැෂ් ටේබල් එකක බාල්දිය ලෙස හැඳින්වේ. සාමාන්‍යයෙන් බාල්දිය යනු එකම හැෂ්% ප්‍රමාණයේ ඇතුළත් කිරීම් සමූහයකි. සාමාන්‍යයෙන් ප්‍රවේශයක් ලෙස හැඳින්වෙන දේ සඳහා ඔබ එය භාවිතා කරන බව පෙනේ. සම්බන්ධිත ලැයිස්තුව බාල්දි මත නොව ප්‍රවේශයන්හි ඇත.
unbeli

12
@unbeli මම PHP විසින් අභ්‍යන්තරව භාවිතා කරන පාරිභාෂිතය භාවිතා කරමි. මෙම Bucket); නියෝගය සඳහා එහි පූරක ගැටුම් හා ද දෙයාකාරයකින් සම්බන්ධ ලැයිස්තුව කොටසක් සඳහා දෙයාකාරයකින් සම්බන්ධ ලැයිස්තුව කොටසක්
NikiC

4
නියම පිළිතුරු. මම හිතන්නේ ඔබ අදහස් කළේ කොතැනකවත් iterate($outerArr);නොවේ iterate($arr);.
niahoo

117

උදාහරණයක් ලෙස 3 ඔබ අරාව වෙනස් නොකරයි. අනෙක් සියලුම උදාහරණ වලදී ඔබ අන්තර්ගතය හෝ අභ්‍යන්තර අරාව දර්ශකය වෙනස් කරයි. පැවරුම් ක්‍රියාකරුගේ අර්ථ නිරූපණය නිසා PHP අරා සම්බන්ධයෙන් මෙය වැදගත් වේ.

PHP හි අරා සඳහා පැවරුම් ක්‍රියාකරු කම්මැලි ක්ලෝනයක් මෙන් වැඩ කරයි. අරාව අඩංගු එක් විචල්‍යයක් තවත් විචල්‍යයකට පැවරීමෙන් බොහෝ භාෂාවන් මෙන් නොව අරාව ක්ලෝන කරනු ඇත. කෙසේ වෙතත්, නියම ක්ලෝන කිරීම අවශ්‍ය නොවන්නේ නම් එය සිදු නොවේ. මෙයින් අදහස් කරන්නේ ක්ලෝනය සිදුවන්නේ එක් විචල්‍යයක් වෙනස් කළ විට පමණක් (පිටපත්-ලිවීම).

මෙන්න උදාහරණයක්:

$a = array(1,2,3);
$b = $a;  // This is lazy cloning of $a. For the time
          // being $a and $b point to the same internal
          // data structure.

$a[] = 3; // Here $a changes, which triggers the actual
          // cloning. From now on, $a and $b are two
          // different data structures. The same would
          // happen if there were a change in $b.

ඔබගේ පරීක්ෂණ අවස්ථා වෙත නැවත පැමිණෙන foreachවිට, අරාව පිළිබඳ සඳහනක් සමඟ යම් ආකාරයක අනුකාරකයක් නිර්මාණය කරන බව ඔබට පහසුවෙන් සිතාගත හැකිය . මෙම සඳහන හරියටම $bමගේ උදාහරණයේ විචල්‍යය මෙන් ක්‍රියා කරයි . කෙසේ වෙතත්, පුනරාවර්තනය සහ යොමු කිරීම සජීවීව ලූපය තුළ පමණක් වන අතර පසුව ඒවා දෙකම ඉවතලනු ලැබේ. දැන් ඔබට දැක ගත හැකිය, සෑම අවස්ථාවකම 3 ක් වුවද, අරාව ලූපය තුළ වෙනස් කර ඇති අතර මෙම අතිරේක යොමුව සජීවීව පවතී. මෙය ක්ලෝනයක් අවුලුවන අතර, මෙහි සිදුවන්නේ කුමක්ද යන්න පැහැදිලි කරයි!

මෙම පිටපත් ලිවීමේ හැසිරීමේ තවත් අතුරු ආබාධයක් සඳහා විශිෂ්ට ලිපියක් මෙන්න: PHP තෘතීය ක්‍රියාකරු: වේගවත්ද නැද්ද?


ඔබේ අයිතිය ලෙස පෙනේ, මම එය උදාහරණ කිහිපයක් ඉදිරිපත් කළෙමි: codepad.org/OCjtvu8r ඔබේ උදාහරණයෙන් එක් වෙනසක් - ඔබ අගය වෙනස් කළහොත් එය පිටපත් නොවේ, යතුරු වෙනස් කළහොත් පමණි.
zb '

ඉහත දැක්වෙන සියලුම හැසිරීම් මෙය සැබවින්ම පැහැදිලි each()කරන අතර, පළමු පරීක්ෂණ නඩුවේ අවසානයේ ඇමතීමෙන් එය මනාව නිදර්ශනය කළ හැකිය , එහිදී අරාව වෙනස් කරන ලද බැවින් මුල් අරාවෙහි අරාව දර්ශකය දෙවන මූලද්‍රව්‍යයට යොමු වන බව අපට පෙනේ . පළමු පුනරාවර්තනය. foreachමා බලාපොරොත්තු නොවූ ලූපයේ කේත වාරණය ක්‍රියාත්මක කිරීමට පෙර අරාව දර්ශකය ඉදිරියට ගෙන යන බව මෙයින් පෙන්නුම් කරන බව පෙනේ - එය අවසානයේ මෙය කරනු ඇතැයි මම සිතුවෙමි. බොහෝ ස්තූතියි, මෙය මට මනාව පැහැදිලි කරයි.
ඩේව් රැන්ඩම්

50

සමඟ වැඩ කිරීමේදී සැලකිල්ලට ගත යුතු කරුණු කිහිපයක් foreach():

a) මුල් අරාවෙහි අපේක්ෂිත පිටපතforeach මත ක්‍රියා කරයි . එහි අර්ථය වනුයේ foreach සටහන් / පරිශීලක අදහස් නිර්මාණය නොවන තෙක් හෝ නැතිනම් SHARED දත්ත ගබඩා කිරීමයි.foreach()prospected copy

ආ) අපේක්ෂිත පිටපතක් අවුලුවන්නේ කුමක් ද ? ප්‍රතිපත්තියක් මත පදනම්ව අපේක්ෂිත පිටපතක් සාදනු copy-on-writeලැබේ, එනම්, අරාව foreach()වෙනස් කළ විට, මුල් අරාවෙහි ක්ලෝනයක් නිර්මාණය වේ.

ඇ) මුල් අරාව සහ foreach()අනුකාරකය සතුව ඇත DISTINCT SENTINEL VARIABLES, එනම්, මුල් අරාව සඳහා එකක් සහ අනෙක සඳහා foreach; පරීක්ෂණ කේතය පහත බලන්න. එස්පීඑල් , ඉටරේටර්ස් සහ අරා ඉටරේටර් .

පිටාර ගැලීමේ ප්‍රශ්නය PHP හි 'foreach' පුඩුවක් තුළ අගය නැවත සකසා ඇති බවට සහතික කර ගන්නේ කෙසේද? ඔබගේ ප්‍රශ්නයේ (3,4,5) නඩු ආමන්ත්‍රණය කරයි.

පහත උදාහරණයෙන් දැක්වෙන්නේ එක් එක් () සහ යළි පිහිටුවීම () අනුකාරකයේ SENTINELවිචල්‍යයන්ට බලපාන්නේ (for example, the current index variable)නැති බවයි foreach().

$array = array(1, 2, 3, 4, 5);

list($key2, $val2) = each($array);
echo "each() Original (outside): $key2 => $val2<br/>";

foreach($array as $key => $val){
    echo "foreach: $key => $val<br/>";

    list($key2,$val2) = each($array);
    echo "each() Original(inside): $key2 => $val2<br/>";

    echo "--------Iteration--------<br/>";
    if ($key == 3){
        echo "Resetting original array pointer<br/>";
        reset($array);
    }
}

list($key2, $val2) = each($array);
echo "each() Original (outside): $key2 => $val2<br/>";

ප්‍රතිදානය:

each() Original (outside): 0 => 1
foreach: 0 => 1
each() Original(inside): 1 => 2
--------Iteration--------
foreach: 1 => 2
each() Original(inside): 2 => 3
--------Iteration--------
foreach: 2 => 3
each() Original(inside): 3 => 4
--------Iteration--------
foreach: 3 => 4
each() Original(inside): 4 => 5
--------Iteration--------
Resetting original array pointer
foreach: 4 => 5
each() Original(inside): 0=>1
--------Iteration--------
each() Original (outside): 1 => 2

2
ඔබේ පිළිතුර තරමක් නිවැරදි නැත. foreachඅරාවෙහි විභව පිටපතක් මත ක්‍රියාත්මක වන නමුත් එය අවශ්‍ය නම් මිස එය සත්‍ය පිටපතක් නොකරයි.
linepogl

කේතය හරහා එම විභව පිටපත නිර්මාණය කරන්නේ කෙසේද සහ කවදාද යන්න නිරූපණය කිරීමට ඔබ කැමතිද? මගේ කේතය පෙන්නුම් කරන්නේ foreachඑය අරාව 100% ක් පිටපත් කරන බවයි. මම දැන ගැනීමට ආශාවෙන් සිටිමි. ඔබගේ අදහස් දැක්වීමට ස්තූතියි
sakhunzai

අරාව පිටපත් කිරීම සඳහා විශාල පිරිවැයක් දැරීමට සිදුවේ. එය භාවිතා කර කොටස් 100000 සමඟ රැසක් වඩාත් කැපීපෙනේ කිරීමට ගතවන කාලය ගණන් උත්සාහ forහෝ foreach. සත්‍ය පිටපතක් සිදු නොවන නිසා ඔවුන් දෙදෙනා අතර සැලකිය යුතු වෙනසක් ඔබට නොපෙනේ.
linepogl

එවිට මම උපකල්පනය කරන්නේ SHARED data storageතෙක් හෝ නැතිව වෙන් කර ඇති බවය copy-on-write, නමුත් (මගේ කේත ස්නිපටයෙන්) සෑම විටම දෙකට SENTINEL variablesඑකක් original arrayසහ අනෙකක් සඳහා දෙවරක් කට්ටලයක් ඇති බව පැහැදිලිය foreach. ස්තූතියි තේරුමක් ඇති
sakhunzai

1
ඔව් එය “අපේක්ෂිත” පිටපත එනම් “විභව” පිටපතයි. ඔබ යෝජනා කළ පරිදි එය ආරක්‍ෂා නොවේ
සකුන්සායි

35

PHP 7 සඳහා සටහන

මෙම පිළිතුර යම් ජනප්‍රියත්වයක් ලබා ඇති බැවින් එය යාවත්කාලීන කිරීම සඳහා: මෙම පිළිතුර PHP 7 වන විට තවදුරටත් අදාළ නොවේ. “ පසුගාමී නොගැලපෙන වෙනස්කම් ” හි පැහැදිලි කර ඇති පරිදි , PHP 7 හි පුරෝකථනය අරාවෙහි පිටපත මත ක්‍රියා කරයි, එබැවින් අරාවෙහි ඕනෑම වෙනසක් සිදු වේ foreach loop හි පිළිබිඹු නොවේ. වැඩි විස්තර සබැඳියෙන්.

පැහැදිලි කිරීම ( php.net වෙතින් උපුටා ගැනීම ):

පළමු පෝරමය array_expression විසින් ලබා දී ඇති අරාව හරහා ලූප වේ. එක් එක් පුනරාවර්තනයේදී, වත්මන් මූලද්‍රව්‍යයේ අගය $ අගයට පවරා ඇති අතර අභ්‍යන්තර අරාව දර්ශකය එකකින් ඉදිරියට ගෙන යනු ලැබේ (එබැවින් ඊළඟ පුනරාවර්තනයේදී ඔබ ඊළඟ මූලද්‍රව්‍යය දෙස බලනු ඇත).

එබැවින්, ඔබේ පළමු උදාහරණයේ ඔබට ඇත්තේ අරාවෙහි එක් මූලද්‍රව්‍යයක් පමණක් වන අතර, දර්ශකය ගෙන යන විට ඊළඟ මූලද්‍රව්‍යය නොපවතී, එබැවින් ඔබ නව මූලද්‍රව්‍යයක් එකතු කිරීමෙන් පසු එය අවසන් අංගය ලෙස දැනටමත් "තීරණය" කර ඇති නිසා එය අවසන් වේ.

ඔබගේ දෙවන උදාහරණයේ දී, ඔබ මූලද්‍රව්‍ය දෙකකින් ආරම්භ කරන අතර, foreach loop අන්තිම මූලද්‍රව්‍යයේ නොපවතින බැවින් එය ඊළඟ පුනරාවර්තනයේ අරාව තක්සේරු කරන අතර අරාවෙහි නව මූලද්‍රව්‍යයක් ඇති බව වටහා ගනී.

ප්‍රලේඛනයේ පැහැදිලි කිරීමේ එක් එක් පුනරාවර්තන කොටසෙහි මේ සියල්ලෙහි ප්‍රති ence ලයක් බව මම විශ්වාස කරමි , එයින් බොහෝ විට එයින් අදහස් foreachවන්නේ එය කේතය ඇමතීමට පෙර සියලු තර්කනයන් සිදු කරන {}බවයි.

පරීක්ෂණ නඩුව

ඔබ මෙය ක්‍රියාත්මක කරන්නේ නම්:

<?
    $array = Array(
        'foo' => 1,
        'bar' => 2
    );
    foreach($array as $k=>&$v) {
        $array['baz']=3;
        echo $v." ";
    }
    print_r($array);
?>

ඔබට මෙම ප්‍රතිදානය ලැබෙනු ඇත:

1 2 3 Array
(
    [foo] => 1
    [bar] => 2
    [baz] => 3
)

එයින් අදහස් කරන්නේ එය වෙනස් කිරීම පිළිගෙන එය “කාලයාගේ ඇවෑමෙන්” වෙනස් කළ නිසා එය හරහා ගිය බවයි. නමුත් ඔබ මෙය කරන්නේ නම්:

<?
    $array = Array(
        'foo' => 1,
        'bar' => 2
    );
    foreach($array as $k=>&$v) {
        if ($k=='bar') {
            $array['baz']=3;
        }
        echo $v." ";
    }
    print_r($array);
?>

ඔබට ලැබෙනු ඇත:

1 2 Array
(
    [foo] => 1
    [bar] => 2
    [baz] => 3
)

එහි අර්ථය වන්නේ අරාව වෙනස් කරන ලදි, නමුත් අපි foreachදැනටමත් අරාවෙහි අවසාන අංගයේ සිටියදී එය වෙනස් කළ බැවින් , එය තවදුරටත් ලූප නොකිරීමට "තීරණය" කළ අතර, අපි නව අංගයක් එකතු කළද, අපි එය "ප්‍රමාද වැඩිය" එකතු කළෙමු හරහා ලූපයක් නොතිබුණි.

විස්තරාත්මක පැහැදිලි කිරීමක් දී කියවිය හැකි , PHP 'foreach' ඇත්තටම වැඩ කරන්නේ කෙසේද? මෙම හැසිරීම පිටුපස ඇති අභ්‍යන්තරය පැහැදිලි කරයි.


7
හොඳයි ඔබ ඉතිරි පිළිතුර කියෙව්වාද? එය එහි කේතය ක්‍රියාත්මක කිරීමට පෙර තවත් වේලාවක් ලූප් කරන්නේද යන්න foreach තීරණය කරන බව එය මනාව අර්ථවත් කරයි .
dkasipovic

2
නැත, අරාව වෙනස් කර ඇත, නමුත් "ප්‍රමාද වැඩියි" බැවින් පුරෝකථනය දැනටමත් "සිතන්නේ" එය අවසාන මූලද්‍රව්‍යය (එය පුනරාවර්තනයේ ආරම්භයේදීම) වන අතර එය තවදුරටත් ලූප නොවනු ඇත. දෙවන උදාහරණයේ දී, එය පුනරාවර්තනයේ ආරම්භයේ ඇති අවසාන මූලද්‍රව්‍යය නොවන අතර ඊළඟ පුනරාවර්තනයේ ආරම්භයේ දී නැවත ඇගයීමට ලක් කරයි. මම පරීක්ෂණ නඩුවක් සූදානම් කිරීමට උත්සාහ කරමි.
dkasipovic

1
දී @AlmaDo බලන්න lxr.php.net/xref/PHP_TRUNK/Zend/zend_vm_def.h#4509 එය සෑම විටම එය දයානන්ද් විට ඊළඟ පහිටුම් දක්වනය සිටුවම් වෙනවා. එබැවින්, එය අවසාන පුනරාවර්තනය කරා ළඟා වූ විට, එය නිමවූ ලෙස සලකුණු කරනු ලැබේ (NULL දර්ශකය හරහා). ඔබ අවසාන පුනරාවර්තනයේ යතුරක් එක් කළ විට, foreach එය නොදකිනු ඇත.
bwoebi

1
@ ඩී කාසිපොවික් අංක. එහි සම්පූර්ණ හා පැහැදිලි පැහැදිලි කිරීමක් නොමැත (අවම වශයෙන් දැනට - මම වැරදියි)
අල්මා ඩෝ

4
ඇල්මාඩෝට ඔහුගේ තර්කනය තේරුම් ගැනීමේ අඩුපාඩුවක් ඇති බව පෙනේ… ඔබේ පිළිතුර හොඳයි.
bwoebi

15

PHP අත්පොත මගින් සපයන ලද ලියකියවිලි වලට අනුව.

එක් එක් පුනරාවර්තනයේදී, වත්මන් මූලද්‍රව්‍යයේ අගය $ v ට පවරා ඇති අතර අභ්‍යන්තර
අරාව දර්ශකය එකකින් ඉදිරියට ගෙන යනු ලැබේ (එබැවින් ඊළඟ පුනරාවර්තනයේදී ඔබ ඊළඟ මූලද්‍රව්‍යය දෙස බලනු ඇත).

එබැවින් ඔබේ පළමු උදාහරණයට අනුව:

$array = ['foo'=>1];
foreach($array as $k=>&$v)
{
   $array['bar']=2;
   echo($v);
}

$arrayඑක් මූලද්‍රව්‍යයක් පමණක් ඇති බැවින් පුරෝකථනය ක්‍රියාත්මක කිරීම අනුව 1 ට අනුයුක්ත කර ඇති $vඅතර එයට දර්ශකය ගෙනයාමට වෙනත් මූලද්‍රව්‍යයක් නොමැත

නමුත් ඔබේ දෙවන උදාහරණයේ:

$array = ['foo'=>1, 'bar'=>2];
foreach($array as $k=>&$v)
{
   $array['baz']=3;
   echo($v);
}

$arrayමූලද්‍රව්‍ය දෙකක් ඇත, එබැවින් දැන් $ අරාව ශුන්‍ය දර්ශක තක්සේරු කර දර්ශකය එකකින් ගෙනයන්න. ලූපයේ පළමු පුනරාවර්තනය සඳහා, $array['baz']=3;යොමු අනුව පාස් ලෙස එකතු කරනු ලැබේ.


13

විශාල ප්‍රශ්නයක් නම්, බොහෝ සංවර්ධකයින්, පළපුරුදු අය පවා, PHP විසින් foreach loops වල අරා හසුරුවන ආකාරය නිසා ව්‍යාකූල වී ඇති බැවිනි. සම්මත foreach loop හි, PHP මඟින් ලූපයේ භාවිතා වන අරාවේ පිටපතක් සාදයි. ලූපය අවසන් වූ වහාම පිටපත ඉවතලනු ලැබේ. සරල foreach loop එකක ක්‍රියාකාරිත්වය තුළ මෙය විනිවිද පෙනෙන ය. උදාහරණයක් වශයෙන්:

$set = array("apple", "banana", "coconut");
foreach ( $set AS $item ) {
    echo "{$item}\n";
}

මෙම ප්‍රතිදානයන්:

apple
banana
coconut

එබැවින් පිටපත නිර්මාණය කර ඇති නමුත් සංවර්ධකයා නොදැනේ, මන්ද මුල් අරාව ලූපය තුළ හෝ ලූපය අවසන් වූ පසු සඳහන් නොවේ. කෙසේ වෙතත්, ඔබ ලූපයක ඇති අයිතම වෙනස් කිරීමට උත්සාහ කරන විට, ඔබ අවසන් කළ විට ඒවා නවීකරණය කර නොමැති බව ඔබට පෙනී යයි:

$set = array("apple", "banana", "coconut");
foreach ( $set AS $item ) {
    $item = strrev ($item);
}

print_r($set);

මෙම ප්‍රතිදානයන්:

Array
(
    [0] => apple
    [1] => banana
    [2] => coconut
)

$ අයිතමයට ඔබ පැහැදිලිවම වටිනාකමක් ලබා දුන්නද, මුල් පිටපතෙහි කිසියම් වෙනස්කමක් දැනුම් දීම් විය නොහැක, ඇත්ත වශයෙන්ම මුල් පිටපතෙහි කිසිදු වෙනසක් නොමැත. මෙයට හේතුව ඔබ වැඩ කරමින් සිටින $ කට්ටලයේ පිටපතෙහි පෙනෙන පරිදි $ අයිතමය මත ක්‍රියාත්මක වීමයි. Reference අයිතමය යොමු කිරීමෙන් උදුරා ගැනීමෙන් ඔබට මෙය අභිබවා යා හැකිය:

$set = array("apple", "banana", "coconut");
foreach ( $set AS &$item ) {
    $item = strrev($item);
}
print_r($set);

මෙම ප්‍රතිදානයන්:

Array
(
    [0] => elppa
    [1] => ananab
    [2] => tunococ
)

එබැවින් එය පැහැදිලිව හා නිරීක්ෂණය කළ හැකිය, $ අයිතමය අතුරු විමර්ශනය මත ක්‍රියාත්මක වන විට, $ අයිතමයට කරන ලද වෙනස්කම් මුල් $ කට්ටලයේ සාමාජිකයින්ට කරනු ලැබේ. $ අයිතමය යොමු කිරීම මඟින් PHP අරාව පිටපත සෑදීම වළක්වයි. මෙය පරීක්ෂා කිරීම සඳහා, පළමුව අපි පිටපත නිරූපණය කරන ඉක්මන් පිටපතක් පෙන්වමු:

$set = array("apple", "banana", "coconut");
foreach ( $set AS $item ) {
    $set[] = ucfirst($item);
}
print_r($set);

මෙම ප්‍රතිදානයන්:

Array
(
    [0] => apple
    [1] => banana
    [2] => coconut
    [3] => Apple
    [4] => Banana
    [5] => Coconut
)

එය උදාහරණයේ පෙන්වා ඇති පරිදි, PHP $ කට්ටලය පිටපත් කර එය ලූප් කිරීමට භාවිතා කළේය, නමුත් $ set ලූපය තුළ භාවිතා කළ විට, PHP විසින් විචල්‍යයන් මුල් අරාවට එකතු කරන ලදි, නමුත් පිටපත් කරන ලද අරාව නොවේ. මූලික වශයෙන්, PHP භාවිතා කරන්නේ ලූපය ක්‍රියාත්මක කිරීම සහ $ අයිතමය පැවරීම සඳහා පිටපත් කළ අරාව පමණි. මේ හේතුව නිසා, ඉහත ලූපය ක්‍රියාත්මක වන්නේ 3 වතාවක් පමණක් වන අතර, සෑම අවස්ථාවකම එය මුල් $ කට්ටලයේ අවසානයට තවත් අගයක් එකතු කරයි, මුල් $ කට්ටලය මූලද්‍රව්‍ය 6 ක් සමඟ පිටව යයි, නමුත් කිසි විටෙකත් අනන්ත පුඩුවක් තුළට ඇතුළු නොවේ.

කෙසේ වෙතත්, මා කලින් සඳහන් කළ පරිදි, අපි $ අයිතමය යොමු කර භාවිතා කර ඇත්නම් කුමක් කළ යුතුද? ඉහත පරීක්ෂණයට එක් අක්ෂරයක් එකතු කරන ලදි:

$set = array("apple", "banana", "coconut");
foreach ( $set AS &$item ) {
    $set[] = ucfirst($item);
}
print_r($set);

ප්‍රති Results ල අසීමිත පුඩුවක් තුළ. මෙය සැබවින්ම අසීමිත පුඩුවක් බව සලකන්න, ඔබට ස්ක්‍රිප්ට් එක ඔබම මරා දැමීමට හෝ ඔබේ මෙහෙයුම් පද්ධතිය මතකය නැති වන තෙක් බලා සිටීමට සිදුවේ. මම පහත දැක්වෙන පේළිය මගේ ස්ක්‍රිප්ටයට එක් කළෙමි, එවිට PHP ඉතා ඉක්මණින් මතකය නැති වී යනු ඇත, ඔබ මෙම අසීමිත ලූප් පරීක්ෂණ ක්‍රියාත්මක කිරීමට යන්නේ නම් එයම කරන්නැයි මම යෝජනා කරමි:

ini_set("memory_limit","1M");

ඉතින් මෙම පෙර උදාහරණයේ දී අසීමිත ලූපය සමඟ, PHP ලිවීමට හේතුව අරාවෙහි පිටපතක් නිර්මාණය කිරීම සඳහා ලිවීමට හේතුව අපට පෙනේ. පිටපතක් සාදනු ලැබූ විට සහ ලූපයේ ව්‍යුහය මගින් පමණක් භාවිතා කරන විට, අරාව ලූපය ක්‍රියාත්මක කිරීමේදී ස්ථිතිකව පවතිනු ඇත, එබැවින් ඔබ කිසි විටෙකත් ගැටළු වලට මුහුණ නොදේ.


7

PHP foreach loop සමඟ භාවිතා කළ හැකිය Indexed arrays, Associative arraysසහ Object public variables.

Foreach loop හි, php කරන පළමු දෙය නම්, එය නැවත නැවත යෙදිය යුතු අරාවෙහි පිටපතක් නිර්මාණය කිරීමයි. PHP පසුව මෙම නව copyඅරාව මුල් පිටපතට වඩා පුනරාවර්තනය කරයි. මෙය පහත උදාහරණයෙන් දැක්වේ:

<?php
$numbers = [1,2,3,4,5,6,7,8,9]; # initial values for our array
echo '<pre>', print_r($numbers, true), '</pre>', '<hr />';
foreach($numbers as $index => $number){
    $numbers[$index] = $number + 1; # this is making changes to the origial array
    echo 'Inside of the array = ', $index, ': ', $number, '<br />'; # showing data from the copied array
}
echo '<hr />', '<pre>', print_r($numbers, true), '</pre>'; # shows the original values (also includes the newly added values).

මේ හැරුණු විට, php ද භාවිතා කිරීමට ඉඩ දෙයි iterated values as a reference to the original array value. මෙය පහත දැක්වේ:

<?php
$numbers = [1,2,3,4,5,6,7,8,9];
echo '<pre>', print_r($numbers, true), '</pre>';
foreach($numbers as $index => &$number){
    ++$number; # we are incrementing the original value
    echo 'Inside of the array = ', $index, ': ', $number, '<br />'; # this is showing the original value
}
echo '<hr />';
echo '<pre>', print_r($numbers, true), '</pre>'; # we are again showing the original value

සටහන: එය original array indexesභාවිතා කිරීමට ඉඩ නොදේ references.

මුලාශ්‍රය: http://dwellupper.io/post/47/understanding-php-foreach-loop-with-examples


1
Object public variablesවැරදියි හෝ නොමඟ යවන සුළුය. නිවැරදි අතුරුමුහුණතක් නොමැතිව ඔබට උදාසීන වස්තුවක් භාවිතා කළ නොහැක (උදා: ගමන් කළ හැකි) ඔබ එසේ කරන විට foreach((array)$obj ...ඇත්ත වශයෙන්ම ඔබ වැඩ කරන්නේ සරල අරාව සමඟ මිස වස්තුවක් නොවේ.
ක්‍රිස්තියානි
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.