Paano gumagana ang foreach loop. Gawin ang while at foreach loops. Loop ng Key-Value

Ang foreach construct ay isang variation ng para na kasama sa wika upang gawing mas madali ang pag-ulit sa mga elemento ng isang array. Mayroong dalawang bersyon ng foreach command, na idinisenyo para sa iba't ibang uri ng array:

foreach (array bilang $element) (

foreach (array bilang $key => $element) (

Halimbawa, kapag isinasagawa ang sumusunod na snippet:

$menu = аrrау("pasta", "steak", "patatas", "isda", "fries");

foreach ($menu bilang $item) (

i-print ang "$item
";

ang sumusunod na resulta ay magiging output:

Mayroong dalawang bagay na dapat tandaan sa halimbawang ito. Una, ang foreach construct ay awtomatikong bumabalik sa simula ng array (hindi ito nangyayari sa iba pang mga looping construct). Pangalawa, hindi na kailangang tahasang dagdagan ang counter o kung hindi man ay lumipat sa susunod na elemento ng array - awtomatiko itong nangyayari sa bawat pag-ulit ng foreach.

Ang pangalawang opsyon ay ginagamit kapag nagtatrabaho sa mga associative array:

$wine_inventory = array (

"merlot" => 15,

"zinfandel" => 17,

"sauvignon" => 32

foreach ($wine_inventory bilang $i => $item_count) (

print "$item_count bote ng $i na natitira
";

Sa kasong ito, ang resulta ay ganito:

15 bote ng merlot ang natitira

17 bote ng zinfandel ang natitira

32 bote ng sauvignon ang natitira

Tulad ng makikita mo mula sa mga halimbawa sa itaas, ang foreach construct ay makabuluhang pinapasimple ang pagtatrabaho sa mga array.

Ang prinsipyo ng pagpapatakbo ng switch construct ay medyo nakapagpapaalaala ng kung - ang resulta na nakuha mula sa pagsusuri ng expression ay nasuri laban sa isang listahan ng mga potensyal na tugma.

Ito ay lalong kapaki-pakinabang kapag sinusuri ang maraming mga halaga, dahil ang paggamit ng switch ay ginagawang mas visual at compact ang program. Ang pangkalahatang format ng switch command ay:

switch (expression) (

kaso (kondisyon):

kaso (kondisyon):

Ang kundisyong sinusuri ay ipinahiwatig sa mga panaklong pagkatapos ng switch na keyword. Ang resulta ng pagkalkula nito ay sunud-sunod na inihambing sa mga kondisyon sa mga seksyon ng kaso. Kung may nakitang tugma, ang block ng kaukulang seksyon ay isasagawa. Kung walang nakitang tugma, ang opsyonal na default na bloke ng seksyon ay isasagawa.

Tulad ng makikita mo sa mga susunod na kabanata, ang isa sa pinakamalakas na lakas ng PHP ay ang paghawak nito sa input ng user. Sabihin nating ang isang programa ay nagpapakita ng isang drop-down na listahan na may ilang mga opsyon, at ang bawat linya sa listahan ay tumutugma sa isang command na isinasagawa sa isang hiwalay na case construct. Ito ay napaka-maginhawa upang bumuo ng pagpapatupad gamit ang switch command:

$user_input = "mga recipe"; // Utos na pinili ng user

switch ($user_input):

case("paghahanap") :

i-print ang "Magsagawa tayo ng paghahanap!";

case("diksyonaryo") :

print "Anong salita ang gusto mong hanapin?";

case("mga recipe") :

print "Narito ang isang listahan ng mga recipe...";

print "Narito ang menu...";

Tulad ng nakikita mo mula sa fragment sa itaas, ang switch command ay nagbibigay ng malinaw at visual na organisasyon ng code. Ang variable na tinukoy sa kundisyon ng switch (sa halimbawang ito, $user_input) ay inihambing sa mga kundisyon ng lahat ng kasunod na seksyon ng kaso. Kung ang halaga na tinukoy sa seksyon ng kaso ay tumutugma sa halaga ng variable na inihahambing, ang bloke ng seksyong ito ay isasagawa. Pinipigilan ng break na command ang karagdagang mga seksyon ng case na masuri at tinatapos ang pagpapatupad ng switch construct. Kung wala sa mga naka-check na kundisyon ang natutugunan, ang opsyonal na default na seksyon ay isaaktibo. Kung walang default na seksyon at wala sa mga kundisyon ay totoo, ang switch command ay magtatapos lamang at ang pagpapatupad ng programa ay magpapatuloy sa susunod na command.

Dapat mong tandaan na kung walang break command sa case section (tingnan ang susunod na seksyon), magpapatuloy ang execution ng switch sa susunod na command hanggang sa makatagpo ng break command o maabot ang dulo ng switch statement. Ang sumusunod na halimbawa ay nagpapakita ng mga kahihinatnan ng nawawalang break command: $value = 0.4;

switch($value):

print "value ay 0.4
";

print "ang halaga ay 0.6
";

print "value ay 0.3
";

print "Hindi ka pumili ng isang halaga!";

Ang resulta ay ganito:

Ang kawalan ng break command ay nagresulta sa pagpapatupad ng hindi lamang print command sa seksyon kung saan natagpuan ang tugma, kundi pati na rin ang print command sa susunod na seksyon. Pagkatapos ay naantala ang pagpapatupad ng switch statement ng switch statement kasunod ng pangalawang print command.

Ang pagpili sa pagitan ng switch at kung ang mga utos ay halos walang epekto sa pagganap ng programa. Ang desisyon na gumamit ng isang disenyo o iba ay sa halip ay isang personal na bagay para sa programmer.

Agad na sinira ng break na command ang pagpapatupad ng while, for, o switch statement kung saan ito matatagpuan. Ang utos na ito ay nabanggit na sa nakaraang seksyon, ngunit ang pagkagambala sa kasalukuyang loop ay hindi nauubos ang mga kakayahan ng break command. Sa pangkalahatan, ganito ang hitsura ng break syntax:

Ang opsyonal na parameter n ay tumutukoy sa bilang ng mga antas ng control construct na tinapos ng break command. Halimbawa, kung ang isang break na command ay naka-nest sa loob ng dalawa habang ang mga command at ang break ay sinusundan ng numero 2, ang parehong mga loop ay lalabas kaagad. Ang default na halaga para sa n ay 1; ang paglabas sa isang antas ay maaaring ipahiwatig alinman sa pamamagitan ng tahasang pagtukoy ng 1 o sa pamamagitan ng pagtukoy ng break command na walang parameter. Tandaan na ang i f command ay hindi isa sa mga control construct na maaaring maputol ng break command.

Ang PHP foreach loop ay maaaring gamitin tulad nito:

foreach($array_name bilang $value)( //code na isasagawa)

foreach($array_name bilang $key =>$value)( // //code na dapat isagawa)

Halimbawa ng paggamit ng foreach loop na may numeric array

Sa halimbawang ito, gagawa kami ng hanay ng limang elemento na may mga numerong halaga. Ang PHP foreach loop ay gagamitin upang umulit sa array na ito. Sa loob ng foreach loop ginamit namin ang echo upang i-print ang mga halaga ng array:

Tingnan ang demo at code

Halimbawa na may mga array key at value

Ang halimbawang ito ay naglalarawan ng isa pang paraan upang gamitin ang PHP foreach loop. Upang gawin ito, lumikha kami ng isang magkakaugnay na hanay ng tatlong elemento. Kasama dito ang mga pangalan ng mga empleyado ( bilang mga susi) at ang halaga ng sahod ( bilang mga halaga):

Tingnan ang demo at code

Isang halimbawa ng pagbabago ng halaga ng isang elemento ng array sa isang foreach loop

Maaari mo ring gamitin ang PHP array foreach upang baguhin ang mga halaga ng mga elemento ng array. Ginagawa ito sa pamamagitan ng paggamit ng "&" bago ang "$" para sa value variable. Halimbawa:

&$value_of_element

Ang halaga ay mababago. Upang maging mas malinaw, isaalang-alang ang sumusunod na halimbawa.

Sa halimbawang ito, gumawa kami ng numeric array ng limang elemento. Pagkatapos nito, gumamit kami ng foreach loop upang ipakita ang mga halaga ng mga elemento.

Pagkatapos ay gumawa kami ng isa pang foreach loop, kung saan idinaragdag ang "& " bago ang $value_of_element. Sa loob ng mga kulot na braces ay nagtatalaga kami ng mga bagong halaga sa mga elemento ng array.

Upang makita ang pagkakaiba bago at pagkatapos magtalaga ng mga bagong halaga, ang array ay ipinapakita gamit ang print_r() function.

Tingnan ang demo at code

Para saan ang PHP foreach loop na ginagamit?

Ang PHP foreach loop ay ginagamit upang gumana sa isang array. Ito ay umuulit sa bawat isa sa mga elemento nito.

Maaari ka ring gumamit ng for loop upang gumana sa mga array. Halimbawa, gamit ang length property upang makuha ang haba ng isang array at pagkatapos ay ilapat ito bilang max operator. Ngunit ginagawang mas madali ang foreach dahil idinisenyo ito upang gumana sa mga array.

Kung nagtatrabaho ka sa MySQL, ang cycle na ito ay mas angkop para dito. Halimbawa, maaari kang pumili ng ilang row mula sa isang database table at ipasa ang mga ito sa isang array. Pagkatapos nito, gamit ang isang foreach loop, ulitin ang lahat ng mga elemento ng array at magsagawa ng ilang aksyon.

Tandaan na maaari kang gumamit ng foreach loop na may array o object lang.

Gamit ang foreach loop

Mayroong dalawang paraan upang gamitin ang PHP foreach loop sa PHP. Parehong inilarawan sa ibaba.

  • Ang syntax para sa unang paraan ay:

foreach($array_name bilang $value)( echo $value )

Sa kasong ito, kailangan mong tukuyin ang pangalan ng array, at pagkatapos ay ang $value variable.

Para sa bawat pag-ulit, ang halaga ng kasalukuyang elemento ay itinalaga sa $value variable. Matapos makumpleto ang pag-ulit, ang variable ay itinalaga ang halaga ng susunod na elemento. At iba pa hanggang sa ang lahat ng mga elemento ng array ay naulit.

  • Syntax ng pangalawang paraan ( PHP foreach bilang pangunahing halaga):

Ito ay angkop para sa mga nauugnay na array na gumagamit ng mga pares ng key/value.

Sa bawat pag-ulit, ang halaga ng kasalukuyang elemento ay itatalaga sa $value_of_element variable. Bilang karagdagan, ang element key ay itinalaga sa $key_of_element variable.

Kung nagtatrabaho ka sa mga numeric array, maaari mong gamitin ang unang paraan, na hindi nangangailangan ng mga key ng elemento.

Ang publikasyong ito ay pagsasalin ng artikulong “ PHP foreach loop 2 paraan para gamitin ito", na inihanda ng magiliw na pangkat ng proyekto

Sa isang kamakailang digest ng mga kagiliw-giliw na link tungkol sa PHP, nakakita ako ng isang link sa isang komento ni Nikita Popov sa StackOverflow, kung saan siya ay nagsasalita nang detalyado tungkol sa mekanismo "sa ilalim ng hood" ng foreach control construct.
Dahil minsan ay gumagana ang foreach sa higit sa isang maliit na kakaibang paraan, nakita kong kapaki-pakinabang na isalin ang sagot na ito.

Pansin: ipinapalagay ng tekstong ito ang isang pangunahing kaalaman sa functionality ng zvals sa PHP, lalo na dapat mong malaman kung ano ang refcount at is_ref.
gumagana ang foreach sa mga entity na may iba't ibang uri: na may mga array, na may mga simpleng object (kung saan nakalista ang mga available na property) at may Traversable object (o sa halip, mga object na may tinukoy na internal get_iterator handler). Madalas nating pinag-uusapan ang mga arrays dito, ngunit pag-uusapan ko ang iba pa sa pinakadulo.

Bago tayo magsimula, ang ilang mga salita tungkol sa mga array at ang kanilang traversal, mahalaga para sa pag-unawa sa konteksto.

Paano gumagana ang array traversal?

Ang mga array sa PHP ay inayos ng mga hash table (ang mga elemento ng hash ay pinagsama sa isang dobleng naka-link na listahan) at ang foreach ay binabagtas ang array kasunod ng tinukoy na pagkakasunud-sunod.

Kasama sa PHP ang dalawang paraan upang tumawid sa isang array:

  • Ang unang paraan ay isang panloob na array pointer. Ang pointer na ito ay bahagi ng istraktura ng HashTable at isa lang itong pointer sa kasalukuyang elemento ng hash table. Ang panloob na array pointer ay maaaring baguhin nang walang parusa, iyon ay, kung ang kasalukuyang elemento ay tinanggal, ang panloob na array pointer ay ililipat sa susunod.
  • Ang pangalawang mekanismo ng pag-ulit ay isang panlabas na array pointer na tinatawag na HashPosition. Ito ay mahalagang kapareho ng panloob na array pointer, ngunit hindi ito bahagi ng HashTable. Ang panlabas na paraan ng pag-ulit na ito ay hindi ligtas sa pagbabago. Kung aalisin mo ang elementong itinuro ng HashPosition, maiiwan kang may nakabitin na pointer, na magreresulta sa isang segmentation fault.

Kaya, ang mga panlabas na array pointer ay dapat lamang gamitin kapag ikaw ay ganap na sigurado na walang user code na isasagawa sa panahon ng traversal. At ang naturang code ay maaaring mapunta sa mga hindi inaasahang lugar, tulad ng isang tagapangasiwa ng error o isang destructor. Ito ang dahilan kung bakit sa karamihan ng mga kaso ang PHP ay kailangang gumamit ng isang panloob na pointer sa halip na isang panlabas. Kung hindi man, maaaring mag-crash ang PHP sa isang segmentation fault sa sandaling magsimulang gumawa ang user ng anumang bagay na hindi karaniwan.

Ang problema sa panloob na pointer ay bahagi ito ng HashTable. Kaya kapag binago mo ito, ang HashTable ay nagbabago kasama nito. At dahil ang mga array sa PHP ay naa-access ayon sa halaga (at hindi sa pamamagitan ng sanggunian), napipilitan kang kopyahin ang array upang mai-loop ang mga elemento nito.

Ang isang simpleng halimbawa na nagpapakita ng kahalagahan ng pagkopya (hindi gaanong karaniwan, sa pamamagitan ng paraan) ay nested iteration:

Foreach ($array bilang $a) ( foreach ($array bilang $b) ( // ... ) )

Dito nais mong ang parehong mga loop ay independyente, at hindi matalinong itinapon sa isang pointer.

Kaya dumating kami sa foreach.

Ang pagtawid sa isang array sa foreach

Ngayon alam mo na kung bakit kailangang gumawa ng kopya ng array si foreach bago ito lampasan. Ngunit malinaw na hindi ito ang buong kuwento. Kung gumawa ng kopya ang PHP o hindi ay depende sa ilang mga kadahilanan:

  • Kung ang iterable array ay isang reference, walang pagkopya na magaganap, sa halip ay ipapatupad ang addref:

    $ref =& $array; // $array has is_ref=1 now foreach ($array as $val) ( // ... )
    bakit naman Dahil ang anumang pagbabago sa array ay dapat na ipalaganap sa pamamagitan ng sanggunian, kasama ang panloob na pointer. Kung gumawa ng kopya si foreach sa kasong ito, masisira nito ang semantika ng link.

  • Kung ang array ay may refcount=1, ang pagkopya ay hindi na isasagawa muli. refcount=1 ay nangangahulugan na ang array ay hindi ginagamit sa ibang lugar at foreach ay maaaring gamitin ito nang direkta. Kung mas malaki sa isa ang refcount, ibinabahagi ang array sa iba pang mga variable at para maiwasan ang pagbabago, dapat itong kopyahin ng foreach (anuman ang reference case na inilarawan sa itaas).
  • Kung ang array ay reference-traversed (foreach ($array as &$ref)), kung gayon - anuman ang copy o non-copy function - ang array ay magiging reference.

Kaya ito ang unang bahagi ng misteryo: ang function ng kopya. Ang pangalawang bahagi ay kung paano isinasagawa ang kasalukuyang pag-ulit, at medyo kakaiba din ito. Ang "normal" na pattern ng pag-ulit na alam mo na (at kadalasang ginagamit sa PHP - hiwalay sa foreach) ay ganito ang hitsura (pseudocode):

I-reset(); habang (get_current_data(&data) == SUCCESS) ( code(); move_forward(); )
ang foreach na pag-ulit ay mukhang medyo naiiba:

I-reset(); habang (get_current_data(&data) == SUCCESS) ( move_forward(); code(); )

Ang pagkakaiba ay ang move_forward() ay isinasagawa sa simula sa halip na sa dulo ng loop. Kaya, kapag gumagamit ang user code ng elementong $i, ang panloob na array pointer ay tumuturo na sa elementong $i+1.

Ang mode na ito ng pagpapatakbo ng foreach ay din ang dahilan kung bakit ang panloob na array pointer ay lumilipat sa susunod na elemento kung ang kasalukuyang isa ay tinanggal, sa halip na sa nauna (tulad ng maaari mong asahan). Ang lahat ay idinisenyo upang gumana nang mahusay sa foreach (ngunit malinaw na hindi gagana nang maayos sa lahat ng iba pa, laktawan ang mga elemento).

Mga implikasyon ng code

Ang unang kinahinatnan ng pag-uugali sa itaas ay ang foreach ay kinokopya ang iterable array sa maraming mga kaso (mabagal). Ngunit huwag matakot: Sinubukan kong tanggalin ang kinakailangan sa pagkopya at wala akong makitang anumang speedup kahit saan maliban sa mga artipisyal na benchmark (na umulit nang dalawang beses nang mas mabilis). Parang hindi sapat ang pag-ulit ng mga tao.

Ang pangalawang kahihinatnan ay karaniwang walang ibang kahihinatnan. Ang pag-uugali ng foreach sa pangkalahatan ay lubos na nauunawaan ng gumagamit at gumagana lamang ayon sa nararapat. Hindi mo dapat pakialam kung paano nangyayari ang pagkopya (o kung nangyari man ito), o sa anong partikular na punto ng oras na inilipat ang pointer.

At ang pangatlong kahihinatnan - at dito tayo dumating sa iyong problema - kung minsan ay nakikita natin ang kakaibang pag-uugali na mahirap maunawaan. Ito ay partikular na nangyayari kapag sinubukan mong baguhin ang array mismo, na iyong tinatahak sa isang loop.

Ang isang malaking koleksyon ng pag-uugali ng edge case na nangyayari kapag binago mo ang isang array sa panahon ng pag-ulit ay makikita sa mga pagsubok sa PHP. Maaari kang magsimula sa pagsusulit na ito, pagkatapos ay baguhin ang 012 sa 013 sa address, at iba pa. Makikita mo kung paano magpapakita ang bawat pag-uugali sa iba't ibang sitwasyon (lahat ng uri ng kumbinasyon ng mga link, atbp.).

Ngayon bumalik tayo sa iyong mga halimbawa:

Foreach ($array bilang $item) ( echo "$item\n"; $array = $item; ) print_r($array); /* Output sa loop: 1 2 3 4 5 $array pagkatapos ng loop: 1 2 3 4 5 1 2 3 4 5 */

Narito ang $array ay mayroong refcount=1 bago ang loop upang hindi ito makopya ngunit makakakuha ng addref. Sa sandaling magtalaga ka ng halaga sa $array, mahahati ang zval, kaya ang array na dinadagdagan mo ng mga elemento at ang array na inuulit mo ay magiging dalawang magkaibang array.

Foreach ($array bilang $key => $item) ($array[$key + 1] = $item + 2; echo "$item\n"; ) print_r($array); /* Output sa loop: 1 2 3 4 5 $array pagkatapos ng loop: 1 3 4 5 6 7 */

Ang parehong sitwasyon tulad ng sa unang pagsubok.

// Shift the pointer by one to make sure na hindi ito makakaapekto sa foreach var_dump(each($array)); foreach ($array as $item) ( echo "$item\n"; ) var_dump(each($array)); /* Output array(4) ( => int(1) ["value"]=> int(1) => int(0) ["key"]=> int(0) ) 1 2 3 4 5 bool( mali) */

Same story ulit. Sa panahon ng foreach loop, mayroon kang refcount=1 at makakakuha ka lamang ng addref, mababago ang panloob na $array pointer. Sa dulo ng loop, ang pointer ay nagiging NULL (ito ay nangangahulugan na ang pag-ulit ay nakumpleto). bawat isa ay nagpapakita nito sa pamamagitan ng pagbabalik ng mali.

Foreach ($array bilang $key => $item) ( echo "$item\n"; each($array); ) /* Output: 1 2 3 4 5 */

Foreach ($array bilang $key => $item) ( echo "$item\n"; reset ($array); ) /* Output: 1 2 3 4 5 */

Ngunit ang mga halimbawang ito ay hindi sapat na nakakumbinsi. Nagsisimulang maging talagang hindi mahulaan ang pag-uugali kapag gumamit ka ng kasalukuyang sa isang loop:

Foreach ($array bilang $val) ( var_dump(current($array)); ) /* Output: 2 2 2 2 2 */

Dito dapat mong tandaan na ang kasalukuyang ay ina-access din sa pamamagitan ng sanggunian, sa kabila ng hindi pagbabago ng array. Ito ay kinakailangan upang gumana nang pare-pareho sa lahat ng iba pang mga function, tulad ng susunod, ang pag-access sa pamamagitan ng reference (kasalukuyan ay talagang isang mas kanais-nais na function ng ref; maaari itong makakuha ng isang halaga, ngunit gumagamit ng isang reference kung maaari). Ang isang sanggunian ay nangangahulugan na ang array ay dapat na ihiwalay, kaya ang $array at ang kopya ng $array na ginagamit ng bawat isa ay magiging independyente. Kung bakit ka nakakuha ng 2 at hindi 1 ay binanggit din sa itaas: foreach increments array pointer bago magsimula ang user code, hindi pagkatapos. Kaya kahit na gumagana pa rin ang code sa unang elemento, inilipat na ng foreach ang pointer sa pangalawa.

Ngayon subukan natin ang isang maliit na pagbabago:

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

Narito mayroon kaming is_ref=1, kaya ang array ay hindi kinopya (katulad ng nasa itaas). Ngunit ngayon na mayroong is_ref, ang array ay hindi na kailangang hatiin, na ipinapasa sa pamamagitan ng pagtukoy sa kasalukuyang. Ngayon gumagana ang kasalukuyan at foreach sa parehong array. Nakikita mo ang array na inilipat ng isa nang tumpak dahil sa paraan ng pagtrato ng foreach sa pointer.

Makikita mo ang parehong bagay kapag binagtas mo ang isang array sa pamamagitan ng sanggunian:

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

Ang mahalagang bagay dito ay ang foreach ay magtatalaga ng aming $array is_ref=1 kapag ito ay nag-loop sa ibabaw nito sa pamamagitan ng sanggunian, kaya ito ay magiging pareho sa itaas.

Isa pang maliit na variation, dito namin itatalaga ang aming array sa isa pang variable:

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

Dito ang refcount ng $array ay nakatakda sa 2 kapag nagsimula ang loop, kaya kailangang gumawa ng kopya bago magsimula. Kaya ang $array at ang array na ginamit ng foreach ay mag-iiba mula sa simula. Iyon ang dahilan kung bakit nakukuha mo ang posisyon ng panloob na array pointer na may kaugnayan bago magsimula ang loop (sa kasong ito ito ay nasa unang posisyon).

Pag-ulit ng mga bagay

Kapag inuulit ang mga bagay, makatuwirang isaalang-alang ang dalawang kaso:

Ang bagay ay hindi Traversable (o sa halip, ang panloob na get_iterator handler ay hindi tinukoy)

Sa kasong ito, ang pag-ulit ay nangyayari halos kapareho ng sa mga array. Ang parehong semantika ng pagkopya. Ang pagkakaiba lang ay tatakbo ang foreach ng ilang karagdagang code para laktawan ang mga property na hindi available sa kasalukuyang saklaw. Ang ilang mas kawili-wiling mga katotohanan:

  • Para sa mga ipinahayag na katangian, muling ino-optimize ng PHP ang talahanayan ng hash ng property. Kung inuulit mo ang bagay, dapat itong muling buuin ang hash table na iyon (na nagpapataas ng paggamit ng memorya). Hindi sa dapat kang mag-alala tungkol dito, maging aware ka lang.
  • Sa bawat pag-ulit, muling makukuha ang talahanayan ng hash ng property, ibig sabihin, tatawagan ng PHP ang get_properties nang paulit-ulit. Para sa mga "regular" na pag-aari na ito ay hindi napakahalaga, ngunit kung ang mga katangian ay dynamic na nilikha (ito ay madalas na ginagawa ng mga built-in na klase) pagkatapos ay ang talahanayan ng ari-arian ay muling kakalkulahin sa bawat oras.
Madadaanan na bagay

Sa kasong ito, ang lahat ng sinabi sa itaas ay hindi mailalapat sa anumang paraan. Gayundin, hindi kokopya ang PHP at hindi gagamit ng anumang mga trick tulad ng pagdaragdag ng pointer bago ang loop. Sa tingin ko, ang paraan ng pagdaan sa isang Traversable object ay mas predictable at hindi nangangailangan ng karagdagang paglalarawan.

Pagpapalit ng isang iterable sa panahon ng isang loop

Ang isa pang hindi pangkaraniwang kaso na hindi ko nabanggit ay ang PHP ay nagbibigay-daan sa kakayahang palitan ang isang iterable sa panahon ng isang loop. Maaari kang magsimula sa isang array at magpatuloy sa pamamagitan ng pagpapalit nito ng isa pa sa kalahati. O magsimula sa isang array, pagkatapos ay palitan ito ng isang bagay:

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

Gaya ng nakikita mo, nagsimula lang ang PHP sa pagtawid sa ibang entity sa sandaling naganap ang pagpapalit.

Pagbabago ng panloob na array pointer sa panahon ng pag-ulit

Isang huling detalye ng foreach na pag-uugali na hindi ko nabanggit (dahil maaari itong magamit upang makakuha ng kakaiba talaga ang ugali): ano ang maaaring mangyari kung susubukan mong baguhin ang panloob na array pointer sa panahon ng isang loop.

Dito maaaring hindi mo makuha ang iyong inaasahan: kung tumawag ka sa susunod o nauna sa katawan ng loop (sa kaso ng pagpasa sa pamamagitan ng sanggunian), makikita mo na ang panloob na pointer ay lumipat, ngunit ito ay walang epekto sa pag-uugali ng ang iterator. Ang dahilan ay ang foreach ay gumagawa ng backup ng kasalukuyang posisyon at hash ng kasalukuyang elemento sa HashPointer pagkatapos ng bawat pass ng loop. Sa susunod na pass, susuriin ng foreach kung nagbago ang posisyon ng internal pointer at subukang ibalik ito gamit ang hash na ito.

Tingnan natin kung ano ang ibig sabihin ng "susubukan". Ipinapakita ng unang halimbawa kung paano hindi binabago ng pagbabago ng panloob na pointer ang foreach mode:

$array = ; $ref =& $array; foreach ($array bilang $value) ( ​​​​var_dump($value); reset ($array); ) // output: 1, 2, 3, 4, 5

Ngayon subukan nating i-unset ang elemento na maa-access ng foreach sa unang pass (key 1):

$array = ; $ref =& $array; foreach ($array bilang $value) ( ​​​​var_dump($value); unset($array); reset($array); ) // output: 1, 1, 3, 4, 5

Dito makikita mo na ang counter ay na-reset dahil ang isang elemento na may katugmang hash ay hindi mahanap.

Tandaan, ang hash ay hash lang. Nangyayari ang mga banggaan. Subukan natin ito ngayon:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array bilang $value) ( ​​​​unset ($array["EzFY"]); $array["FYFZ"] = 4; reset ($array); var_dump($value); ) // output: 1 1 3 4

Gumagana tulad ng inaasahan namin. Inalis namin ang EzFY key (ang isa kung saan matatagpuan ang foreach), kaya ginawa ang isang pag-reset. Nagdagdag din kami ng dagdag na susi, kaya nakikita namin ang 4 sa dulo.

At narito ang hindi alam. Ano ang mangyayari kung papalitan mo ang FYFY key ng FYFZ? Subukan natin:

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

Ngayon ang loop ay direktang lumipat sa bagong elemento, nilaktawan ang lahat ng iba pa. Ito ay dahil ang FYFY key ay may banggaan sa EzFY (sa totoo lang, lahat ng mga key mula sa array na ito ay masyadong). Bukod dito, ang elemento ng FYFY ay matatagpuan sa parehong address ng memorya ng elementong EzFY na kakatanggal lang. Kaya para sa PHP ito ay magiging parehong posisyon na may parehong hash. Ang posisyon ay "naibalik" at ang paglipat sa dulo ng array ay nangyayari.

Kadalasan kailangan mong umulit sa lahat ng mga elemento ng isang PHP array at magsagawa ng ilang operasyon sa bawat elemento. Halimbawa, maaari mong i-output ang bawat value sa isang HTML table o bigyan ang bawat elemento ng bagong value.

Sa araling ito, titingnan natin ang foreach construct kapag nag-aayos ng loop sa mga naka-index at nauugnay na array.

I-loop ang mga halaga ng elemento

Ang pinakasimpleng kaso ng paggamit para sa foreach ay ang pag-loop sa mga halaga sa isang naka-index na array. Pangunahing syntax:

Foreach ($array bilang $value) ( ​​​​ // Gawin ang isang bagay na may $value ) // Dito ipapatupad ang code pagkatapos makumpleto ang loop

Halimbawa, ang sumusunod na script ay umuulit sa listahan ng mga direktor sa isang naka-index na hanay at nagpi-print ng pangalan ng bawat isa:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); foreach ($director bilang $director) ( echo $director . "
"; }

Ang code sa itaas ay maglalabas ng:

Alfred Hitchcock Stanley Kubrick Martin Scorsese Fritz Lang

Loop ng Key-Value

Paano ang mga nauugnay na array? Kapag gumagamit ng ganitong uri ng array, madalas kailangan mong magkaroon ng access sa susi ng bawat elemento pati na rin ang halaga nito. Ang foreach construct ay may paraan upang malutas ang problema:

Foreach ($array bilang $key => $value) ( ​​// Gawin ang isang bagay gamit ang $key at/o $value ) // Dito ipapatupad ang code pagkatapos makumpleto ang loop

Isang halimbawa ng pag-aayos ng loop sa pamamagitan ng nauugnay na array na may impormasyon tungkol sa mga pelikula, na nagpapakita ng susi ng bawat elemento at ang halaga nito sa HTML na listahan ng mga kahulugan:

$movie = array("title" => "Rear Window", "director" => "Alfred Hitchcock", "year" => 1954, "minutes" => 112); echo"

"; foreach ($pelikula bilang $key => $value) (echo "
$key:
"; echo"
$halaga
"; ) echo "
";

Kapag naisakatuparan, ang script na ito ay maglalabas ng:

Pamagat: Direktor sa Rear Window: Alfred Hitchcock taon: 1954 minuto: 112

Pagbabago ng halaga ng isang elemento

Paano ang tungkol sa pagbabago ng halaga ng isang elemento habang dumadaan ang loop? Maaari mong subukan ang code na ito:

Foreach ($myArray bilang $value) ($value = 123; )

Gayunpaman, kung patakbuhin mo ito, makikita mo na ang mga halaga sa array huwag kang magbago. Ang dahilan ay ang foreach ay gumagana sa isang kopya mga halaga ng array, hindi kasama ang orihinal. Sa ganitong paraan nananatiling buo ang orihinal na hanay.

Upang baguhin ang mga halaga ng array na kailangan mo link sa kahulugan. Para magawa ito, kailangan mong maglagay ng & sign sa harap ng value variable sa foreach construct:

Foreach ($myArray bilang &$value) ($ ​​value = 123; )

Halimbawa, ang sumusunod na script ay umiikot sa bawat elemento (pangalan ng direktor) sa $directors array, at ginagamit ang PHP explode() function at ang list construct upang palitan ang una at huling pangalan:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); // Baguhin ang format ng pangalan para sa bawat elemento foreach ($director bilang &$director) ( list($firstName, $lastName) = explode(" ", $director); $director = "$lastName, $firstName"; ) unset ($director); // I-print ang huling resulta foreach ($director bilang $director) ( echo $director . "
"; }

Ang script ay maglalabas ng:

Hitchcock, Alfred Kubrick, Stanley Scorsese, Martin Lang, Fritz

Tandaan na tinatawag ng script ang unset() function upang alisin ang $director variable pagkatapos makumpleto ang unang loop. Ito ay isang magandang kasanayan kung plano mong gamitin ang variable sa ibang pagkakataon sa script sa ibang konteksto.

Kung hindi mo aalisin ang reference, magkakaroon ka ng panganib ng karagdagang pagpapatupad ng code nang hindi sinasadyang sumangguni sa huling elemento sa array ("Lang, Fritz") kung patuloy mong gagamitin ang variable na $director, na hahantong sa mga hindi inaasahang kahihinatnan!

Ipagpatuloy

Sa tutorial na ito, tiningnan namin kung paano gamitin ang PHP foreach construct para i-loop ang mga elemento ng isang array. Ang mga sumusunod na isyu ay isinasaalang-alang:

  • Paano mag-loop sa mga elemento ng array
  • Paano i-access ang susi at halaga ng bawat elemento
  • Paano gumamit ng isang sanggunian upang baguhin ang mga halaga habang dumadaan ka sa isang loop

Isipin na mayroon kang isang associative array na gusto mong ulitin. Nagbibigay ang PHP ng madaling paraan upang magamit ang bawat elemento ng array gamit ang Foreach construct.

Sa simpleng wika ay ganito ang tunog:
"Para sa bawat elemento sa tinukoy na array, isagawa ang code na ito."

Bagama't magpapatuloy ito hangga't natutugunan ang ilang kundisyon, magpapatuloy ang foreach loop hanggang sa dumaan ito sa bawat elemento ng array.

PHP Foreach: Halimbawa

Mayroon kaming isang associative array na nag-iimbak ng mga pangalan ng mga tao sa aming kumpanya, pati na rin ang kanilang mga edad. Gusto naming malaman kung ilang taon na ang bawat empleyado, kaya gumagamit kami ng for-each loop para i-print ang pangalan at edad ng lahat.

$employeeAges; $employeeAges["Lisa"] = "28"; $employeeAges["Jack"] = "16"; $employeeAges["Ryan"] = "35"; $employeeAges["Rachel"] = "46"; $employeeAges["Grace"] = "34"; foreach($employeeAges bilang $key => $value)( echo "Pangalan: $key, Edad: $value
"; }

Nakukuha namin ang resulta:

Pangalan: Lisa, Edad: 28 Pangalan: Jack, Edad: 16 Pangalan: Ryan, Edad: 35 Pangalan: Rachel, Edad: 46 Pangalan: Grace, Edad: 34

Well, ang resulta ay mabuti at naiintindihan, ngunit ang syntax ng foreach construct ay hindi masyadong madali at naiintindihan. Tingnan natin ito nang maigi.

Para sa bawat syntax: $something as $key => $value

Ang lahat ng kabaliwan na ito ay halos isinasalin sa: “Para sa bawat elemento ng associative array na $employeeAges, gusto kong i-access ang $key at ang value sa loob nito, i.e. $value.

Ang operator na "=>" ay kumakatawan sa kaugnayan sa pagitan ng isang susi at isang halaga. Sa aming halimbawa, pinangalanan namin sila bilang key - $key at value - $value. Gayunpaman, mas madaling isipin ang mga ito bilang pangalan at edad. Sa ibaba sa aming halimbawa ay gagawin namin ito, at tandaan na ang resulta ay magiging pareho dahil binago lang namin ang mga pangalan ng mga variable na nauugnay sa mga susi at halaga.

$employeeAges; $employeeAges["Lisa"] = "28"; $employeeAges["Jack"] = "16"; $employeeAges["Ryan"] = "35"; $employeeAges["Rachel"] = "46"; $employeeAges["Grace"] = "34"; foreach($employeeAges as $name => $age)( echo "Pangalan: $name, Edad: $age
"; }

Well, ang resulta, inuulit namin, ay pareho.