IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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 7 - Dokončení knihovny ArrayUtils v PHP

V minulé lekci, Knihovna ArrayUtils pro práci s poli v PHP, jsme rozepsali knihovnu ArrayUtils pro práci s poli v PHP.

Dnes do knihovny ArrayUtils přidáme práci s prefixy, konverzi notací a ukážeme si převod pole do XML a naopak.

Přidání a odstranění prefixu klíčů

O prefixech jsme se již krátce zmínili. Představme si vložení adresy z formuláře do databáze. Názvy formulářových polí budou samozřejmě opět korespondovat s názvy sloupců v tabulce:

<!-- ... -->
<label>Ulice:<br/>
    <input type="text" name="ulice"/>
</label><br/>
<label>Č. popisné:<br/>
    <input type="text" name="cislo_popisne"/>
</label><br/>
<label>Č. orientační:<br/>
    <input type="text" name="cislo_orientacni"/>
</label><br/>
<label>
    Město:<br/>
    <input type="text" name="mesto"/>
</label><br/>
<label>PSČ:<br/>
    <input type="text" name="psc"/>
</label><br/>
<!-- ... -->

Formulář zpracujeme zkráceně takto:

$kliceAdresa = array('ulice', 'cislo_popisne', 'cislo_orientacni', 'mesto', 'psc');
$adresa = ArrayUtils::filterKeys($_POST, $kliceAdresa);
Db::insert('adresa', $adresa);

Databázový wrapper (třída Db) je dostupná z kurzu PHP databáze.

Složitější formulář

Občas data ale dorazí z nějakého složitějšího formuláře, ve kterém máme např. 2 adresy - fakturační a dodací. Aby se nám kontrolky nepletly, předsadíme dodací adresu prefixem dodaci_. Formulář by vypadal např. takto:

<!-- ... -->
<h2>Fakturační adresa</h2>
<label>Ulice:<br/>
    <input type="text" name="ulice"/>
</label><br/>
<label>Č. popisné:<br/>
    <input type="text" name="cislo_popisne"/>
</label><br/>
<label>Č. orientační:<br/>
    <input type="text" name="cislo_orientacni"/>
</label><br/>
<label>
    Město:<br/>
    <input type="text" name="mesto"/>
</label><br/>
<label>PSČ:<br/>
    <input type="text" name="psc"/>
</label><br/>
<!-- ... -->
<h2>Dodací adresa</h2>
<label>Ulice:<br/>
    <input type="text" name="dodaci_ulice"/>
</label><br/>
<label>Č. popisné:<br/>
    <input type="text" name="dodaci_cislo_popisne"/>
</label><br/>
<label>Č. orientační:<br/>
    <input type="text" name="dodaci_cislo_orientacni"/>
</label><br/>
<label>Město:<br/>
    <input type="text" name="dodaci_mesto"/>
</label><br/>
<label>PSČ:<br/>
    <input type="text" name="dodaci_psc"/>
</label><br/>
<input type="submit">
<!-- ... -->

PHP část

V PHP budeme chtít z pole $_POST vytáhnout část bez prefixů a část s prefixy, u té poté prefixy odstranit a uložit obě adresy do tabulky adresa. Kód bude vypadat takto:

$kliceAdresa = array('ulice', 'cislo_popisne', 'cislo_orientacni', 'mesto', 'psc');
$fakturacniAdresa = ArrayUtils::filterKeys($_POST, $kliceAdresa);
// Získání jen polí s prefixem
$dodaciAdresa = ArrayUtils::filterKeysPrefix('dodaci_', $_POST);
// Odstranění prefixu
$dodaciAdresa = ArrayUtils::removePrefix('dodaci_', $dodaciAdresa);
// Filtrování
$dodaciAdresa = ArrayUtils::filterKeys($dodaciAdresa, $kliceAdresa);
// Vložení adres do databáze
Db::insert('adresa', $fakturacniAdresa);
Db::insert('adresa', $dodaciAdresa);

Uveďme si kód metod addPrefix() a removePrefix(). Všimněte si, že jsou napsané tak, aby fungovaly i rekurzivně:

public static function addPrefix(string $prefix, array $input): array
{
    $output = array();
    foreach ($input as $key => $value) {
        $key = $prefix . $key;
        if (is_array($value))
            $value = self::addPrefix($prefix, $value);
        $output[$key] = $value;
    }
    return $output;
}

public static function removePrefix(string $prefix, array $input): array
{
    $output = array();
    foreach ($input as $key => $value) {
        if (strpos($key, $prefix) === 0)
            $key = substr($key, mb_strlen($prefix));
        if (is_array($value))
            $value = self::removePrefix($prefix, $value);
        $output[$key] = $value;
    }
    return $output;
}

Metoda addPrefix() rekurzivně přidá prefixy klíčům v poli, druhá metoda removePrefix() dělá opak, tedy rekurzivně odstraní prefixy klíčů v poli.

Změna velbloudí notace na podtržítkovou a naopak

V MySQL databázi je zvykem pojmenovávat tabulky podtržítkovou notací (snake_case). Jednak se vyhneme problémům s velkými/malými písmeny na linuxových serverech a také nám např. nástroj PhpMyAdmin seskupuje tabulky podle dvou podtržítek, např. uzivatel__adresa, uzivatel__bankovni_ucet a podobně. V PHP ovšem používáme spíše velbloudíNotaci (CamelCase s velkým prvním písmenem, jinak je správný název PascalCase). Někdy je užitečné převést klíče pole z jedné notace na druhou. A právě to dělají dvě níže uvedené metody. K samotnému převodu je použita knihovna StringUtils, kterou jsme dokončili minule:

public static function camelToSnake(array $inputArray): array
{
    $outputArray = array();
    foreach ($inputArray as $key => $value) {
        $key = StringUtils::camelToSnake($key);
        if (is_array($value))
            $value = self::camelToSnake($value);
        $outputArray[$key] = $value;
    }
    return $outputArray;
}

public static function snakeToCamel(array $inputArray): array
{
    $outputArray = array();
    foreach ($inputArray as $key => $value) {
        $key = StringUtils::snakeToCamel($key);
        if (is_array($value))
            $value = self::snakeToCamel($value);
        $outputArray[$key] = $value;
    }
    return $outputArray;
}

Převod do XML

Při spolupráci s externími systémy často pracujeme s formáty JSON nebo XML. Oba tyto formáty je výhodné generovat z pole, přičemž pro generování pole do JSON a z JSON PHP obsahuje skvělé funkce. Generování pole do XML bohužel chybí a proto si za účelem této i zpětné konverze přidáme metody. Uveďme si nejprve kód metody xmlEncode():

public static function xmlEncode(array $input, string $root): string
{
    $doc = new DOMDocument('1.0', 'UTF-8');
    $doc->formatOutput = true;

    $rootElement = $doc->createElement($root);
    $doc->appendChild($rootElement);
    self::xmlEncodeElement($input, $rootElement);

    return $doc->saveXML();
}

private static function xmlEncodeElement(array $input, DOMElement $parent): void
{
    foreach ($input as $key => $value) {
        $element = $parent->ownerDocument->createElement($key);
        $parent->appendChild($element);
        if (is_array($value))
            self::xmlEncodeElement($value, $element);
        else {
            $text = $parent->ownerDocument->createTextNode($value);
            $element->appendChild($text);
        }
    }
}

Metoda přijímá vstupní pole a název kořenového XML elementu. Následně vytvoří nový dokument a přidá do něj kořenový element. Dále spustí privátní metodu xmlEncodeElement(). Ta přijímá pole a element, do kterého má prvky z pole přivěsit. Druhou metodu jsme vytvořili kvůli usnadnění rekurze, budeme chtít, aby bylo možné zanořit pole do sebe. Pro každý klíč pole zde vytvoříme element a do toho buď vložíme rovnou text nebo zavoláme metodu rekurzivně znovu pro případ, že je vkládanou hodnotu opět pole.

Metodu můžeme vyzkoušet:

$uzivatele = array(
    'administrator' => array(
        'uzivatel_id' => 1,
        'jmeno' => 'Jan Novák',
        'email' => '[email protected]',
    ),
    'redaktor' => array(
        'uzivatel_id' => 2,
        'jmeno' => 'Jana Nováková',
        'email' => '[email protected]',
    ),
);
echo(ArrayUtils::xmlEncode($uzivatele, 'uzivatele'));

A výsledné XML:

<?xml version="1.0" encoding="UTF-8"?>
<uzivatele>
  <administrator>
    <uzivatel_id>1</uzivatel_id>
    <jmeno>Jan Novák</jmeno>
    <email>[email protected]</email>
  </administrator>
  <redaktor>
    <uzivatel_id>2</uzivatel_id>
    <jmeno>Jana Nováková</jmeno>
    <email>[email protected]</email>
  </redaktor>
</uzivatele>

Pokud chceme, aby se nám v prohlížeči zobrazilo XML správně, musíme nastavit před jakýkoliv výpisem hlavičku header('Content-type: text/xml').

Při tvorbě XML z pole jsme samozřejmě limitovaní tím, že každý klíč může být v poli jen jednou. Některá XML tedy polem nevytvoříme, ale jindy nám ušetří spoustu práce.

Pro úplnost dodejme i zpětnou konverzi. Tentokrát využijeme malého hacku, a to že funkce json_encode() dokáže přijímat objekt typu SimpleXMLElement. Výsledný JSON poté převedeme na pole pomocí funkce json_decode():

public static function xmlDecode(string $xml): array
{
    $simpleXMLElement = simplexml_load_string($xml);
    $json = json_encode($simpleXMLElement);
    return json_decode($json, true);
}

A máme hotovo :) Kompletní a zdokumentovanou třídu naleznete jako vždy ke stažení níže.

V příští lekci, Knihovna Image pro práci s obrázky v PHP, začneme pracovat na knihovně pro práci s obrázky.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 326x (3.38 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
Knihovna ArrayUtils pro práci s poli v PHP
Všechny články v sekci
Knihovny pro PHP
Přeskočit článek
(nedoporučujeme)
Knihovna Image pro práci s obrázky v PHP
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
12 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