Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 6 - Knihovna ArrayUtils pro práci s poli v PHP

V předešlém cvičení, Řešené úlohy k 4.-5. lekci knihovny v PHP, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

Důležitou datovou strukturou v PHP jsou pole. Asi vás nepřekvapí, že i pro pole 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' => '[email protected]',
);
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): array
{
    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í funkce array_flip() získáme pole, které má jako klíče ty klíče, které chceme ponechat. Pomocí funkce array_intersect_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 pole $_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(string $prefix, array $input): array
{
    $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] => [email protected]
        )

    [1] => Array
        (
            [uzivatel_id] => 2
            [jmeno] => Jana Nováková
            [email] => [email protected]
        )

    [2] => Array
        (
            [uzivatel_id] => 3
            [jmeno] => Josef Nový
            [email] => [email protected]
        )
)

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, string $keyKey, string $valueKey): array
{
    $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 dva 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] => [email protected]
    [1] => [email protected]
    [2] => [email protected]
)

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

public static function mapSingles(array $rows, array $singleKey): array
{
    $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í lekci, Dokončení knihovny ArrayUtils v PHP, se zaměříme na práci s prefixy, konverzi notací a převod pole do XML a naopak.


 

Předchozí článek
Řešené úlohy k 4.-5. lekci knihovny v PHP
Všechny články v sekci
Knihovny pro PHP
Přeskočit článek
(nedoporučujeme)
Dokončení knihovny ArrayUtils v PHP
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
10 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity