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.  ;)