Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Michal Švarc 06. 11. 2020, 04:58:54
-
<?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á
-
Co to vypíše a co jste očekával?
-
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
-
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.
-
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.
-
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.
-
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.
-
Děkuji všem za vyčerpávající odpovědi. ;)