Bezpečnější foreach v latte

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Honza Marek
Člen | 1664
+
0
-

V PHP mě irituje ta vlastnost foreache, že dokáže přepsat dříve definovanou proměnnou, která se nešťastnou shodou okolností jmenuje stejně jako proměnná, do které foreach ukládá procházené prvky.

$name = 'name';

foreach (array('a', 'b', 'c') as $name) {

}

echo $name; // vypíše c místo name

To vede k občasným záhadným chybám v šablonách. Nemohlo by tedy latte předchozí proměnnou (pokud existuje) před foreachem zazálohovat a pak jí navrátit původní obsah?

David Grudl
Nette Core | 8227
+
0
-

Taky jsem na to párkrát narazil, ale nejsem si vědom žádného non-WTF způsobu, jak to řešit.

Foowie
Člen | 269
+
0
-

Možná by se mohla proměnná po ukončení cyklu alespoň unsetnout.

Honza Marek
Člen | 1664
+
0
-

DG: vyparsovat z „expression as $a ⇒ $b“ názvy proměnných za as, kouknout na ně v get_defined_vars. Pak by možná stačilo vyhodit laděnku s varováním a nemuselo by se nijak čarovat se zálohováním původních hodnot.

Foowie: To je k ničemu. Pokud mi foreach něco omylem přepíše nebo omylem smaže, to vyjde na stejno.

Filip Procházka
Moderator | 4668
+
0
-

Mohlo by to vyhazovat třeba notice…

Tomáš Kolinger
Člen | 136
+
0
-

V případě přepsání vyhodit laděnku…

To zálohování je víc WTF, než samotná vlastnost PHP. Hlavně když si na to člověk zvykl.

paranoiq
Člen | 392
+
0
-

Foowie napsal(a):

Možná by se mohla proměnná po ukončení cyklu alespoň unsetnout.

někdy je ale účelem, aby poslední hodnota zůstala v proměnné

mkoubik
Člen | 728
+
0
-

paranoiq: V tom případě si ji můžeš před cyklem unsetnout, nebo ještě lépe pojmenovat si ji tak, aby s ničím nekolidovala.

David Grudl
Nette Core | 8227
+
0
-

Honza Marek napsal(a):

DG: vyparsovat z „expression as $a ⇒ $b“ názvy proměnných za as, kouknout na ně v get_defined_vars. Pak by možná stačilo vyhodit laděnku s varováním a nemuselo by se nijak čarovat se zálohováním původních hodnot.

Jako že by

{foreach $cokoliv as $item}...{/foreach}
{foreach $cokoliv as $item}...{/foreach}

Vyhodilo varování, že si mám v každém cyklu vymyslet jinou proměnou? Olalá!

juzna.cz
Člen | 248
+
0
-

Fixing magic with more magic :)
Taky se mi parkrat stalo, ze jsem kvuli tomuto zuril a chtel to zmenit. Ale jak se clovek uklidni, dojde mu, ze by vznikly daleko vetsi WTF a ze by v budoucnu asi zuril jeste vic.

(toto aspon kazdemu dojde, pze je to tak v PHP; ale kdo by pak mohl tusit, jak se chova latte, ktere do detailu nezna)

Spise bych to resil nejakou statickou analyzou na urovni IDE

paranoiq
Člen | 392
+
0
-

@mkoubik: wtf?

Milo
Nette Core | 1283
+
0
-
// Kontrolovat jedinečnost $item, na konci cyklu unset($item),
// nebo spustit v limited scope.
{foreach $items as $item}...{/foreach}

// Nic nekontrolovat
{!foreach $items as $item}...{/foreach}
jtousek
Člen | 951
+
0
-

Milo napsal(a):

// Kontrolovat jedinečnost $item, na konci cyklu unset($item),
// nebo spustit v limited scope.
{foreach $items as $item}...{/foreach}

// Nic nekontrolovat
{!foreach $items as $item}...{/foreach}

Když už tak kvůli zpětné kompatibilitě raději naopak.

mkoubik
Člen | 728
+
0
-

paranoiq: Po skončení cyklu by ti tam ta proměnná normálně zůstala. Nicméně jak nad tím přemýšlím, tak by to bylo velký WTF.

paranoiq
Člen | 392
+
0
-

pořád nerozumím na co vlastně reaguješ :]

  • k čemu unsetování před cyklem, když se stejně v cyklu přepíše?
  • jak „pojmenovat aby nekolidovala“? tahle debata je právě o tom jak onu kolizi rozumě detekovat (a asi to nejde)

@jtousek: to ale odporuje konvenci vykřičníku ve zbytku Latte

mkoubik
Člen | 728
+
0
-

Reagoval jsem na:

někdy je ale účelem, aby poslední hodnota zůstala v proměnné

Navrhovaná úprava (vyhazovaní notice) by tohle nerozbila (pokud jsi tu proměnnou nepoužil už předtím).

// tady $item neexistuje
foreach ($items as $item) { ... }
// tady $item obsahuje poslední položku, no problem
Honza Marek
Člen | 1664
+
0
-

David Grudl napsal(a):

Jako že by

{foreach $cokoliv as $item}...{/foreach}
{foreach $cokoliv as $item}...{/foreach}

Vyhodilo varování, že si mám v každém cyklu vymyslet jinou proměnou? Olalá!

No tak pak se to bude muset kontrolovat jen proti $template->getParameters()… #tonoucisesteblachyta

uestla
Backer | 799
+
0
-

Nedá mi to nereagovat:

Myslím, že tohle už by bylo až moc, mohlo by to dokonce býti i na škodu.

PHP holt takové je, a faktu, že iterační proměnné jsou po doběhnutí skriptu „obsazené“ hodnotami z poslední iterace, může někdo využívat.

Pak je jakákoli machinace (jako udělat iterační proměnné lokální jen pro vnitřek cyklu, kontrola předchozí obsazenosti proměnné se stejným jménem, atd.) vyloženě nežádoucí.

Editoval uestla (12. 6. 2012 0:02)