Je ArrayHash omyl? … Předmět nesmí být kratší než 25 znaků

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Filip Procházka
Moderator | 4668
+
0
-

Ahoj, chtěl bych se zeptat…

  • na co je dobrý ArrayHash?
  • proč mám pocit, že když už byl využit v Nette\Database, tak byl vnucen i formulářům, kterým tím totálně zničil jakoukoliv zpětnou kompatibilitu, jen aby byl použit i někde jinde?
  • proč je vnucen do $container->params?

Opravdu v něm nevidím nic užitečného, naopak přináší spoustu problémů s přetypováním a přepisováním hromady kódu, „jenom aby to byl objekt“.

Pokud to je nějaký princip čistoty, tak se mi vůbec nelíbí.

Nerad bych, aby to vyznělo, že teď David musí bránit ArrayHash, protože se mně nelíbí (a spoustě dalších lidí činí velké problémy), ale opravdu bych rád znal alespoň nějaké výhody při použití ve formulářích a contextu (kromě voňavějšího zápisu $context->params->database vs $context->params['database']).

PS: dost mi tam chybí metoda toArray, proč tam není? Má význam posílat pull?

22
Člen | 1478
+
0
-

$arrayHash->toArray() !== (array) $arrayHash ???

Filip Procházka
Moderator | 4668
+
0
-

Páááni, nevěděl jsem že (array) umí ArrayHash přetypovat rekurzivně? :)) Díky, problém vyřešen!

Počkat… vlastně neumí, jiné nápady?

PS: Je veselé jak mi okamžitě třemi různými kanály začali radit lidé, s tou největší pitomostí, která je z toho příspěvku úplně nejméně podstatná…

Editoval HosipLan (30. 6. 2011 9:07)

22
Člen | 1478
+
0
-

já ti neradil, já se spíš ptal :-) rekurze mě nenapadla

Tharos
Člen | 1030
+
0
-

HosipLan: Můžeš zkusit ještě interator_to_array($arrayHash). Jinak já ArrayHash občas používám proto, protože se pak snadno předává skrz aplikaci jako reference (ne jako kopie u klasického pole). Pro jednoduché kolekce mi přijde ideální.

Editoval Tharos (30. 6. 2011 9:35)

Patrik Votoček
Člen | 2221
+
0
-

$arrayHash->getIterator()->getArrayCopy();

Jinak souhlasím s @Tharos.

nanuqcz
Člen | 822
+
0
-

Ahoj, můžete pls vysvětlit méně zkušenému programátorovi, v čem je problém? Ony nefungují obě varianty zároveň ($context->params->database i $context->params['database']) ? Díky :-)

Filip Procházka
Moderator | 4668
+
0
-

To je pěkné :) asi tu poslední větu umažu… To si opravdu myslíte, že si to neumím přetypovat?

@**xxxObiWan**: fungují

@**Tharos**, @**Patrik Votoček**:

$data = ArrayHash::from($array);
$model->method($data);
$data = (object)$array;
$model->method($data);

Neskutečnej rozdíl ;)

Nefungují php funkce, rozbilo nám to snad všechny validace v systému, nemám jak dohledat, kde musím všechny validace opravit, jenom proto, že je to i ve formulářích. Všechno co se do teď změnilo ve dvojce bylo úplně v pohodě, až na tohle. Tohle je neskutečný porod přemigrovat.

Takže ptám se, znovu.

Jaké má výhody ArrayHash? Kromě toho, že mi umí pole přetypovat rekurzivně, což jsem ještě nikdy nepotřeboval a neumí ho přetypovat zpátky rekurzivně, což bych ocenil.

A už mi prosím neraďte jak se přetypovává objekt… diky

JakubJarabica
Gold Partner | 184
+
0
-

@Hosiplan: Co sa tyka formularov, nenapadlo ta prepisat getValues aby vracala uz pretypovane udaje?

Patrik Votoček
Člen | 2221
+
0
-

HosipLan napsal(a):

Páááni, nevěděl jsem že (array) umí ArrayHash přetypovat rekurzivně? :)) Díky, problém vyřešen!

Počkat… vlastně neumí, jiné nápady?

Sorry ale v tomhle se ta ironie fakt blbě hledá! (str_replace("? :)) Díky, problém vyřešen!", "! :))", ...))

Neskutečnej rozdíl ;)

Přesně tak! A o ten rozdíl jde! :-)

… že je to i ve formulářích. Všechno co se do teď změnilo ve dvojce bylo úplně v pohodě, až na tohle.

Počkat ale formuláře ArrayHash používají už nevím jak dlouho… :-) (a neříkej že zrovna ty jedeš na 0.9.x).

Nox
Člen | 378
+
0
-

@JAM3SoN: tak ono to řešit asi jde, je ale otázka jestli je ArrayHash celkově prospěšný pro všechny co používají Nette, jestli to tak fakt nechat

Filip Procházka
Moderator | 4668
+
0
-

@**JAM3SoN**: Konstruktivní nápad, díky! Jenom je blbé, že bych toho musel měnit poněkud více. Kontejnery, vlastni formulářové prvky, … ale dobrý nápad, díky!

@**Patrik Votoček**: Ja ne, firma ano. Ale o to nejde, to se prostě přepíše a odladí.

Jenom jsem se ale do teď pořád od nikoho nedozvěděl, co mi přinesl ArrayHash užitečného.

PS: Všimněte si prosím, že příspěvek je v obecné diskuzi, ne v bug reportech nebo feature requestech!

Editoval HosipLan (30. 6. 2011 12:10)

Tharos
Člen | 1030
+
0
-

@HosipLan: Zvolil jsi příklad koulervoucí :) (využívající ArrayHash::from s předáním již existujícího pole). Teď si vem následující kódy:

$collection = array();

$collection[1] = 'foo';
$collection[2] = 'bar';

$this->doSomethingUsefull((object) $collection);
$collection = new Nette\ArrayHash;

$collection[1] = 'foo';
$collection[2] = 'bar';

$this->doSomethingUsefull($collection);

Osobně bych pro lepší čitelnost volil druhou variantu.

Filip Procházka
Moderator | 4668
+
0
-

To je ale tvůj subjektivní názor, a podle mě to dost záleží na konkrétním use-case a v čitelnosti nevidím rozdíl.

Když budu chtít pracovat s daty, které jsou logicky seznam, pak budu psát.

$list = array();
$list[] = 'a';

$model->method($list);

když budu pracovat s asociativním polem, tak podle zvyku

$assoc = array();
$assoc['a'] = 'b';

$model->method($list);

když budu mít potřebu, to mít jako objekt…

$o = (object)NULL;
$o = (object)array();
$o = new stdClass; // tohle se mi nevímproč nelíbí
$o = new ArrayCollection();
$o = new MojeTrida();

$o->klic = 'neco';

$model->method($o);

echo $o->klic; // očekávám nějakou případnou modifikaci

Pokud tam nemáš ohromne megabajty, tak se ti nemůže vyplatit to předávat objektem…

Také bych upozornil všechny na Davidův článek Černá magie optimalizace, který mimo jiné říká, že když předanou hodnotu nezměním, pak stále ukazuje na stejnou fyzickou hodnotu v paměti a jenom přibývají ukazatelé.

Takže v 87% případů, jenom zkontroluji hodnoty a uložím do databáze (když nepočítám převádění na DateTime a pod drobnosti)

Jo a taky mi ptáček cvrlikáček našeptal, že Davídek se kdysi rozčiloval jak ArrayObject a podobné nejdou protahovat PHP funkcemi array_*, takže tohle by mě taky zajímalo, proč změnil názor.

PS: Prej to ženu zlým tónem, takže se dyštak omlouvám, já nejsem zlej.. jenom možná trochu nevyspalej :)

edit: něco o hash mapách k tématu: http://pastebin.com/82uwyqEi

Editoval HosipLan (30. 6. 2011 13:38)

vyvazil.jakub
Člen | 6
+
0
-

Popravdě jsem nad tím samým přemýšlel taky, takže se přidávám k otázce :)

David Grudl
Nette Core | 8228
+
0
-

V prvé řadě bych poprosil snížit míru ironie, jinak se nedomluvíme.

Anonymní objekt (tj. objekt třídy stdClass) je v PHP v podstatě zbytečná věc, protože tu máme vícefunkční pole. Nicméně anonymní objekt má výhodu příjemnější syntaxe $val->item místo $val['item'] a zároveň určité odlišnosti oproti poli: předává se referencí, má jiný přístup k číselným hodnotám, zakazuje prázdné klíče a taky klíče obsahující \x00. Nejde tedy jen o syntaktickou úsporu dvou znaků, ale má to určitý filosofický přesah. Prostě to není pole.

ArrayHash je nadstavbou nad anonymním objektem stdClass, přidávající možnost volat count() a používat hranaté závorky pro přístup k prvkům. Proč?

$obj = (object) array('a' => 1, 'b' => 2);
count($obj); // poněkud překvapivě vrací 1

echo $obj->$a; // ten dolar vypadá spíš jako bug...
echo $obj[$a]; // teď je jasné, že dolar je tam schválně

Vedlejším efektem pak je, že ArrayHash při přímém přístupu k prvkům funguje i tam, kde se očekává pole.

Problém ale vzniká u vícerozměrných struktur. Zatímco $a['b']['c'] = 'x' vytvoří vícerozměrné pole v poklidu, tak $a->b->c = 'x' vyhodí notice (v PHP 5.4 dokonce Warning). Pokud by $a byl ArrayHash, tak to vyhodí Notice: Indirect modification of overloaded a struktura se vůbec nevytvoří.

Z toho důvodu je vhodné používat anonymní objekty buď jako read-only nebo jako jednorozměrné struktury. Tohle se mi jevilo splněné v případě formulářů (1. případ) a databází (1. + 2. případ).

Původně i v případě $container->params, jenže tehdy jsem nepočítal s používáním vícerozměrných parametrů. Dnes bych u kontejnerů ArrayHash jednoznačně zrušil, bylo by to ovšem za cenu velkého BC breaku.

David Grudl
Nette Core | 8228
+
0
-

…a tak se i stalo https://github.com/…17f18f303ad2

Filip Procházka
Moderator | 4668
+
0
-

Ok, omlouvám se za tu ironii, pár věcí mě kapku dožralo po ránu.

Use-case: ve firmě máme formuláře více rozměrné (klidně i 3–4 zanoření) a není to chyba návrhu, prostě je to potřeba, je to vysoce komponentové. Máme potomky Forms\Container snad na všechno a skládáme to pak dohromady. Občas je potřeba tuhle něco sečíst, tuhle něco prohnat tímhle… a $form->values['neco'] + $form->values['neco2'] a další v takových případech odmítají fungovat po upgradu, což je dost velký BC break (respektive byl, hodně týdnů zpátky :).

V těch parametrech v Containeru a v Nette\Database to chápu, je to přecejenom něco „nového“ hodí se to víc a navíc to nebylo v žádných aplikacích už použito. Ale blbé je, že ty formuláře jsou v hodně aplikacích a počítají s poly. Teď otázka kolik lidí už přemigrovalo z 0.9 a pro koho to budou BC breaky (tipuju že hodně). V těch formulářích mi to dost vadí, všude dopisovat (array) a přetypovávat není pěkné.

Otázka je, co ty si o tom myslíš v těch formulářích. A jestli si myslíš, že má význam to dávat z formulářů pryč.

No a taky díky za příspěvek co mi neradil jak přetypovávat objekt, ale odpověděl mi na to, na co jsem se ptal :)

edit: Kontejner sem, kontejner tam. Já o formulářích ty o contextu :)) Trošku se ztrácím

Editoval HosipLan (30. 6. 2011 15:57)

David Grudl
Nette Core | 8228
+
0
-

HosipLan napsal(a):

edit: Kontejner sem, kontejner tam. Já o formulářích ty o contextu :)) Trošku se ztrácím

V prvním příspěvku o kontejnerech nepíšeš?

Filip Procházka
Moderator | 4668
+
0
-

Jo to taky :)