Nefunkční array_key_exists nad ArrayHash

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

Narazil jsem na zajímavou chybu (?) se kterou jsem se asi 30 minut pral. Pokud mám ArrayHash a chci se zeptat jestli tam je nějaký klíč, tak to vrátí vždy FALSE.

$test = [
    0 => 'Tohle',
    1 => 'je',
    2 => 'zoufalost'
];

dump(array_key_exists(1, $test)); // return TRUE
dump(array_key_exists(1, ArrayHash::from($test)));  // return FALSE
dump(array_key_exists(1, (array) ArrayHash::from($test)));  // return FALSE

Je to tak správně? Případně proč? A proč, když to přemapuju na pole, tak to stejně vrací FALSE? Díky.

Michal Hlávka
Člen | 190
+
0
-

Použíj isset() nebo metodu v ArrayHash offsetExists()

var_dump(ArrayHash::from($test)->offsetExists(1));

Editoval emptywall (1. 9. 2016 16:51)

CZechBoY
Člen | 3608
+
+1
-

Ty totiz nepretypujes objekt na pole ale vlozis objekt do pole jako jediny prvek.

Oli
Člen | 1215
+
0
-

CZechBoY napsal(a):

Ty totiz nepretypujes objekt na pole ale vlozis objekt do pole jako jediny prvek.

Pokud to je tak, tak potom Tracy to nevrací správně. Protože, když si to dumptu, tak to vrátí normálně pole. Správně by to teda mělo vrátit pole v poli, ne?

emptywall napsal(a):

Použíj isset() nebo metodu v ArrayHash offsetExists()

var_dump(ArrayHash::from($test)->offsetExists(1));

Je možný, že to někde napsaný je, jen o tom nevím, ale přišlo mě to právě zvláštní, protože to normálně můžeš iterovat ve foreach, můžeš k prvku přistoupit jako $test[1];, ale array_key_exists to nenajde :-)

Šlo o data z formuláře, takže jsem to nakonec vyřešil jednoduše (jak jsem zjistil v čem je problém). Prostě jsem si předal pole $form->getValues(TRUE);.

Díky, offsetExists jsem neznal.

artemevsin
Člen | 61
+
0
-

Celkem mě to zaujalo, tak jsem zkusil malý test a vypadá to, že array_key_exists nefunguje jen s číselným klíčem. Pokud je klíč stringem, tak to funguje správně. Platí však toto:

Additionally the following key casts will occur:

Strings containing valid integers will be cast to the integer type. E.g. the key „8“ will >actually be stored under 8. On the other hand „08“ will not be cast, as it isn't a valid >decimal integer.

Floats are also cast to integers, which means that the fractional part will be truncated. E.g. >the key 8.7 will actually be stored under 8.

Bools are cast to integers, too, i.e. the key true will actually be stored under 1 and the key >false under 0.

Null will be cast to the empty string, i.e. the key null will actually be stored under "".

Arrays and objects can not be used as keys. Doing so will result in a warning: Illegal offset >type.

<?php

		$test = [
            0 => 'Tohle',
            1 => 'je',
            'c' => 'zoufalost',
            '2' => 'velká'
        ];

        $objA = new ArrayHash();
        $objB = new \stdClass();
        foreach ($test as $key => $value) {
            $objA->$key = $value;
            $objB->$key = $value;
        }

        $resA1 = array_key_exists(0, $objA);  // return FALSE
        $resA2 = array_key_exists(1, $objA);  // return FALSE
        $resA3 = array_key_exists('c', $objA);  // return TRUE
        $resA4 = array_key_exists('2', $objA);  // return FALSE
        $resA5 = array_key_exists(2, $objA);  // return FALSE

        $resB1 = array_key_exists(0, $objB);  // return FALSE
        $resB2 = array_key_exists(1, $objB);  // return FALSE
        $resB3 = array_key_exists('c', $objB);  // return TRUE
        $resB4 = array_key_exists('2', $objB);  // return FALSE
        $resB5 = array_key_exists(2, $objB);  // return FALSE

        $resC1 = array_key_exists(0, ArrayHash::from($test));  // return FALSE
        $resC2 = array_key_exists(1, ArrayHash::from($test));  // return FALSE
        $resC3 = array_key_exists('c', ArrayHash::from($test));  // return TRUE
        $resC4 = array_key_exists('2', ArrayHash::from($test));  // return FALSE
        $resC5 = array_key_exists(2, ArrayHash::from($test));  // return FALSE

?>
David Grudl
Nette Core | 8239
+
+1
-

To je bohužel problém přímo v jádru PHP, pokud klíče pole obsahují čísla, je lepší se vyhnout přetypovávání na objekty, jako je stdClass nebo ArrayHash.