Jinsi kitanzi cha foreach kinavyofanya kazi. Kufanya wakati na foreach loops. Kitanzi cha Thamani Muhimu

Muundo wa foreach ni tofauti ya ambayo imejumuishwa katika lugha ili kufanya kurudia juu ya vipengele vya safu rahisi. Kuna matoleo mawili ya amri ya mbele, iliyoundwa kwa aina tofauti za safu:

foreach (safu kama kipengele cha $) (

foreach (safu kama $key => $element) (

Kwa mfano, wakati wa kutekeleza snippet ifuatayo:

$ menu = аrrау("pasta", "steak", "viazi", "samaki", "vikaanga");

foreach (menu ya $ kama $item) (

chapisha "$item
";

matokeo yafuatayo yatakuwa pato:

Kuna mambo mawili ya kuzingatia katika mfano huu. Kwanza, ujenzi wa foreach unarudi kiatomati mwanzo wa safu (hii haifanyiki katika ujenzi mwingine wa kitanzi). Pili, hakuna haja ya kuongeza kihesabu kwa uwazi au vinginevyo kuhamia kipengele kinachofuata cha safu - hii hutokea moja kwa moja kwa kila marudio ya foreach.

Chaguo la pili hutumiwa wakati wa kufanya kazi na safu za ushirika:

$wine_inventory = safu (

"merlot" => 15,

"zinfandel" => 17,

"sauvignon" => 32

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

chapisha "$item_count chupa za $i zilizosalia
";

Katika kesi hii, matokeo yanaonekana kama hii:

Chupa 15 za merlot zilizobaki

Chupa 17 za zinfandel zilizosalia

Chupa 32 za sauvignon zilizobaki

Kama unaweza kuona kutoka kwa mifano hapo juu, muundo wa mbele hurahisisha sana kufanya kazi na safu.

Kanuni ya utendakazi wa muundo wa swichi kwa kiasi fulani inakumbusha ikiwa - matokeo yanayopatikana kutokana na kutathmini usemi yamekaguliwa dhidi ya orodha ya uwezekano wa kulinganisha.

Hii ni muhimu sana wakati wa kuangalia maadili mengi, kwani kutumia swichi hufanya programu kuwa ya kuona zaidi na ngumu. Muundo wa jumla wa amri ya kubadili ni:

kubadili (maneno) (

kesi (hali):

kesi (hali):

Hali inayojaribiwa imeonyeshwa kwenye mabano baada ya neno kuu la kubadili. Matokeo ya hesabu yake ni sequentially ikilinganishwa na masharti katika sehemu ya kesi. Ikiwa mechi inapatikana, kizuizi cha sehemu inayolingana inatekelezwa. Ikiwa hakuna ulinganifu unaopatikana, uzuiaji wa sehemu ya chaguo-msingi wa hiari hutekelezwa.

Kama utaona katika sura za baadaye, mojawapo ya nguvu kuu za PHP ni kushughulikia ingizo la mtumiaji. Wacha tuseme programu inaonyesha orodha ya kushuka na chaguzi kadhaa, na kila mstari kwenye orodha unalingana na amri ambayo inatekelezwa katika muundo tofauti wa kesi. Ni rahisi sana kujenga utekelezaji kwa kutumia amri ya kubadili:

$user_input = "mapishi"; // Amri iliyochaguliwa na mtumiaji

badilisha ($user_input) :

kesi("tafuta"):

chapisha "Hebu" tufanye utafutaji!";

kesi("kamusi"):

chapisha "Ni neno gani ungependa kutazama?";

kesi("mapishi"):

kuchapisha "Hapa kuna orodha ya mapishi ...";

chapisha "Hapa kuna menyu ...";

Kama unaweza kuona kutoka kwa kipande hapo juu, amri ya kubadili hutoa shirika wazi na la kuona la msimbo. Tofauti iliyobainishwa katika hali ya kubadili (katika mfano huu, $user_input) inalinganishwa na masharti ya sehemu zote za kesi zinazofuata. Ikiwa thamani iliyobainishwa katika sehemu ya kesi inalingana na thamani ya kigezo kinacholinganishwa, kizuizi cha sehemu hii kitatekelezwa. Amri ya mapumziko inazuia sehemu zaidi za kesi kukaguliwa na kumalizia utekelezaji wa muundo wa swichi. Ikiwa hakuna masharti yoyote yaliyowekwa alama yametimizwa, sehemu ya chaguo-msingi ya hiari inawashwa. Ikiwa hakuna sehemu ya chaguo-msingi na hakuna masharti yoyote ambayo ni kweli, amri ya kubadili inaisha tu na utekelezaji wa programu unaendelea na amri inayofuata.

Lazima ukumbuke kwamba ikiwa hakuna amri ya kuvunja katika sehemu ya kesi (tazama sehemu inayofuata), utekelezaji wa kubadili unaendelea na amri inayofuata mpaka amri ya kuvunja inakabiliwa au mwisho wa taarifa ya kubadili unapatikana. Mfano ufuatao unaonyesha matokeo ya kukosa amri ya mapumziko: $value = 0.4;

badilisha(thamani ya $):

chapa "thamani ni 0.4
";

chapa "thamani ni 0.6
";

chapa "thamani ni 0.3
";

chapisha "Hukuchagua thamani!";

Matokeo yake yanaonekana kama hii:

Kutokuwepo kwa amri ya kuvunja ilisababisha utekelezaji wa si tu amri ya uchapishaji katika sehemu ambapo mechi ilipatikana, lakini pia amri ya uchapishaji katika sehemu inayofuata. Kisha amri katika taarifa ya kubadili ziliingiliwa na amri ya kubadili kufuatia amri ya pili ya uchapishaji.

Chaguo kati ya swichi na ikiwa amri haina athari kwa utendakazi wa programu. Uamuzi wa kutumia muundo mmoja au mwingine ni suala la kibinafsi kwa mpangaji programu.

Amri ya kuvunja mara moja huvunja utekelezaji wa wakati, kwa, au kubadili taarifa ambayo inapatikana. Amri hii ilikuwa tayari imetajwa katika sehemu iliyopita, lakini kukatiza kitanzi cha sasa hakumalizi uwezo wa amri ya kuvunja. Kwa ujumla, syntax ya mapumziko inaonekana kama hii:

Kigezo cha hiari n kinabainisha idadi ya viwango vya udhibiti vilivyokomeshwa na amri ya kuvunja. Kwa mfano, ikiwa amri ya mapumziko imewekwa ndani ya amri mbili na mapumziko yanafuatwa na nambari ya 2, loops zote mbili hutoka mara moja. Thamani chaguo-msingi ya n ni 1; kutoka kwa ngazi moja inaweza kuonyeshwa ama kwa kutaja wazi 1 au kwa kutaja amri ya mapumziko bila parameter. Kumbuka kuwa amri ya i f sio moja wapo ya vidhibiti ambavyo vinaweza kuingiliwa na amri ya mapumziko.

Kitanzi cha mbele cha PHP kinaweza kutumika kama hii:

foreach($array_name as $value)(//code ya kutekelezwa)

foreach($array_name as $key =>$value)( // //code ambayo inapaswa kutekelezwa)

Mfano wa kutumia kitanzi cha foreach na safu ya nambari

Katika mfano huu, tutaunda safu ya vipengele vitano na maadili ya nambari. Kitanzi cha mbele cha PHP kitatumika kurudia kupitia safu hii. Ndani ya kitanzi cha mbele tulitumia echo kuchapisha maadili ya safu:

Tazama onyesho na msimbo

Mfano na funguo za safu na maadili

Mfano huu unaelezea njia nyingine ya kutumia kitanzi cha mbele cha PHP. Ili kufanya hivyo, tuliunda safu ya ushirika ya vipengele vitatu. Inajumuisha majina ya wafanyikazi ( kama funguo) na kiasi cha mshahara ( kama maadili):

Tazama onyesho na msimbo

Mfano wa kubadilisha thamani ya kipengele cha safu katika kitanzi cha foreach

Unaweza pia kutumia safu ya mbele ya PHP kubadilisha maadili ya vitu vya safu. Hii inafanywa kwa kutumia "&" kabla ya "$" kwa utofauti wa thamani. Kwa mfano:

&$value_of_element

Thamani itabadilishwa. Ili kuifanya iwe wazi zaidi, fikiria mfano ufuatao.

Katika mfano huu, tuliunda safu ya nambari ya vitu vitano. Baada ya hapo, tulitumia kitanzi cha foreach kuonyesha maadili ya vitu.

Kisha tukaunda kitanzi kingine cha mbele, ambapo "&" huongezwa kabla ya $value_of_element. Ndani ya braces curly tunapeana maadili mapya kwa vitu vya safu.

Ili kuona tofauti kabla na baada ya kugawa maadili mapya, safu huonyeshwa kwa kutumia print_r() kazi.

Tazama onyesho na msimbo

Je, kitanzi cha mbele cha PHP kinatumika kwa ajili gani?

Kitanzi cha mbele cha PHP kinatumika kufanya kazi na safu. Inarudia juu ya kila moja ya vipengele vyake.

Unaweza pia kutumia kitanzi kufanya kazi na safu. Kwa mfano, kutumia sifa ya urefu kupata urefu wa safu na kisha kuitumia kama opereta max. Lakini foreach hurahisisha kwani imeundwa kufanya kazi na safu.

Ikiwa unafanya kazi na MySQL, basi mzunguko huu unafaa zaidi kwa hili. Kwa mfano, unaweza kuchagua safu kadhaa kutoka kwa jedwali la hifadhidata na kuzipitisha kwenye safu. Baada ya hayo, kwa kutumia kitanzi cha mbele, rudia kupitia vipengele vyote vya safu na fanya kitendo fulani.

Kumbuka kuwa unaweza kutumia kitanzi cha mbele na safu au kitu tu.

Kutumia kitanzi cha mbele

Kuna njia mbili za kutumia kitanzi cha mbele cha PHP katika PHP. Zote mbili zimefafanuliwa hapa chini.

  • Syntax ya njia ya kwanza ni:

foreach($array_name as $value)( echo $value )

Katika kesi hii, unahitaji kutaja jina la safu, na kisha kutofautiana kwa thamani ya $.

Kwa kila marudio, thamani ya kipengee cha sasa imepewa $value variable. Baada ya kurudia kukamilika, kutofautisha kunapewa thamani ya kipengele kinachofuata. Na kadhalika mpaka vipengele vyote vya safu vimerudiwa.

  • Sintaksia ya njia ya pili ( PHP forach kama thamani muhimu):

Hii inafaa kwa safu shirikishi zinazotumia jozi za funguo/thamani.

Wakati wa kila marudio, thamani ya kipengele cha sasa itagawiwa kwa kigezo cha $value_of_element. Kwa kuongeza, ufunguo wa kipengele umepewa $key_of_element variable.

Ikiwa unafanya kazi na safu za nambari, unaweza kutumia njia ya kwanza, ambayo hauhitaji funguo za vipengele.

Chapisho hili ni tafsiri ya makala “ PHP foreach kitanzi njia 2 za kuitumia", iliyoandaliwa na timu ya mradi wa kirafiki

Katika muhtasari wa hivi karibuni wa viungo vya kupendeza kuhusu PHP, nilipata kiunga cha maoni ya Nikita Popov juu ya StackOverflow, ambapo anazungumza kwa undani juu ya utaratibu "chini ya kofia" ya ujenzi wa udhibiti wa mbele.
Kwa kuwa foreach wakati mwingine hufanya kazi kwa njia zaidi ya ya kushangaza, nimeona ni muhimu kutafsiri jibu hili.

Angalizo: maandishi haya yanachukua maarifa ya kimsingi ya utendakazi wa zvals katika PHP, haswa unapaswa kujua refcount na is_ref ni nini.
foreach hufanya kazi na vyombo vya aina tofauti: na safu, na vitu rahisi (ambapo sifa zinazopatikana zimeorodheshwa) na kwa vitu vinavyoweza Kupitika (au tuseme, vitu ambavyo vina kidhibiti cha get_iterator cha ndani kimefafanuliwa). Tunazungumza zaidi juu ya safu hapa, lakini nitazungumza juu ya zingine mwishoni kabisa.

Kabla ya kuanza, maneno machache kuhusu safu na upitishaji wao, muhimu kwa kuelewa muktadha.

Upitishaji wa safu hufanya kazije?

Safu katika PHP zimeagizwa jedwali la heshi (vipengee vya heshi vimeunganishwa kuwa orodha iliyounganishwa mara mbili) na foreach hupitia safu kufuatia mpangilio uliobainishwa.

PHP inajumuisha njia mbili za kuvuka safu:

  • Njia ya kwanza ni pointer ya safu ya ndani. Kielekezi hiki ni sehemu ya muundo wa HashTable na ni kielekezi kwa kipengele cha sasa cha jedwali la hashi. Pointer ya safu ya ndani inaweza kubadilishwa bila kutokujali, ambayo ni, ikiwa kipengee cha sasa kimefutwa, pointer ya safu ya ndani itahamishwa hadi inayofuata.
  • Utaratibu wa pili wa kurudia ni kiashiria cha safu ya nje kinachoitwa HashPosition. Hii kimsingi ni sawa na kiashirio cha safu ya ndani, lakini sio sehemu ya HashTable. Njia hii ya nje ya kurudia si rahisi kubadilisha-salama. Ukiondoa kipengee kilichoelekezwa na HashPosition, utabaki na kielekezi kinachoning'inia, ambacho kitasababisha hitilafu ya sehemu.

Kwa hivyo, viashiria vya safu ya nje vinapaswa kutumika tu wakati una uhakika kabisa kuwa hakuna msimbo wa mtumiaji utakaotekelezwa wakati wa kuvuka. Na nambari kama hiyo inaweza kuishia katika sehemu zisizotarajiwa, kama vile kidhibiti makosa au kiharibifu. Hii ndio sababu katika hali nyingi PHP lazima itumie kiashiria cha ndani badala ya cha nje. Ikiwa sivyo, PHP inaweza kuanguka na hitilafu ya sehemu mara tu mtumiaji anapoanza kufanya jambo lolote lisilo la kawaida.

Shida na kiashiria cha ndani ni kwamba ni sehemu ya HashTable. Kwa hivyo unapoibadilisha, HashTable inabadilika nayo. Na kwa kuwa safu katika PHP zinapatikana kwa thamani (na sio kwa kumbukumbu), unalazimika kunakili safu ili kuzunguka kupitia vitu vyake.

Mfano rahisi unaoonyesha umuhimu wa kunakili (sio kawaida, kwa njia) ni marudio ya kiota:

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

Hapa unataka vitanzi vyote viwili vijitegemee, na sio kutupwa kwa busara na pointer moja.

Kwa hivyo tunakuja kutabiri.

Kupitia safu katika foreach

Sasa unajua kwa nini foreach lazima iunde nakala ya safu kabla ya kuipitia. Lakini hii ni wazi sio hadithi nzima. Ikiwa PHP hufanya nakala au la inategemea mambo kadhaa:

  • Ikiwa safu inayoweza kutekelezwa ni rejeleo, hakuna kunakili kutatokea, badala yake addref itatekelezwa:

    $ref =& $safu; // $array ina is_ref=1 sasa foreach ($array as $val) ( // ... )
    Kwa nini? Kwa sababu mabadiliko yoyote kwenye safu lazima yaenezwe kwa marejeleo, pamoja na kielekezi cha ndani. Ikiwa foreach atatoa nakala katika kesi hii, ingevunja semantiki ya kiungo.

  • Ikiwa safu ina refcount=1, unakili hautafanywa tena. refcount=1 inamaanisha kuwa safu haitumiki mahali pengine na foreach inaweza kuitumia moja kwa moja. Ikiwa refcount ni kubwa kuliko moja, basi safu inashirikiwa na vigeu vingine na ili kuzuia urekebishaji, foreach lazima iinakili (bila kujali kesi ya marejeleo iliyoelezwa hapo juu).
  • Ikiwa safu inapitiwa-rejelea (foreach ($array as &$ref)), basi - bila kujali chaguo za kukokotoa za kunakili au zisizo za nakala - safu itakuwa marejeleo.

Kwa hivyo hii ndio sehemu ya kwanza ya fumbo: kazi ya nakala. Sehemu ya pili ni jinsi iteration ya sasa inatekelezwa, na pia ni ya kushangaza kabisa. Mchoro wa "kawaida" wa kurudia ambao tayari unajua (na ambao hutumiwa mara nyingi katika PHP - tofauti na foreach) inaonekana kama hii (pseudocode):

Weka upya(); wakati (get_current_data(&data) == SUCCESS) (code(); move_forward(); )
iteration foreach inaonekana tofauti kidogo:

Weka upya(); wakati (get_current_data(&data) == SUCCESS) ( move_forward(); code(); )

Tofauti ni kwamba move_forward() inatekelezwa mwanzoni badala ya mwisho wa kitanzi. Kwa hivyo, msimbo wa mtumiaji unapotumia kipengele $i, kielekezi cha safu ya ndani tayari kinaelekeza kwenye kipengele $i+1.

Njia hii ya utendakazi wa foreach pia ndio sababu kielekezi cha safu ya ndani kinasogea kwa kipengee kinachofuata ikiwa cha sasa kimefutwa, badala ya ile ya awali (kama unavyoweza kutarajia). Kila kitu kimeundwa kufanya kazi vizuri na foreach (lakini ni wazi haitafanya kazi vizuri na kila kitu kingine, kuruka vitu).

Athari za kanuni

Matokeo ya kwanza ya tabia iliyo hapo juu ni kwamba foreach inakili safu inayoweza kutekelezeka katika visa vingi (polepole). Lakini usiogope: Nilijaribu kuondoa hitaji la nakala na sikuweza kuona kasi yoyote mahali popote isipokuwa kwenye alama za bandia (ambazo ziliongezeka kwa kasi mara mbili). Inaonekana watu hawasomi vya kutosha.

Matokeo ya pili ni kwamba haipaswi kuwa na matokeo mengine. Tabia ya foreach kwa ujumla inaeleweka kabisa kwa mtumiaji na inafanya kazi kama inavyopaswa. Haupaswi kujali jinsi kunakili kunatokea (au ikiwa kunatokea kabisa), au ni kwa wakati gani maalum kwa wakati pointer inasogezwa.

Na matokeo ya tatu - na hapa ndipo tunapokuja kwa shida yako - ni kwamba wakati mwingine tunaona tabia ya kushangaza sana ambayo ni ngumu kuelewa. Hii hutokea hasa unapojaribu kurekebisha safu yenyewe, ambayo unapitia kwenye kitanzi.

Mkusanyiko mkubwa wa tabia ya kesi ya makali ambayo hutokea unaporekebisha safu wakati wa kurudia inaweza kupatikana katika majaribio ya PHP. Unaweza kuanza na mtihani huu, kisha ubadilishe 012 hadi 013 kwenye anwani, na kadhalika. Utaona jinsi tabia ya foreach itajidhihirisha katika hali tofauti (kila aina ya mchanganyiko wa viungo, nk).

Sasa turudi kwenye mifano yako:

Foreach ($array as $item) ( echo "$item\n"; $array = $item; ) print_r($array); /* Pato katika kitanzi: 1 2 3 4 5 $safu baada ya kitanzi: 1 2 3 4 5 1 2 3 4 5 */

Hapa $array ina refcount=1 kabla ya kitanzi kwa hivyo haitanakiliwa lakini itapata addref. Mara tu unapoweka thamani kwa $array, zval itagawanywa, kwa hivyo safu unayoongeza vitu na safu unayoirudia itakuwa safu mbili tofauti.

Foreach ($array as $key => $item) ( $array[$key + 1] = $item + 2; echo "$item\n"; ) print_r($array); /* Pato katika kitanzi: 1 2 3 4 5 $safu baada ya kitanzi: 1 3 4 5 6 7 */

Hali sawa na katika mtihani wa kwanza.

// Hamisha pointer kwa moja ili kuhakikisha kuwa haiathiri foreach var_dump(kila($array)); foreach ($array as $item) ( echo "$item\n"; ) var_dump(each($array)); /* Safu ya pato(4) ( => int(1) ["thamani"]=> int(1) => int(0) ["ufunguo"]=> int(0) ) 1 2 3 4 5 bool( uongo)*/

Hadithi sawa tena. Wakati wa kitanzi cha mbele, unayo refcount=1 na unapata tu addref, kiashiria cha ndani cha $array kitarekebishwa. Mwishoni mwa kitanzi, pointer inakuwa NULL (hii ina maana kwamba iteration imekamilika). kila mmoja anaonyesha hili kwa kurudisha uongo.

Foreach ($array as $key => $item) ( echo "$item\n"; kila($array); ) /* Pato: 1 2 3 4 5 */

Foreach ($array as $key => $item) ( echo "$item\n"; weka upya($array); ) /* Pato: 1 2 3 4 5 */

Lakini mifano hii haishawishi vya kutosha. Tabia huanza kuwa haitabiriki kabisa unapotumia sasa kwenye kitanzi:

Foreach ($array as $val) ( var_dump(current($array));) /* Pato: 2 2 2 2 2 */

Hapa unapaswa kukumbuka kuwa mkondo pia unapatikana kwa kumbukumbu, licha ya kutorekebisha safu. Hii inahitajika ili kufanya kazi kwa uthabiti na kazi zingine zote, kama inayofuata, ufikiaji huo kwa marejeleo (sasa ni kazi bora ya ref; inaweza kupata dhamana, lakini hutumia rejeleo ikiwa inaweza). Rejeleo linamaanisha kuwa safu lazima itenganishwe, kwa hivyo $array na nakala ya $array ambayo foreach hutumia itakuwa huru. Kwa nini unapata 2 na sio 1 pia imetajwa hapo juu: pointer ya safu ya nyongeza ya foreach kabla ya kuanza kwa nambari ya mtumiaji, sio baada. Kwa hivyo hata kama msimbo bado unafanya kazi kwenye kipengele cha kwanza, foreach tayari imehamisha pointer hadi ya pili.

Sasa hebu tujaribu mabadiliko madogo:

$ref = &$safu; foreach ($array as $val) ( var_dump(current($array)); ) /* Pato: 2 3 4 5 uongo */

Hapa tunayo is_ref=1, kwa hivyo safu haijanakiliwa (sawa na hapo juu). Lakini sasa kwa kuwa kuna is_ref, safu haitaji tena kugawanywa, kupita kwa kumbukumbu ya sasa. Sasa kazi ya sasa na ya mbele na safu sawa. Unaona safu ikibadilishwa na moja haswa kwa sababu ya jinsi foreach inavyoshughulikia pointer.

Utaona kitu kimoja wakati unapitia safu kwa kumbukumbu:

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

Jambo la muhimu hapa ni kwamba foreach itakabidhi $array yetu is_ref=1 inapozunguka juu yake kwa rejeleo, kwa hivyo itaishia sawa na hapo juu.

Tofauti nyingine ndogo, hapa tutagawa safu yetu kwa tofauti nyingine:

$ foo = $ safu; foreach ($array as $val) ( var_dump(current($array));) /* Pato: 1 1 1 1 1 */

Hapa refcount ya $array imewekwa kuwa 2 wakati kitanzi kilianza, kwa hivyo nakala inahitaji kufanywa kabla ya kuanza. Kwa hivyo $array na safu inayotumiwa na foreach itakuwa tofauti na mwanzo. Ndiyo sababu unapata nafasi ya pointer ya safu ya ndani ambayo ilikuwa muhimu kabla ya kitanzi kuanza (katika kesi hii ilikuwa katika nafasi ya kwanza).

Iteration ya vitu

Wakati wa kurudia vitu, ni jambo la busara kuzingatia kesi mbili:

Kitu hicho hakiwezi Kupitika (au tuseme, kidhibiti cha get_iterator cha ndani hakijafafanuliwa)

Katika kesi hii, iteration hutokea karibu sawa na kwa safu. Semantiki sawa za kunakili. Tofauti pekee ni kwamba foreach itatumia nambari ya ziada ili kuruka mali ambazo hazipatikani katika wigo wa sasa. Mambo kadhaa ya kuvutia zaidi:

  • Kwa mali iliyotangazwa, PHP huboresha jedwali la hashi ya mali. Ukirudisha kitu, lazima itengeneze tena jedwali hilo la hashi (ambayo huongeza utumiaji wa kumbukumbu). Sio kwamba unapaswa kuwa na wasiwasi juu yake, fahamu tu.
  • Katika kila marudio, jedwali la hashi la mali litapatikana tena, kumaanisha PHP itaita get_properties tena na tena na tena. Kwa mali "ya kawaida" hii sio muhimu sana, lakini ikiwa mali zinaundwa kwa nguvu (hii mara nyingi hufanywa na madarasa yaliyojengwa) basi meza ya mali itahesabiwa upya kila wakati.
Kitu kinachoweza kupitika

Katika kesi hii, kila kitu kilichosemwa hapo juu hakitatumika kwa njia yoyote. Pia, PHP haitanakili na haitatumia hila zozote kama nyongeza za pointer kabla ya kuzunguka. Nadhani njia ya kupita kwenye kitu kinachoweza Kupitika inaweza kutabirika zaidi na hauhitaji maelezo zaidi.

Kubadilisha iterable wakati wa kitanzi

Kesi nyingine isiyo ya kawaida ambayo sikutaja ni kwamba PHP inaruhusu uwezo wa kuchukua nafasi ya iterable wakati wa kitanzi. Unaweza kuanza na safu moja na kuendelea kwa kuibadilisha na nyingine katikati. Au anza na safu, kisha ubadilishe na kitu:

$ arr = ; $obj = (kitu) ; $ref =& $arr; foreach ($ref as $val) ( echo "$val\n"; ikiwa ($val == 3) ( $ref = $obj; ) ) /* Pato: 1 2 3 6 7 8 9 10 */

Kama unaweza kuona, PHP ilianza tu kuvuka chombo kingine mara tu uingizwaji ulipotokea.

Kubadilisha kielekezi cha safu ya ndani wakati wa kurudia

Maelezo moja ya mwisho ya tabia ya mbele ambayo sikutaja (kwa sababu inaweza kutumika kupata tabia ya ajabu kweli): nini kinaweza kutokea ikiwa utajaribu kubadilisha kiashiria cha safu ya ndani wakati wa kitanzi.

Hapa huwezi kupata kile ulichotarajia: ikiwa unapiga simu inayofuata au iliyotangulia kwenye mwili wa kitanzi (katika kesi ya kupita kwa kumbukumbu), utaona kuwa pointer ya ndani imehamia, lakini hii haina athari kwa tabia ya mtangazaji. Sababu ni kwamba foreach hufanya chelezo ya nafasi ya sasa na heshi ya kipengele cha sasa katika HashPointer baada ya kila kupita ya kitanzi. Katika pasi inayofuata, foreach itakagua ili kuona ikiwa nafasi ya kielekezi cha ndani imebadilika na ujaribu kuirejesha kwa kutumia heshi hii.

Wacha tuone "nitajaribu" inamaanisha nini. Mfano wa kwanza unaonyesha jinsi kubadilisha pointer ya ndani haibadilishi hali ya mbele:

$safu =; $ref =& $safu; foreach (safu ya $ kama $value) ( var_dump($value); weka upya($array);) // pato: 1, 2, 3, 4, 5

Sasa wacha tujaribu kuweka kipengee ambacho foreach itapata kwenye kibali cha kwanza (ufunguo 1):

$safu =; $ref =& $safu; foreach (safu ya $ kama thamani ya $) ( var_dump($value); haijawekwa($array); weka upya($array); ) // pato: 1, 1, 3, 4, 5

Hapa utaona kuwa kaunta imewekwa upya kwa sababu kipengele kilicho na heshi inayolingana hakikuweza kupatikana.

Kumbuka, heshi ni heshi tu. Migongano hutokea. Hebu tujaribu hii sasa:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $safu; foreach (safu ya $ kama $value) ( unset($array["EzFY"]); $array["FYFZ"] = 4; weka upya($array); var_dump($value);) // pato: 1 1 3 4

Inafanya kazi kama tulivyotarajia. Tuliondoa ufunguo wa EzFY (ile ambayo foreach ilikuwa iko), kwa hivyo kuweka upya kulifanyika. Pia tuliongeza ufunguo wa ziada, kwa hivyo tunaona 4 mwishoni.

Na hapa inakuja haijulikani. Nini kitatokea ikiwa utabadilisha kitufe cha FYFY na FYFZ? Tujaribu:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $safu; foreach (safu ya $ kama thamani ya $) ( "haijawekwa($array["EzFY"]); $array["FYFY"] = 4; weka upya($array); var_dump($value); ) // pato: 1 4

Sasa kitanzi kimehamia moja kwa moja kwenye kipengele kipya, kikiruka kila kitu kingine. Hii ni kwa sababu kitufe cha FYFY kina mgongano na EzFY (kwa kweli, funguo zote kutoka kwa safu hii pia). Zaidi ya hayo, kipengele cha FYFY kiko kwenye anwani ya kumbukumbu sawa na kipengele cha EzFY ambacho kilikuwa kimefutwa. Kwa hivyo kwa PHP itakuwa nafasi sawa na heshi sawa. Msimamo "umerejeshwa" na mpito hadi mwisho wa safu hutokea.

Mara nyingi unahitaji kurudia kupitia vipengele vyote vya safu ya PHP na kufanya operesheni fulani kwenye kila kipengele. Kwa mfano, unaweza kutoa kila thamani kwenye jedwali la HTML au upe kila kipengele thamani mpya.

Katika somo hili tutaangalia muundo wa mbele wakati wa kupanga kitanzi juu ya safu zilizo na alama na zinazohusiana.

Pitia maadili ya vipengele

Kesi rahisi zaidi ya utumiaji kwa foreach ni kuzunguka kwa maadili katika safu iliyoorodheshwa. Sintaksia ya msingi:

Foreach ($array as $value) (// Fanya kitu na $value ) // Hapa nambari inatekelezwa baada ya kitanzi kukamilika.

Kwa mfano, hati ifuatayo inarudia kupitia orodha ya wakurugenzi katika safu iliyoorodheshwa na kuchapisha jina la kila moja:

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

Nambari iliyo hapo juu itatoa:

Alfred Hitchcock Stanley Kubrick Martin Scorsese Fritz Lang

Kitanzi cha Thamani Muhimu

Vipi kuhusu safu zinazohusiana? Unapotumia aina hii ya safu, mara nyingi unahitaji kupata ufunguo wa kila kipengele pamoja na thamani yake. Ubunifu wa mbele una njia ya kutatua shida:

Foreach ($array as $key => $value) ( ​​// Fanya kitu na $key na/au $value ) // Hapa msimbo unatekelezwa baada ya kitanzi kukamilika.

Mfano wa kupanga kitanzi kupitia safu inayohusishwa na habari kuhusu filamu, inayoonyesha ufunguo wa kila kipengele na thamani yake katika orodha ya HTML ya ufafanuzi:

$movie = safu("title" => "Dirisha la Nyuma", "director" => "Alfred Hitchcock", "year" => 1954, "minutes" => 112); mwangwi"

"; foreach ($movie as $key => $value) ( echo "
$key:
"; mwangwi"
$thamani
";) mwangwi"
";

Inapotekelezwa, hati hii itatoa:

Kichwa: Mkurugenzi wa Dirisha la Nyuma: Alfred Hitchcock mwaka: dakika 1954: 112

Kubadilisha thamani ya kipengele

Vipi kuhusu kubadilisha thamani ya kitu kitanzi kinapopitia? Unaweza kujaribu nambari hii:

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

Walakini, ikiwa utaiendesha, utapata kuwa maadili kwenye safu usibadilike. Sababu ni kwamba foreach inafanya kazi na nakala thamani za safu, sio na asili. Kwa njia hii safu asili inabaki kuwa sawa.

Ili kubadilisha maadili ya safu unayohitaji kiungo kwa maana. Ili kufanya hivyo, unahitaji kuweka & ishara mbele ya utofauti wa thamani katika ujenzi wa foreach:

Foreach ($myArray kama &$value) ($value = 123; )

Kwa mfano, hati ifuatayo inazunguka kwa kila kipengele (jina la mkurugenzi) katika safu ya wakurugenzi $, na hutumia kitendakazi cha PHP explode() na muundo wa orodha kubadilisha majina ya kwanza na ya mwisho:

$ wakurugenzi = safu("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); // Badilisha muundo wa jina kwa kila kipengele cha mbele ($directors kama &$director) ( list($firstName, $lastName) = explode(" ", $director); $director = "$lastName, $firstName"; ) haijawekwa (mkurugenzi wa $); // Chapisha matokeo ya mwisho kwa kila mmoja ($directors kama $director) ( echo $director . "
"; }

Hati itatoa:

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

Kumbuka kuwa hati huita kazi ya unset() ili kuondoa utofauti wa $director baada ya kitanzi cha kwanza kukamilika. Hii ni mazoezi mazuri ikiwa unapanga kutumia kutofautisha baadaye kwenye hati katika muktadha tofauti.

Usipoondoa marejeleo, unakuwa na hatari ya kutekeleza zaidi msimbo unaorejelea kwa bahati mbaya kipengele cha mwisho kwenye safu ("Lang, Fritz") ikiwa utaendelea kutumia utofauti wa $director, ambao utasababisha matokeo yasiyotarajiwa!

Muhtasari

Katika somo hili, tuliangalia jinsi ya kutumia PHP foreach construct ili kupitia vipengele vya safu. Masuala yafuatayo yalizingatiwa:

  • Jinsi ya kuzunguka kupitia vitu vya safu
  • Jinsi ya kupata ufunguo na thamani ya kila kipengele
  • Jinsi ya kutumia rejeleo kubadilisha maadili unapopitia kitanzi

Fikiria una safu ya ushirika ambayo ungependa kuirudia. PHP hutoa njia rahisi ya kutumia kila kipengele cha safu kwa zamu kwa kutumia Foreach construct.

Kwa lugha rahisi ingesikika kama hii:
"Kwa kila kipengele katika safu maalum, tekeleza nambari hii."

Ingawa itaendelea mradi hali fulani imetimizwa, kitanzi cha mbele kitaendelea hadi kipitie kila kipengele cha safu.

PHP Foreach: Mfano

Tuna safu ya ushirika ambayo huhifadhi majina ya watu katika kampuni yetu, pamoja na umri wao. Tunataka kujua kila mfanyakazi ana umri gani, kwa hivyo tunatumia kitanzi kwa kila mmoja kuchapisha jina na umri wa kila mtu.

Enzi za $mfanyakazi; $employeeAges["Lisa"] = "28"; $employeeAges["Jack"] = "16"; $employeeAges["Ryan"] = "35"; $employeeAges["Rachel"] = "46"; $employeeAges["Grace"] = "34"; foreach($employeeAges as $key => $value)( echo "Jina: $key, Umri: $value
"; }

Tunapata matokeo:

Jina: Lisa, Umri: 28 Jina: Jack, Umri: 16 Jina: Ryan, Umri: 35 Jina: Rachel, Umri: 46 Jina: Grace, Umri: 34

Kweli, matokeo ni mazuri na yanaeleweka, lakini syntax ya ujenzi wa foreach sio rahisi sana na inaeleweka. Hebu tuangalie kwa karibu zaidi.

Kwa kila syntax: $something as $key => $value

Wazimu huu wote unatafsiriwa kuwa: "Kwa kila kipengele cha safu ya ushirika $employeeAges, ninataka kufikia $key na thamani iliyo ndani yake, yaani $value.

Opereta "=>" inawakilisha uhusiano kati ya ufunguo na thamani. Katika mfano wetu, tulizitaja kama ufunguo - $key na thamani - $value. Walakini, itakuwa rahisi kuwafikiria kama jina na umri. Chini ya mfano wetu tutafanya hivi, na kumbuka kuwa matokeo yatakuwa sawa kwa sababu tulibadilisha tu majina ya vigezo vinavyohusiana na funguo na maadili.

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

Naam, matokeo, tunarudia, ni sawa.