Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Michal Švarc 06. 11. 2020, 04:58:54

Název: Pole a foreach v PHP
Přispěvatel: Michal Švarc 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á
Název: Re:Pole a foreach v PHP
Přispěvatel: qelurg 06. 11. 2020, 07:34:13
Co to vypíše a co jste očekával?
Název: Re:Pole a foreach v PHP
Přispěvatel: Rob Ros 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
Název: Re:Pole a foreach v PHP
Přispěvatel: Michal Švarc 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.
Název: Re:Pole a foreach v PHP
Přispěvatel: tecka 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.
Název: Re:Pole a foreach v PHP
Přispěvatel: Kit 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.
Název: Re:Pole a foreach v PHP
Přispěvatel: Hamparle 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.
Název: Re:Pole a foreach v PHP
Přispěvatel: Michal Švarc 07. 11. 2020, 22:44:59
Děkuji všem za vyčerpávající odpovědi.  ;)