Lekce 13 - Objektové počítadlo návštěv v PHP - Databáze
V minulé lekci, Objektové počítadlo návštěv v PHP a PDO, jsme začali programovat počítadlo návštěv. Založili jsme si databázovou tabulku a naučili se obsluhovat databázi pomocí ovladače PDO.
V dnešním PHP tutoriálu si ukážeme, jak databázové spojení udržovat, předávat a jak usnadnit spouštění dotazů.
Databázový wrapper
Práce s databází v PDO, jak jsme si ji ukazovali, má jeden nedostatek. Určitě totiž budeme chtít používat databázi na více místech v aplikaci a takto bychom se museli pokaždé znovu připojovat nebo si instanci spojení ručně předávat. Když si vzpomeneme na statiku, tak právě ta nám umožňuje sdílet nějaká data v celé aplikaci. Vytvoříme si tzv. databázový wrapper. Bude se jednat o statickou, pomocnou třídu, kterou obalíme volání PDO. Z toho označení wrapper, jako obal.
Vytvoříme si naši známou složku pro třídy, opět ji pojmenujeme třeba
tridy/
. Ve složce vytvoříme soubor Databaze.php
s
následujícím obsahem:
class Databaze { private static PDO $spojeni; private static array $nastaveni = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" ); public static function pripoj(string $host, string $uzivatel, string $heslo, string $databaze): PDO { if (!isset(self::$spojeni)) { self::$spojeni = @new PDO( "mysql:host=$host;dbname=$databaze", $uzivatel, $heslo, self::$nastaveni ); } return self::$spojeni; } public static function dotaz(string $sql, array $parametry = array()): PDOStatement { $dotaz = self::$spojeni->prepare($sql); $dotaz->execute($parametry); return $dotaz; } }
Třída je velmi krátká a obsahuje dva privátní statické atributy.
Jedním je nastavení PDO, druhým je právě připojená instance
PDO
, kterou budeme v aplikaci sdílet.
Ve třídě dále nalezneme dvě veřejné statické metody. Jednu pro
připojení, která vytvoří instanci PDO
a tu uloží do
statické proměnné $spojeni
. Tam připojená instance zůstane
až do skončení skriptu. Druhá statická metoda nám umožňuje zadat dotaz a
jeho parametry. Dotaz je potom předán instanci PDO
a metoda
navrátí to, co navrátil dotaz. Wrapper je velmi jednoduchý a během tohoto i
dalších seriálů ho budeme ještě vylepšovat. Zatím nám však
stačí.
Třída SpravceNavstev
Logiku ke správě návštěv umístíme do nové třídy
SpravceNavstev
. Určitě budeme potřebovat metodu k zaznamenání
návštěvy, přesněji k uložení zobrazení. Dále se nám bude hodit metoda,
která vrátí celkový počet zobrazení a unikátních návštěvníků. Na
konec přidejme metodu, která vrátí návštěvy a zobrazení za posledních
několik dní.
Naše třída bude vypadat asi takto:
class SpravceNavstev { public function zapocitej(): void { Databaze::dotaz(' INSERT INTO `zobrazeni` (`ip`, `datum`) VALUES (?, ?) ', array($_SERVER['REMOTE_ADDR'], time())); } public function zobrazeniCelkem(): int { $vysledek = Databaze::dotaz(' SELECT COUNT(*) AS `pocet` FROM `zobrazeni` '); $data = $vysledek->fetch(); return $data['pocet']; } public function zobrazeniZa(int $dnu): int { $vysledek = Databaze::dotaz(' SELECT COUNT(*) AS `pocet` FROM `zobrazeni` WHERE `datum` > ? ', array(time() - $dnu * 86400)); $data = $vysledek->fetch(); return $data['pocet']; } public function uipCelkem(): int { $vysledek = Databaze::dotaz(' SELECT COUNT(DISTINCT `ip`) AS `pocet` FROM `zobrazeni` '); $data = $vysledek->fetch(); return $data['pocet']; } public function uipZa(int $dnu): int { $vysledek = Databaze::dotaz(' SELECT COUNT(DISTINCT `ip`) AS `pocet` FROM `zobrazeni` WHERE `datum` > ? ', array(time() - $dnu * 86400)); $data = $vysledek->fetch(); return $data['pocet']; } public function vypisStatistiky(): void { echo('<table>'); echo('<tr> <td>Zobrazení celkem</td> <td>' . $this->zobrazeniCelkem() . '</td> </tr>'); echo('<tr> <td>UIP celkem</td> <td>' . $this->uipCelkem() . '</td> </tr>'); echo('<tr> <td>Zobrazení měsíc</td> <td>' . $this->zobrazeniZa(30) . '</td> </tr>'); echo('<tr> <td>UIP mesíc</td> <td>' . $this->uipZa(30) . '</td> </tr>'); echo('<tr> <td>Zobrazení týden</td> <td>' . $this->zobrazeniZa(7) . '</td> </tr>'); echo('<tr> <td>UIP týden</td> <td>' . $this->uipZa(7) . '</td> </tr>'); echo('</table>'); } }
Ve třídě používáme náš statický databázový wrapper. Obsahuje celkem 6 jednoduchých metod. První je metoda pro uložení nového zobrazení. Tento dotaz jsme si již uváděli, teď jen používáme náš wrapper. Další 2 metody vracejí buď celkový počet zobrazení nebo počet zobrazení za posledních několik dní. Podobně potom máme 2 metody pro UIP. Všechny metodu jsou veřejné, kdybychom si někde v aplikaci chtěli zjistit nějakou statistiku samostatně.
Pokud z výsledku dotazu potřebujeme přečíst nějakou hodnotu, je třeba
nejprve zavolat na výsledku metodu fetch()
nebo
fetchAll()
.
fetch()
vrátí další řádek výsledku (při základním
nastavení jako asociativní pole), fetchAll()
vrátí
dvojrozměrné pole všech řádků, které dotaz vrátil. fetch()
budeme volat v případě, kdy nás zajímá jen jeden řádek,
fetchAll()
potom tehdy, kdy nás zajímají všechny řádky. Na
výsledku můžeme zavolat také rowCount()
, která vrátí počet
řádků ve výsledku. Nepoužívejte ji však místo SQL příkazu
COUNT
! K zajištění počtu unikátních IP adres jsme použili
klauzuli DISTINCT
. Pokud jste četli zdejší MySQL
seriál, tak jistě víte, že právě ta pracuje s unikátními
řádky.
V dotazech dále používáme konstantu 86400
, což je počet
vteřin ve dni Konstantu
vynásobíme počtem dní a výsledek odečteme od aktuálního času, který
vrací funkce time()
. Máme potom datum, od kterého nás
statistiky zajímají. Takováto práce s datem a časem mi přijde velmi
přehledná, ale to je asi věc názoru. Klidně můžete používat
databázový DATETIME
.
Zprovoznění aplikace
Pojďme vše zprovoznit. Vraťme se do index.php
, vložme do
něj HTML strukturu, PHP autoloader (abychom nemuseli třídy načítat ručně)
a nakonec se připojme k databázi:
<!DOCTYPE html> <html lang="cs-cz"> <head> <meta charset="utf-8" /> <title>Návštěvnost webu</title> </head> <body> <h1>Návštěvnost webu</h1> <?php mb_internal_encoding("UTF-8"); function nactiTridu($trida) : void { require("tridy/$trida.php"); } spl_autoload_register("nactiTridu"); Databaze::pripoj('localhost', 'root', '', 'pocitadlo_db'); ?> </body> </html>
Spojení se uložilo do statické proměnné a už se o něj nemusíme starat, zůstane tam do skončení skriptu.
Započítání návštěvy a výpis tabulky návštěv vložíme pro
jednoduchost obojí do indexu. V praxi je zjištění počtu návštěv velmi
náročná operace (kvůli COUNT
ve velkém počtu záznamů) a
proto ji budeme volat jen někde v administraci, abychom se podívali jak si
stojíme. Naopak započtení návštěvy zavoláme na každé stránce webu:
$spravceNavstev = new SpravceNavstev(); $spravceNavstev->zapocitej(); $spravceNavstev->vypisStatistiky();
Výsledek jsme nijak nestylovali, takže vypadá skromně:
Výsledek dnešního snažení je ke stažení pod lekcí.
V následujícím kvízu, Kvíz - Statika a práce s databází v PHP OOP, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
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 1146x (4.15 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP