6. díl - Knihovna ArrayUtils pro práci s poli v PHP

PHP Knihovny Knihovna ArrayUtils pro práci s poli v PHP American English version English version

V minulém dílu našeho seriálu tutoriálů o tvorbě knihoven pro PHP jsme dokončili knihovnu StringUtils, která poskytovala pomocné metody pro práci s textovými řetězci. Další důležitou datovou strukturou v PHP jsou kromě řetězců pole. Asi vás nepřekvapí, že i pro ně se najde několik užitečných funkcí, které si dnes zabalíme do třídy ArrayUtils.

ArrayUtils

Nejprve si založíme naši třídu:

class ArrayUtils
{
}

Filtrování pole podle klíčů

Často se nám stává, že potřebujeme profiltrovat pole tak, aby obsahovalo jen některé klíče. Pokud používáte místní databázový wrapper nad PDO, jistě víte, že pomocí něj můžeme např. jednoduše vložit nový řádek do tabulky "uzivatel" tímto způsobem:

$uzivatel = array(
        'jmeno' => 'Jan',
        'prijmeni' => 'Novak',
        'email' => 'jan@novak.cz',
);
Db::insert('uzivatel', $uzivatel);

Kód výše by se mohl využít např. pro nějakou registraci. Pokud předáme data z formuláře, bude sice fungovat, ale vystavujeme se nebezpečnému riziku a to sice, že uživatel si může nějaká formulářová pole přidat a ta se poté vloží do dotazu (např. "admin" = 1):

// Tento kód není bezpečný
Db::insert('uzivatel', $_POST);

Hodilo by se nám pole $_POST profiltrovat tak, aby obsahovalo jen určitý výčet klíčů. Uvedený postup se samozřejmě neváže jen na pole $_POST, ale využijeme ho i v dalších případech.

Do třídy přidáme následující metodu:

public static function filterKeys(array $input, array $keys)
{
        return array_intersect_key($input, array_flip($keys));
}

Metoda filterKeys() přijímá v argumentech vstupní pole a dále pole klíčů, které chceme ponechat. Co se týče kódu, pomocí array_flip() získáme pole, které má jako klíče ty klíče, které chceme ponechat. Pomocí array_intersec­t_key() následně provedeme průnik klíčů dvou polí a vrátíme výsledek.

Ukažme si využití v původním příkladu, kde zabezpečíme získání dat z $_POST:

$klice = array('jmeno', 'prijmeni', 'email');
Db::insert('uzivatel', ArrayUtils::filterKeys($_POST, $klice));

Když je klíčů více, je výhodné dát jim nějaký prefix (předponu) a filtrovat podle něj.

public static function filterKeysPrefix($prefix, array $input)
{
        $output = array();
        foreach ($input as $key => $value)
        {
                if (mb_strpos($key, $prefix) === 0)
                        $output[$key] = $value;
        }
        return $output;
}

Funkce filterKeysPrefix() přijímá prefix a vstupní pole. Ve výsledném poli zůstanou jen ty klíče, které začínají řetězcem $prefix. Kód by měl být srozumitelný.

Mapování párů klíč-hodnota a hodnot

Když vybíráme data z databáze, přijdou nám vždy jako pole polí, např. takto:

Array
(
    [0] => Array
        (
            [uzivatel_id] => 1
            [jmeno] => Jan Novák
            [email] => jan@novak.cz
        )

    [1] => Array
        (
            [uzivatel_id] => 2
            [jmeno] => Jana Nováková
            [email] => jana@novakova.cz
        )

    [2] => Array
        (
            [uzivatel_id] => 3
            [jmeno] => Josef Nový
            [email] => josef@novy.cz
        )
)

Mapování párů

Nyní si představte, že budeme v aplikaci chtít přidat formulář s výběrem uživatele pomocí HTML selectu (popisek bude jméno uživatele a hodnota odesílaná na server bude jeho ID). Pokud pro to použijeme nějaký formulářový framework, je velmi pravděpodobné, že bude chtít data ve formátu klíč-hodnota:

Array
(
    [Jan Novák] => 1
    [Jana Nováková] => 2
    [Josef Nový] => 3
)

Pro mapování výsledku databázového dotazu na takovéto asociativní pole přidejme do naší třídy metodu mapPairs():

public static function mapPairs(array $rows, $keyKey, $valueKey)
{
        $pairs = array();
        foreach ($rows as $row)
        {
                $key = $row[$keyKey];
                // Kontrola kolizí klíče
                if (isset($pairs[$key]))
                {
                        $i = 1;
                        while (isset($pairs[$key . ' (' . $i . ')']))
                        {
                                $i++;
                        }
                        $key .= ' (' . $i . ')';
                }
                $pairs[$key] = $row[$valueKey];
        }
        return $pairs;
}

Metodě předáme pole a poté 2 názvy klíčů. První klíč se stane ve výsledném poli klíčem a druhý hodnotou.

Výše zmíněné pole tedy získáme tímto způsobem:

$uzivatele = Db::queryAll('SELECT jmeno, uzivatel_id FROM uzivatel');
$polozky = ArrayUtils::mapPairs($uzivatele, 'jmeno', 'uzivatel_id');

Všimněte si, že metoda řeší i případ, když se 2 uživatelé jmenují stejně. V takovém případě začne položky číslovat.

Mapování hodnot

Podobně budeme občas potřebovat získat pole nějakých hodnot, např. emailů všech uživatelů, kterým pošleme newsletter. Budeme chtít získat následující pole:

Array
(
    [0] => jan@novak.cz
    [1] => jana@novakova.cz
    [2] => josef@novy.cz
)

Metoda mapSingles() není nijak složitá:

public static function mapSingles(array $rows, $singleKey)
{
        $singles = array();
        foreach ($rows as $row)
        {
                $singles[] = $row[$singleKey];
        }
        return $singles;
}

A použití:

$emaily = ArrayUtils::mapSingles(Db::queryAll('SELECT email FROM uzivatel'), 'email');

V příštím dílu se zaměříme na práci s prefixy, konverzi notací a převod pole do XML a naopak. Knihovnu tím dokončíme.


 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (4 hlasů) :
4.754.754.754.754.75


 


Miniatura
Všechny články v sekci
Knihovny pro PHP
Miniatura
Následující článek
Dokončení knihovny ArrayUtils v PHP

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!