Pole a foreach v PHP

Pole a foreach v PHP
« kdy: 06. 11. 2020, 04:58:54 »
Kód: [Vybrat]
<?php
$title 
"Oříšek v PHP";

$vstup "1,2,3,4,5,6,7,8,9";
$vstup2 "1,3,4,5,7,8";

$vstupA explode(','$vstup);

foreach (
$vstupA as &$val)
{
echo "$val * $val - $val = ".($val $val $val)."<br>";
}
$vstupB explode(','$vstup2);

echo 
"<strong>\$vstupA:<br>".str_replace(PHP_EOL"<br>"print_r($vstupA,true))."</strong>";
echo 
"<strong>\$vstupB:<br>".str_replace(PHP_EOL"<br>"print_r($vstupB,true))."</strong>";

$porovnani array_diff((array)$vstupA,(array)$vstupB);
echo 
"<strong>\$porovnani po array_diff((array)\$vstupA,(array)\$vstupB):<br>".str_replace(PHP_EOL"<br>"print_r($porovnani,true))."</strong>";

foreach ((array)
$porovnani as $key => $val)
{
echo "<strong>\$key($key) => \$val($val)</strong><br>";
}
?>

druhý foreach vypíše (pro mě) překvapivé hodnoty a mne by zajímal co možná nejpodrobnější důvod, proč se takto chová


qelurg

  • ****
  • 386
    • Zobrazit profil
    • E-mail
Re:Pole a foreach v PHP
« Odpověď #1 kdy: 06. 11. 2020, 07:34:13 »
Co to vypíše a co jste očekával?

Re:Pole a foreach v PHP
« Odpověď #2 kdy: 06. 11. 2020, 07:42:24 »
Pouzivate $val jako referenci v prvnim foreach, coz vede k vysledku, ktery neocekavate. Takze bud nepouzivejte referenci v prvnim foreach nebo ji po provedeni cyklu zruste pomoci unset.

Podobny priklad je tady v prvnim varovani: https://www.php.net/manual/en/control-structures.foreach.php

Re:Pole a foreach v PHP
« Odpověď #3 kdy: 06. 11. 2020, 19:34:09 »
Co to vypíše a co jste očekával?
Vpodstatě viz. Rob Ros. Kód je upravený tak, aby, když se spustí na serveru, vypsal všechny informace o jednotlivých polích a výsledku.
Pouzivate $val jako referenci v prvnim foreach, coz vede k vysledku, ktery neocekavate. Takze bud nepouzivejte referenci v prvnim foreach nebo ji po provedeni cyklu zruste pomoci unset.
Vím, co to dělá i jak to upravit, ale uzajímalo mě proto to tak funguje. Prostě mě zajímá 'jádro pudla'.
Kamarád přišel s tezí, že se tam nějak ukládá ukazatel, který projde krz všechny změny až do posledního pole a tam pak dělá rámus.
A mě teď prostě zajímá, jak to co nejpřesněji je a proč to tak je.

tecka

  • ***
  • 165
    • Zobrazit profil
    • E-mail
Re:Pole a foreach v PHP
« Odpověď #4 kdy: 07. 11. 2020, 07:47:43 »
Vím, co to dělá i jak to upravit, ale uzajímalo mě proto to tak funguje. Prostě mě zajímá 'jádro pudla'.
Na tom odkazu od Roba je kód s komentáři, které ten problém vysvětlují. Pokud reference nechápeš, tak je nepoužívej.


Kit

  • *****
  • 721
    • Zobrazit profil
    • E-mail
Re:Pole a foreach v PHP
« Odpověď #5 kdy: 07. 11. 2020, 12:34:26 »
Kód je upravený tak, aby, když se spustí na serveru, vypsal všechny informace o jednotlivých polích a výsledku.

Bez těch zbytečných značek HTML by to bylo čitelnější. Asi to prohlížíš browserem, že?

Kamarád přišel s tezí, že se tam nějak ukládá ukazatel, který projde krz všechny změny až do posledního pole a tam pak dělá rámus.
A mě teď prostě zajímá, jak to co nejpřesněji je a proč to tak je.

Však přesně tohle dělá symbol "&". Stačí přestat s recyklací proměnných a bude to v suchu.

Hamparle

  • ****
  • 365
  • junior developer ucho
    • Zobrazit profil
    • E-mail
Re:Pole a foreach v PHP
« Odpověď #6 kdy: 07. 11. 2020, 14:46:38 »
Chce se to naučit funkce var_dump, takhle se to nedá číst. Případně do toho neplést html, a používat Content-type: text/plain. (nebo <PRE>). Když už masochismus, tak nl2br .



A Skutečně už žádné další hlubší vysvětlení není. Klíčové věci jsou, že při použítí  as &$val opakovaně vzniká proměnná $val, která ukazuje na aktuální prvek (přesněji řečeno hodnotu prvku) ) a zůstane na posledním po skončení a že array_diff v tom vytváří rozdílové pole tak, že tam do hodnoty prvků přejímá jak jsou, takže i s referencemi.

A v dalším cyklu použití as $val znamená, do proměnné $val ulož něco.


Zdálo by se že řešení, je použít i v druhém cyklu  taky as &$val, ale to jen odsune problém.



Kromě taky var_dump by ti ukázala, že u posledního prvku vstupA je symbol &, značící, že existuje reference na tento člen.

Právě reference jsou v programování nebezpečná věc, právě se to ukázalo, protože ty někde v kódu si vytvoříš referenci $val a s vstupAa pak někde kousek jinde použiješ $val v domění, že si vytváříš novou proměnnou...


Tím spíš v cyklech, tam dokonce střídavě $val se nastavuje na všechny prvky a zůstane na posledním...

Kromě toho je rozdíl mezi unset($val) a $val=null;




To znamená, že při druhém foreach opět dráždíš spícího hada,, probudil si hotím, že v každé iteraci se proměnné, které je dostupné jako  $val  a jako poslední prvek $vstup a ještě dokonce i jako $porovnani[8] přiřazuješ různé hodnoty. a tím měníš proměnou nikoli na 2,6,9, ale na 2, pak 6 , a v ttřetí iteraci přiřazuješ "proměnné stejnou proměnnnou " protože obě ukazují na stejnou hodnotu.
« Poslední změna: 07. 11. 2020, 14:52:45 od Hamparle »

Re:Pole a foreach v PHP
« Odpověď #7 kdy: 07. 11. 2020, 22:44:59 »
Děkuji všem za vyčerpávající odpovědi.  ;)