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í.

3. diel - Tipy pre začiatočníkov v PHP

Vitajte v 3. diele série Tipy pre začiatočníkov v PHP. Tento diel bude zameraný hlavne na prácu s dátami z databázy. Predovšetkým na to, čo sa robí zbytočne a čo ide urobiť lepšie s menšou záťažou servera. Príklady vyžadujú aspoň základná znalosť objektového ovládače PDO a využívajú databázu MySQL.

Vyhľadanie len potrebných dát

V SQL možné dáta vyhľadať dvoma spôsobmi - vymenovat jednotlivé stĺpce alebo napísať hviezdičku (tá vyhľadá všetky stĺpce z tabuľky). Použitie hviezdičky je síce veľmi jednoduché a nie je potreba moc písanie, avšak vo väčšine prípadov vyhľadá aj stĺpce, ktoré nakoniec vôbec nepotrebujete a nevyužijete ich.

Jednoduchý príklad

Máme tabuľku s užívateľmi, ktorá obsahuje stĺpce ID, prihlasovacie meno, meno, priezvisko, dátum narodenia a dátum registrácie. Chceme vyhľadať všetkých užívateľov a zobraziť ich meno, priezvisko a dátum registrácie.

Pri použití hviezdičky by sme napísali

$pdo->query("
  SELECT * FROM `user`
");

code

Avšak tento dotaz nám vyhľadá všetkých 6 stĺpcov, namiesto 3, ktoré chceme. Znamená to, že sa bude prenášať zbytočne viac dát. U veľmi malých databáz by to prakticky nemalo na výkon vplyv, ale predstavte si databázu, kde je registrovaných 10 tisíc ľudí a stránku s týmto dotazom by si otvorili treba 2 tisícky užívateľov v jeden okamih. Znamenalo by to, že by sa zbytočne prenášalo o 3 * 10k * 2k = 60M viac blokov dát (3 stĺpce navyše, 10.000 záznamov a 2000 užívateľov na stránke).

Prakticky by sme nevyhľadávali všetkých 10 tisíc záznamov, ale rôzne ich obmedzovali klauzulou LIMIT (napr. U stránkovanie). Avšak pre malý príklad toho, koľko zbytočných dát by sa prenieslo, to stačí.

Riešením je vymenovať v dotaze len tie stĺpce, ktoré naozaj potrebujeme.

$pdo->query("
  SELECT `nick`, `first_name`, `last_name`
  FROM `user`
");

code

Spätné apostrofy

Niekedy sa nám môže stať, že meno tabuľky alebo stĺpce bude kolidovať s kľúčovým slovom databázy. Napríklad keby sme mali stĺpec pomenovaný text alebo from, taký dotaz by bol zle:

$pdo->query("
  SELECT text, from
  FROM user
");

code

Musíme teda povedať databázu, aby názvy našich stĺpcov nebrala ako kľúčové slová. K tomu slúži spätnej apostrofy.

$pdo->query("
  SELECT `text`, `from`
  FROM `user`
");

code

Osobne odporúčam písať spätné apostrofy vždy, aj keď názvy nekolidujú. Minimálne sa tým vyhnete risku, že v novej verzii databázy pribudne nové kľúčové slovo, ktoré by kolidovať mohlo.

Manipulácia so záznamami

Databáza obsahujú hromadu funkcií, ktoré môžeme využiť na získanie presného formátu záznamov. Napríklad, ak by sme chceli spočítať hodnotu nejakého stĺpca všetkých záznamov, môžeme to urobiť na úrovni PHP.

$sum = 0;
$query = $pdo->query("
  SELECT `amount`
  FROM `table`
");
$rows = $query->fetchAll(PDO::FETCH_OBJ);

foreach ($rows as $row) {
  $sum += $row->amount;
}

echo $sum;  // zobrazení celkového součtu

code

V tomto prípade ale píšeme zbytočne viac kódu a zároveň zbytočne z databázy ťaháme hodnotu stĺpca a až potom pričítame. Databáza zvyčajne obsahuje funkciu, ktorá to rovno spočíta za nás a vráti nám už výsledok. V MySQL je pre to funkcia SUM ().

$query = $pdo->query("
  SELECT SUM(`amount`)
  FROM `table`
");
$sum = $query->fetchColumn();

echo $sum;  // zobrazení celkového součtu

code

Veľmi podobný prípad nastáva aj u samotného získavania počtu záznamov. Môžeme to riešiť na úrovni PHP, kde jednotlivo budeme v cykle pričítať. Ak ešte používate starý ovládač mysql_ *, mohli by ste napísať niečo takéto:

$query = mysql_query("
  SELECT `amount`
  FROM `table`
");
$rowsCount = mysql_num_rows($query);

echo $rowsCount;  // zobrazení počtu záznamů

code

Opäť zbytočne ťaháme dáta a riadky počítame až potom. Databáza však obsahuje funkciu COUNT (), ktorá riadky rovno spočíta.

$query = $pdo->query("
  SELECT COUNT(*)
  FROM `table`
");
$rowsCount = $query->fetchColumn();

echo $rowsCount;  // zobrazení počtu záznamů

code

Funkciu COUNT () môžeme odovzdať tiež názov určitého stĺpca. V takom prípade nám to spočíta záznamy, kde hodnota daného stĺpca nie je NULL.

Databáza takých funkcií obsahuje veľa. Je výhodnejšie tieto funkcie použiť už na úrovni databázového dopytu a nie až na úrovni PHP.

Získanie ID posledne vloženého záznamu

V určitých prípadoch chceme, aby sme po vloženie nového riadku do tabuľky získali jeho ID. Budeme mať tabuľku s dvomi stĺpci - ID a meno používateľa. Možno to urobiť zbytočne zložitým spôsobom:

// ze seznamu sloupců vynecháme ID, protože je nastaven jako AUTO_INCREMENT
// a databáze do něj hodnotu vloží automaticky
$pdo->query("
  INSERT INTO `user` (`nick`)
  VALUES ('jméno uživatele')
");

$query = $pdo->query("
  SELECT MAX(`id`)
  FROM `user`
");
$lastId = $query->fetchColumn();

code

Tento kód nám prvýkrát vloží nový záznam do tabuľky a následne pomocou funkcie MAX () vyberie to najvyššie číslo.

$query = $pdo->query("
  SELECT `id`
  FROM `user`
  ORDER BY `id` DESC
  LIMIT 1
");

$lastId = $query->fetchColumn();

code

Inak zapísané, ale urobí to to isté. Jednoducho vyberie hodnotu stĺpca ID, zoradia od najväčšieho a vyberie len to prvé (pomocou LIMIT).

Tieto otázky sú ale úplne zbytočné. Pre získanie posledne vloženého ID má PDO metódu lastInsertId ().

$pdo->query("
  INSERT INTO `user` (`nick`)
  VALUES ('jméno uživatele')
");
$lastId = $pdo->lastInsertId();

code

Prechádzanie záznamov

Na rozdiel napríklad od starého ovládača mysql_ *, vie PDO vracať záznamy tak, ako požadujeme. Ak chceme len jednu hodnotu, nemusíme sa k nej dostávať cez nejaké pole alebo naopak na získanie všetkých záznamov nemusíme postupne prechádzať riadok po riadku, ale PDO nám vráti rovno celý zoznam.

Metóda fetchAll ()

Ako z názvu vyplýva, metóda nám vráti všetky nájdené záznamy. Uloží ich do dvojrozmerného poľa v tvare:

array (
  0 => array(
     // první řádek
  ),

  1 => array(
     // druhý řádek atp.
  )
)

code

Vďaka tomu možno pole prejsť cyklom (zvyčajne sa používa foreach) a pracovať s jednotlivými záznamami.

$query = $pdo->query("
  SELECT `data`
  FROM `table`
");
$data = $query->fetchAll();

foreach ($data as $row) {
  // $row obsahuje sloupce z daného řádku
}

code

Ak sa nenašla žiadne dáta, výsledkom je prázdne pole.

Metóda fetch ()

Metóda fetch () vracia jednorozmerné pole podľa daného záznamu. Využije sa v prípade, že hľadáme jeden konkrétny záznam, napríklad informácie o užívateľovi.

$id = (int) $_GET["id"];

$query = $pdo->query("
  SELECT `first_name`, `last_name`
  FROM `user`
  WHERE `id` = {$id}
  LIMIT 1
");
$data = $query->fetch(PDO::FETCH_OBJ);

echo $data->first_name;  // vypsání jména daného uživatele

code

Ak sa nenájde žiadny vyhovujúci riadok, metóda vráti FALSE. Možno to veľmi ľahko použiť pre zistenie, či sa riadok našiel alebo nie. Využiť sa to dá napríklad pri prihlasovaní užívateľov.

$query = $pdo->query("
  SELECT `id`
  FROM `user`
  WHERE `nick` = 'nějaké jméno' AND `password` = 'nějaké heslo'
  LIMIT 1
");
$data = $query->fetch(PDO::FETCH_OBJ);
if ($data !== FALSE) {
  $_SESSION["userId"] = $data->id;
  // atd.

} else {
  echo "Je nám líto, uživatel s takovým jménem nebo heslem neexistuje.";
}

code

Metóda fetchColumn ()

Táto metóda nám vracia hodnotu jedného určitého stĺpca v jednom zázname. Často sa používa napríklad pri počítaní záznamov.

$query = $pdo->query("
  SELECT COUNT(*)
  FROM `user`
");
$usersCount = $query->fetchColumn();  // proměnná obsahuje počet všech uživatelů

code

Ak sa nenájde žiadna hodnota, metóda vráti FALSE.

Formát výstupných dát

Táto časť úzko súvisí s tou predchádzajúcou. Okrem jednotlivého zoskupenia dát môžeme určiť v akom formáte sa nám vráti. Môžeme dáta napríklad uložiť len do asociatívneho poľa alebo napríklad do objektu.

$id = (int) $_GET["id"];

$query = $pdo->query("
  SELECT `first_name`, `last_name`, `email`
  FROM `user`
  WHERE `id` = {$id}
  LIMIT 1
");

// nejčastěji používané
$data = $query->fetch(PDO::FETCH_BOTH);   // vrátí jak indexované, tak asociativní pole (defaultně)
$data = $query->fetch(PDO::FETCH_NUM);    // vrátí pouze indexované pole
$data = $query->fetch(PDO::FETCH_ASSOC);  // vrátí pouze asociativní pole
$data = $query->fetch(PDO::FETCH_OBJ);    // vrátí objekt třídy stdClass

code

Uviedol som len najpoužívanejšie štýly, existuje ich viac (viď php.net).

Unikátny hodnoty

Ak chceme mať v tabuľke len unikátnej hodnoty, nie je potrebné sa vopred pýtať, či tam už daná hodnota. Často je k videniu taký kód:

// budeme předpokládat, že proměnná $name neobsahuje nebezpečné znaky

$query = $pdo->query("
  SELECT 1 FROM `user`
  WHERE `name` = '{$name}'
  LIMIT 1
");
$exists = $query->fetchColumn();

if (!$exists) {
  // zaregistrování nového uživatele
}

code

Ak nejaký záznam existuje, vráti sa 1, inak nám PDO vráti FALSE.

Môžeme ale využiť unikátneho kľúča priamo v tabuľke. Stačí danému stĺpci pridať "unikátny kľúč (unique key)" a nemôže sa nám stať, že by sme vložili rovnaký záznam. Ak sa o to pokúsime, vráti databázy chybu. Tú PDO reprezentuje podľa nastavenia. Najčastejším nastavením je, že sa pri chybe vyhodí výnimka.

try {
  $pdo->query("
     INSERT INTO `user` (`nick`)
     VALUES ('nějaké jméno')
  ");
} catch (PDOException $e) {
  echo "Uživatel s tímto jménem již existuje.";
}

code

Tak a tretí diel je za nami. Ďakujem za prečítanie a ak bude záujem, rád sa pokúsim spísať ďalšie tipy, ktoré by mohli pomôcť ako začínajúcim, tak určite aj mierne pokročilým vývojárom.


 

Predchádzajúci článok
Tipy pre začiatočníkov v PHP
Všetky články v sekcii
Tipy pre začiatočníkov v PHP
Článok pre vás napísal Martin Konečný (pavelco1998)
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se o IT moc nezajímá, raději by se věnoval speciálním jednotkám jako jsou SEALs nebo SAS. Když už to ale musí být něco z IT, tak tvorba web. aplikací v PHP. Také vyvýjí novou českou prohlížečovou RPG hru a provozuje osobní web http://www.mkonecny.cz
Aktivity