ArrayHash a integer klice

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

Nevím, jestli tohle brát jako chybu. Kam to vůbec napsat…

ArrayHash mi celkem zkomplikoval život, než jsem na to přišel.
Měl jsem dynamické položky ve formuláři, tzn. název (klíč) form. prvku bylo číslo.
Ale přetypování ArrayHash na pole vytvoří něco, co normálně v PHP neuděláte. Číselné klíče, jsou string!!!

Nejlépe to předvést na ukázce:

<?php
$a = new Nette\ArrayHash;
$a['0'] = 'a';
$a[1] = 'b';
$a = (array) $a;
var_dump($a); // array(2) { ["0"]=> string(1) "a" ["1"]=> string(1) "b" }
unset($a['0']);
unset($a[1]);
var_dump($a); // array(2) { ["0"]=> string(1) "a" ["1"]=> string(1) "b" }

$a = array();
$a['0'] = 'a';
$a[1] = 'b';
var_dump($a); // array(2) { [0]=> string(1) "a" [1]=> string(1) "b" }
unset($a['0']);
unset($a[1]);
var_dump($a); // array(0) { }


// problem je jasny
$a = array();
$a[] = 'a';
var_dump($a); // array(1) { [0]=> string(1) "a" }
$a = Nette\ArrayHash::from($a);
$a = (array) $a;
var_dump($a); // array(1) { ["0"]=> string(1) "a" }


// a takto se v podstate tvori formularove 'getValues'
$a = new Nette\ArrayHash;
$key = 0;
$a->$key = 'a';
$a = (array) $a;
var_dump($a); // array(1) { ["0"]=> string(1) "a" }
Filip Procházka
Moderator | 4668
+
0
-

Souhlasím, po půl roce pořád nechápu přidanou hodnotu ArrayHash. Nebudu rejpat do Davida, to už jsem zkoušel a stejně to furt nevím :)

Takže jak to řešit?

  • nespoléhat se na indexy (ignorovat je)
  • zbavit se potřeby unsetovat hodnoty (tohle je fakt úchylnost. Že se to snažíš pak vkládat do db?)
  • přetypovávat na pole (asi nejlepší co můžeš udělat…)
  • používat foreach (tomu je jedno, že je to objekt)
mkoubik
Člen | 728
+
0
-

Další problém je s typehintingem parametrů, dá se to udělat tak, aby prošlo jak pole, tak ArrayHash? Zkoušel jsem ArrayAccess, ale co čert nechtěl, pole neimplementuje ArrayAccess (resp. vůbec to není objekt).

David Grudl
Nette Core | 8228
+
0
-

Přidal jsem do metodě getValues() parameter $asArray, když bude TRUE vrátí se normální pole.

Ascaria
Člen | 187
+
0
-

Já jsem narazil ještě na jednu záludnost. Pokud ArrayHash z formuláře uložím do session:

<?php
$this->sessionSection = $this->presenter->context->session->getSection('certification-request-form');
$this->sessionSection->values = $form->getValues();
?>

A poté po redirectu na další stránce se snažím z té session data tahat ven:

<?php
$this->sessionSection = $this->presenter->context->session->getSection('certification-request-form');

// V $this->sessionSection->values je nyní vše ArrayHash
$class = 1;

// selže
$requirements = $this->sessionSection->values['main']['stars'][$class];

// provede se a $requirements je stále ArrayHash
$stars = (Array)$this->sessionSection->values['main']['stars'];
$requirements = $stars[$class];
?>

Problémové inputy mají name napriklad:
main[stars][1][pozadavek1]
main[stars][1][pozadavek2]

main[stars][2][pozadavek3]
main[stars][2][pozadavek4]

a když chci iterovat „foreach(main[stars][1] as pozadavek)“ tak mám smůlu, musím nejdřiv „main[stars]“ přetypovat na pole a pak iterovat nad „foreach(pole[1] as pozadavek)“. Obejít by to šlo přidáním písmena před číslo v indexu, ale na to už je pozdě.

Editoval Ascaria (21. 3. 2012 15:27)

David Grudl
Nette Core | 8228
+
0
-

Tohle je opraveno v PHP 5.3.9 a 5.4 https://bugs.php.net/bug.php?…. Jak to opravit na straně PHP netuším.