Vložení prvku do pole

Řekněme, že máme nějaké asociativní pole, do kterého chceme vložit další prvek. Např. pole s povinnými položkami při registraci, do kterého chceme za určitých okolností přidat další prvky. Pokud chceme prvky přidat na konec, je to jednoduché:

<?php
$povinne = array("login" => "Login", "psc" => "PSČ");
if ($uplna_registrace) {
    $povinne["email"] = "E-mail";
}
?>

Horší je to v případě, kdy prvek chceme vložit doprostřed pole. Ideálně by se k tomu hodila funkce array_splice, ta ale nezachovává názvy klíčů. Můžeme použít funkci array_slice, řešení je ale krkolomné:

<?php
if ($uplna_registrace) {
    $povinne = array_slice($povinne, 0, 1, true) + array("email" => "E-mail") + array_slice($povinne, 1, null, true);
}
?>

Trik, který se dá v tomto případě použít, spočívá ve vytvoření kompletního pole už při inicializaci a odnastavení nadbytečných prvků, když nejsou potřeba:

<?php
$povinne = array("login" => "Login", "email" => "E-mail", "psc" => "PSČ");
if (!$uplna_registrace) {
    unset($povinne["email"]);
}
?>
Jakub Vrána, Řešení problému, 5.1.2009, on-line

Diskuse

Andrew:

Dík za príma postřeh, ale trošku to nesouvisí s nadpisem článku. Takže skončím opět u array_slice. Předpoklad definice pole dopředu je opravdu jen pro značně omezenou množinu (například ho nepoužiji při získání dat z db a následném rozšíření struktury).
5.1.2009 05:07:43

Peter Listiak:

Nejako tomu nerozumiem. Naco je dobre pridavat prvky niekam "do stredu" asociativneho pola. Nestaci, ked sa to prida nakoniec? Ved stale k tomu pristupujem cez kluc.
5.1.2009 06:41:40

ikona Jakub Vrána:

Pole můžu chtít následně i procházet, potom je pořadí prvků důležité.
5.1.2009 06:42:55

ikona david@grudl.com:

Příkladem použití je třeba pole atributů HTML elementu (http://phpfashion.com/nette-web-html-pomocnik-php-programatora). Vytvořím si objekt představující element a postupně mu dosadím (v libovolném pořadí) jednotlivé atributy do asociativního pole. Renderování pak spočívá ve vypsání jeho názvu a všech atributů s nenulovou (!== NULL) hodnotou, k procházení se použije právě foreach.

Konkrétně u elementu IMG by bylo šikovné, aby atribut SRC byl vždy uveden jako první a dále aby HEIGHT následoval po WIDTH. Což lze řešit buď poměrně krkolomným přesunem klíčů v poli, nebo tak, že už při vytvoření elementu IMG nastavím do pole atributů hodnotu array('src'=>NULL, 'width'=>NULL, 'height'=>NULL)
5.1.2009 07:19:29

JimX:

Můžu se zeptati, jestli to pořadí SRC, WIDTH, HEIGHT má nějaký reálný význam, nebo to tak prostě jenom chcete :)
5.1.2009 12:34:53

ikona david@grudl.com:

Jen tak. Pro ty, co preferují CoolTAGs ;)
7.1.2009 04:43:42

ivan_d:

No nevím, asociativní pole a pořadí mi stále nesedí. Ten popsaný úkol lze splnit prostřednictvím pomocného obyčejného pole s klíči - to určí pořadí:

$order = array('src', 'width', 'height');
foreach($order as $key){
  if(!is_null($settings[$key])){
    ...
  }
}
5.1.2009 22:56:53

Peter Listiak:

Ale prave pri atributoch HTML elementu mi na poradi nezalezi (ak sa teda nebavime o estetike) a teda toto robit nemusim. Ale uznavam, ze niekedy sa mozu objavit pripady kedy na poradi zalezi.
7.1.2009 01:33:18

ikona Jakub Vrána:

Je žádoucí, aby si prohlížeč načetl nejdřív URL obrázku, aby ho hned mohl začít stahovat, a potom rozměry, aby věděl, kolik pro něj má vyhradit místa. Většinou se celá značka přenese najednou, tak na tom nezáleží, ale někdy může být uprostřed značky konec paketu, tak se rozdíl projeví.

Otázkou ale je, jestli prohlížeče značku vůbec zpracovávají předtím, než ji celou načtou.
7.1.2009 04:39:47

ikona david@grudl.com:

To sem nemůžeš takhle napsat, vem si kolik lidí teď bude po nocích překopávat své weby :-)
7.1.2009 04:45:00

Radek:

Myslím si, že to je milná informace. Mám docela pomalé připojení k netu tak si myslím, že je žádoucí mít nejdřív height a width a až potom adresu obrázku. Prohlížeč si při načítání vyhradí místo pro obrázek a pokračuje dál ve formátování stránky. Pokud nejsou rozměry dány, nikomu nepřeju vidět jak se to celé hýbe podle toho kolik je z obrázku načteno.
11.1.2009 01:34:58

ikona Joelp:

Nechci někomu brát iluze, jak funguje prohlížeč, ale například Firefox mi nejdříve stáhne všechny soubory text/html a až následně stahuje obrázky. Takže pozice atributů je absolutně nepodstatná (co se týče rychlosti).
12.1.2009 03:07:03

ikona Jakub Vrána:

Mě tedy ne. Firefox 3.0.5 pod Windows v následujícím kódu stáhne dřív obrázek než zbytek HTML:

<img src="jakub.jpg" alt="" />
<?php
ob_flush
();
flush();
sleep(10);
?>

A neřekl bych, že je to nějaká anomálie, spíš jsi provedl špatný úsudek.

Značku nicméně zpracuje až po jejím celém načtení, což se dá potvrdit přesunutím sleep() dovnitř značky.
12.1.2009 03:14:17

ikona Joelp:

Použil jsem wireshark a ten mi jasně ukázal že se mi (linux) nejdřív stáhne HTML a až následně obrázek.
14.1.2009 05:04:12

ikona Jakub Vrána:

Tak si ten kód vyzkoušej. Obrázek je jednoduše vidět ještě před nahráním celé stránky. Bez sleep() je možné i to, že se rychleji stihne dotáhnout HTML než se začne stahovat obrázek, obecně to ale neplatí.
14.1.2009 05:09:57

ikona Joelp:

Tak jsem to vyzkoušel a nemůžu potvrdit tvoje tvrzení.
Wireshark mi píše:

AAAA joelp.wz.cz
Standard query response A 88.86.113.136
SYN
SYN, ACK
ACK
GET /test/ HTTP/1.1  (obsahuje komplet HTML)
ACK
HTTP/1.1 200 OK (text/html)
ACK
GET /test/moto_0376.jpg HTTP/1.1

Příklad je zde: http://joelp.wz.cz/test/
14.1.2009 08:00:32

ikona Jakub Vrána:

Samotný sleep() nestačí - data se do prohlížeče posílají až když se to vyplatí. V mém příkladu není ob_flush() a flush() pro nic za nic. Vyzkoušej ten příklad ode mě a pak se vrať.
14.1.2009 08:04:37

ikona Joelp:

Zdá se, že to velmi závisí na nastavení serveru. Ve výše uvedeném testu se to chová stále stejně i s použitím ob_flush(); a flush();. Když jsem to pak zkoušel na lokálu, tak se to chovalo přesně podle Tebe.
15.1.2009 02:06:19

Michal:

Výborný tip, díky za něj. Dřív jsem byl zvyklý hledat řešení svých problémů v diskuzích na php.net (např. na stránkách s funkcemi). Teď chodím první sem :-)
5.1.2009 08:14:29

Qwerty:

a co když chci přidat prvek do pole třeba takového a nevím kolik má prvků?

$a = array(2, 3, 4);
26.1.2010 22:39:57
avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.