Psst. EU dotace 85 % pro OSVČ a firmy lze nyní čerpat i na e-learning. Více informací
Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij halloweenské akce 80% výuky zdarma!
Python týden

Lekce 5 - Práca s MySQL v PHP - PDO objektovo a modulárne

V predchádzajúcom článku http://www.itnetwork.cz/...ovladace-pdo som napísal, že by bolo vhodné oddeliť prácu s databázou do samostatnej triedy, aby sme s ňou mohli pracovať na viacerých miestach - nielen v triede Adresar a nemuseli ju zakaždým znova otvárať. Otváranie databázy je totiž časovo náročná operácia. Preto ju v aplikácii otvoríme len raz a použijeme všade, kde sa nám bude hodiť.

Tentokrát už bude meno triedy mydb na mieste. Vytvoril som vlastné jednoduchú nadstavbu databázy.

<?php
// soubor MyDB.class.php

class MyDB{
  private $spojeni;

  function __construct($host,$user,$pass,$name){
    $options=array(
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
      );
    $this->spojeni= @new PDO("mysql:host=$host;dbname=$name",$user,$pass,$options);
  }

  function query($query,$param=Array()){
      $navrat=$this->spojeni->prepare($query);
      $navrat->execute($param);
      return $navrat->rowCount();
  }

  function queryOne($query,$param=Array()){
      $navrat=$this->spojeni->prepare($query);
      $navrat->execute($param);
      return $navrat->fetch(PDO::FETCH_ASSOC);
  }

  function queryAll($query,$param=Array()){
      $navrat=$this->spojeni->prepare($query);
      $navrat->execute($param);
      return $navrat->fetchAll(PDO::FETCH_ASSOC);
  }
}

Ako je vidieť, okrem otvorenia databázy som si vyrobil 3 metódy:

  • query(), ktorá vracia len počet ovplyvnených riadkov v DB
  • queryOne(), ktorá vracia prvý záznam, na ktorý narazí
  • queryAll(), ktorá vracia kompletné výsledok dotazu
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

V mojej aplikácii síce budem potrebovať len jednu z nich, ale tie zvyšné sa nám iste budú hodiť v niektorom z ďalších pokračovaní tohto seriálu. Ak by niekomu nejaká metóda chýbala, môže si ju dopísať. Chýba tu napríklad iterátor pre vyberanie výsledkov dotazu. Ak však nepotrebujeme získavať z tabuľky státisíce riadok, chýbať nám nebude.

Prvým parametrom je SQL dotaz. Druhý parameter je nepovinný a slúži na odovzdávanie dát pomocou tzv. Parametrizovaných otázok. Je to vynikajúca vlastnosť ovládačov MySQLi a PDO. Pôvodný ovládač túto vlastnosť nemá, preto je nutné dáta od užívateľov ošetriť funkcií mysql_real_escape_string(). PDO túto barličku nepotrebuje, dáta je možné odovzdávať priamo. Nespornou výhodou je, že dĺžka vkladaných dát sa nezapočítava do limitu dĺžky SQL dotazu. To iste ocenia najmä tí, ktorí radi do databázy ukladajú fotky či videá. V našom príklade druhý parameter zatiaľ nebude použitý.

<?php
// soubor Adresar.class.php

class Adresar{
  private $seznam;

  function __construct($spojeni){
    $this->seznam=$spojeni->queryAll("SELECT * FROM adresar");
    if(!sizeof($this->seznam)) {
      throw new Exception("Tabulka je prázdná");
    }
  }

  function __toString() {
    $headers='<tr><th>'.implode('</th><th>',array_keys($this->seznam[0])).'</th></tr>';
    $rows=array();
    foreach($this->seznam as $row){
      $rows[]='<tr><td>'.implode('</td><td>',array_map('htmlspecialchars',$row)).'</td></tr>';
    }
    $table=implode("\n",$rows);
    return <<<EOT
<table border="1">
$headers
$table
</table>

EOT;
  }
}

Trieda Adresar doznala len kozmetické zmeny. Zjednodušil sa konštruktor a volanie SQL dotazu. Presenter je stále rovnaký.

Zostáva už len hlavný modul, ktorý nazvem jednoducho index.php. Musím mu nejako vysvetliť, aby si natiahol potrebné moduly a pracoval s nimi. K tomu slúži príkaz include():

include('MyDB.class.php');
include('Adresar.class.php');

Lenže dnes už sa to tak nerobí, pretože u väčších projektov by mohlo byť dosť pracné a neprehľadné starať sa o natiahnutie všetkých modulov. Našťastie si môžeme v PHP nadefinovať funkcii so špeciálnym názvom __autoload(), ktorá to urobí za nás zakaždým, keď budeme chcieť nejakú triedu použiť.

<?php
// soubor index.php

function __autoload($class){
  include($class.'.class.php');
}

try{
  $spojeni=new MyDB("localhost","kit","","test");
  $adresar=new Adresar($spojeni);
  echo $adresar;
} catch(Exception $e) {
  echo "Tabulku nelze vypsat<br />\n";
  echo $e->getMessage(),"\n";
}

Teraz je už aplikácia hotová. Je síce trochu dlhšie, než bola pôvodne, ale získali sme modulárnosť. Databázu môžeme použiť aj na iný účel so zjednodušeným ovládaním. Triede Adresár môžeme podstrčiť inú databázu alebo iný zdroj dát. Ak budeme potrebovať inú vlastnosť databázy, jednoducho ju do triedy pridáme ako ďalšiu metódu.

Javí sa niekomu výsledný kód príliš komplikovaný? Aj to je možné. Úplne prvý príklad robil prakticky to isté a mal len 14 riadok. Lenže vypísanie tabuľky je veľmi primitívne úloha. U bežných aplikácií by sme veľmi rýchlo stratili prehľad a zhoršila by sa udržiavateľnosť kódu.

Nabudúce si urobíme trochu zložitejšie príklad a vysvetlíme si záhadnú skratku CRUD.


 

Všechny články v sekci
Ostatné tutoriály v PHP
Článek pro vás napsal Kit
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Jsem spokojeným uživatelem operačních systémů založených na linuxovém jádře. Zejména openSUSE a Ubuntu. Pro psaní veškerých textů a programů používám vynikající textový editor Vim. Aplikace se snažím psát vždy v tom nejvhodnějším programovacím jazyk...
Aktivity (1)

 

 

Komentáře

Avatar
Kit
Redaktor
Avatar
Kit:7.7.2012 12:05

Proto jsem z WZ utekl na Endoru, kde je PHP 5.3.13. Je tam i rychlejší MySQL, ale občas mi zmizí a musím ji založit znovu. Raději používám SQLite.

Odpovědět
7.7.2012 12:05
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Karel
Neregistrovaný
Avatar
Karel:10.3.2013 23:46

Sem ještě docela začátečník a chci se zeptat jak stímhle můžu dál pracovat?

 
Odpovědět
10.3.2013 23:46
Avatar
Luboš Běhounek Satik
Autoredaktor
Avatar
Odpovídá na Kit
Luboš Běhounek Satik:10.3.2013 23:54

Na Endoře mám jeden web asi 3 roky a bez problémů, DB se mi ještě neztratila.. :)

Odpovědět
10.3.2013 23:54
https://www.facebook.com/peasantsandcastles/
Avatar
Kit
Redaktor
Avatar
Odpovídá na Luboš Běhounek Satik
Kit:11.3.2013 9:48

Možná jsem si to spletl s IC. Možná mi ta databáze expirovala pro nečinnost.

Odpovědět
11.3.2013 9:48
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
mkub
Redaktor
Avatar
mkub:17.11.2013 14:52

v tvojom priklade sa 3x opakuje tento kod:

$navrat=$this->spojeni->prepare($query);
$navrat->execute($param);

myslim, ze by sa dal nahradit privatnou metodou a tam kde sa ma pouzit, tak sa na tu metodu jednoducho odkazovat pomocou $this
tym by sa skratil cely kod triedy

 
Odpovědět
17.11.2013 14:52
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Kit
Redaktor
Avatar
Odpovídá na mkub
Kit:17.11.2013 14:57

Kód třídy by se tím prodloužil. Proto je to tak jak to je.

Odpovědět
17.11.2013 14:57
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
mkub
Redaktor
Avatar
Odpovídá na Kit
mkub:17.11.2013 15:07

myslim, ze v tomto pripade mierne, ale pri vacsom mnozstve metod definicia privatnej metody by zmensil kod triedy
ja mam radsej, ked sa opakujuci kod zapise iba raz a potom sa nan na potrebnom mieste odkazuje

 
Odpovědět
17.11.2013 15:07
Avatar
Kit
Redaktor
Avatar
Odpovídá na mkub
Kit:17.11.2013 15:21

Ten kód se mi většinou neopakuje tak jak v tomto příkladu. Nepotřebné metody tam nedávám a naopak tam dávám komplexnější, které některé parametry doplňují samy z lokálních atributů a konstant. Databázovou vrstvu prostě nedělám tak primitivní jako v tomto příkladu.

Dnes bych to napsal jinak, ale přepisovat to nebudu a opravovat už vůbec ne.

Snažím se, aby se mi celá třída vešla do 60 řádek, takže o moc delší je stejně nedělám.

Editováno 17.11.2013 15:22
Odpovědět
17.11.2013 15:21
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Ondřej Langr (andysekcze):1.10.2015 13:58

Kde je ten další díl? :D

Odpovědět
1.10.2015 13:58
I have a charger. I have Note 7. Umh I haven't Note7.
Avatar
Tomáš Chocenský:25.4.2018 0:07

Ahoj
Chci se zeptat. Díl na nějž nejspíše odkazuje tato věta : "Příště si uděláme trochu složitější příklad a vysvětlíme si záhadnou zkratku CRUD." (tedy závěrečná věta tohoto tutoriálu) ten někde existuje? Pokud ANO tak kde? :-)

 
Odpovědět
25.4.2018 0:07
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í!