Práce s MySQL v PHP - Použití ovladače MySQLi
Zde je pokračování úvodního článku http://www.itnetwork.cz/…iho-ovladace
Tentokrát jsem použil novejší ovladač MySQLi. Bohužel s ním mnoho zkušeností nemám, ale nemohu ho ignorovat. V uvedeném příkladu se moc neprojeví jeho přednosti, ale snad to nebude na škodu.
Nejprve jsem se pokusil o klasický procedurální kód. Výjimky jsou však pouze objektové, proto je ponechám.
<?php try { $spojeni=@mysqli_connect("localhost","kit","","test"); if (!$spojeni) { throw new Exception(mysqli_connect_error(), mysqli_connect_errno()); } mysqli_query($spojeni,"SET NAMES utf8"); $navrat=@mysqli_query($spojeni,"SELECT * FROM adresar"); if(!$navrat) { throw new Exception(mysqli_stmt_error($navrat), mysqli_stmt_errno($navrat)); } $row=mysqli_fetch_assoc($navrat); if(!isset($row)) { throw new Exception("Tabulka je prázdná"); } echo("<table border=\"1\">\n"); echo("<tr>\n"); foreach($row as $key => $value) { echo("<th>".$key."</th>\n"); } echo("</tr>\n"); mysqli_data_seek($navrat,0); while ($row = mysqli_fetch_assoc($navrat)){ echo("<tr>"); foreach($row as $value) { echo("<td>".htmlspecialchars($value)."</td>"); } echo("</tr>\n"); } echo("</table>\n"); } catch(Exception $e) { echo "Tabulku nelze vypsat<br />\n"; echo $e->getMessage(),"\n"; }
Je patrné, že se tato procedurální verze příliš neliší od předchozí verze základního ovladače MySQL. Výhoda MySQLi se projeví až při použití parametrizovaných dotazů a dalších pokročilých funkcí. Také se projeví na výkonu, neboť MySQLi je rychlejší.
Nyní následuje pokus o objektové řešení aplikace. Snažil jsem se přiblížit objektovému programování, jak ho vidím v různých návodech.
<?php class Adresar{ private $spojeni; private $navrat; function __construct($host,$user,$pass,$name){ $this->spojeni= @new mysqli($host,$user,$pass,$name); if ($this->spojeni->connect_error) { throw new Exception($this->spojeni->connect_error, $this->spojeni->connect_errno); } $this->spojeni->query("SET NAMES utf8"); } function query($query) { $this->navrat=$this->spojeni->query($query); if(!$this->navrat) { throw new Exception($spojeni->error, $spojeni->errno); } } function getHeaders(){ $row=$this->navrat->fetch_assoc(); if(!isset($row)) { throw new Exception("Tabulka je prázdná"); } return $row; } function getRows(){ $rows=array(); $this->navrat->data_seek(0); while ($row = $this->navrat->fetch_assoc()){ $rows[]=$row; } return $rows; } } try{ $db=new Adresar("localhost","kit","","test"); $db->query("SELECT * FROM adresar"); $row=$db->getHeaders(); echo("<table border=\"1\">\n"); echo("<tr>\n"); foreach($row as $key => $value) { echo("<th>".$key."</th>\n"); } echo("</tr>\n"); foreach($db->getRows() as $row){ echo("<tr>"); foreach($row as $value) { echo("<td>".htmlspecialchars($value)."</td>"); } echo("</tr>\n"); } echo("</table>\n"); } catch(Exception $e) { echo "Tabulku nelze vypsat<br />\n"; echo $e->getMessage(),"\n"; }
Jak je vidět, program se mi trochu prodloužil. Ani se mi v této podobě moc nelíbí. Pokusím se tedy přepsat ho do podoby, která je mi bližší:
<?php class Adresar{ private $spojeni; private $navrat; private $head; private $adr; function __construct($host,$user,$pass,$name){ $this->spojeni= @new mysqli($host,$user,$pass,$name); if ($this->spojeni->connect_error) { throw new Exception($this->spojeni->connect_error, $this->spojeni->connect_errno); } $this->spojeni->query("SET NAMES utf8"); } function precti() { $this->navrat=$this->spojeni->query("SELECT * FROM adresar"); $this->head=$this->navrat->fetch_assoc(); if(!isset($this->head)) { throw new Exception("Tabulka je prázdná"); } $this->navrat->data_seek(0); if(!$this->navrat) { throw new Exception($spojeni->error, $spojeni->errno); } $this->adr=$this->navrat->fetch_all(); } function __toString() { $headers='<tr><th>'.implode('</th><th>',array_keys($this->head)).'</th></tr>'; $rows=array(); foreach($this->adr 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; } } try{ $adresar=new Adresar("localhost","kit","","test"); $adresar->precti(); echo $adresar; } catch(Exception $e) { echo "Tabulku nelze vypsat<br />\n"; echo $e->getMessage(),"\n"; }
Ještě stále to není ono. SQL dotazy jsou již odděleny od prezentace v HTML, program je o něco kratší a snad i přehlednější, ale testování návratové hodnoty po každém volání SQL dotazu nevypadá právě ideálně. Výsledek jednoho z dotazů jsem ani netestoval, i když bych vlastně měl.
Hodilo by se mi, kdyby se po každé chybě při práci s databází automaticky vyhodila výjimka. Možná to v MySQLi nějak jde, ale rozumný návod jsem nenašel. Řešení jsem však objevil v ovladači PDO, o kterém bude třetí pokračování tohoto seriálu.