Geek tričko zdarma Geek tričko zdarma
Hledáme grafika na pohodovou brigádu v Blenderu nebo programátora na hry v PyGame. Máš zájem? Napiš nám na redakce [zavináč] itnetwork.cz!
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde

Lekce 12 - Objektové počítadlo návštěv v PHP a PDO

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Statika v PHP do třetice, jsme dokončili statiku. Na dnešní PHP tutoriál máme slíbený opět nějaký reálný příklad. Půjde o objektovou práci s databází pomocí ovladače PDO, se kterým se v tomto dílu seznámíme.

Původně jsem chtěl vytvořit anketu, ale ta již je vysvětlená v tutoriálu se začátky PHP a jistě byste si ji do objektů dokázali převést. Dnes si tedy zkusíme naprogramovat webové počítadlo návštěv.

Metodika počítání přístupů

Při počítání návštěv webu se většinou rozlišuje mezi třemi termíny:

  1. Zobrazení - Počet všech zobrazení webu. Započítá se při každém přístupu. Pokud tedy nějaký uživatel zobrazí na webu 10 stránek za hodinu, připočte se 10 zobrazení.
  2. Návštěva - Návštěvník se započítá jen jednou asi za 30 minut. Pokud si tedy za hodinu 1 uživatel přečte 10 článků, bere se to jako že web 2x navštívil.
  3. UIP - Unikátní návštěvníci, přesněji počet unikátních IP adres za určité období. Pokud si uživatel přečte za měsíc 1000 článků, bere se to jen jako 1 unikátní zobrazení.

Zobrazení jsou samozřejmě nejvyšší a UIP nejnižší. UIP mají nejvyšší vypovídací hodnotu. Návštěvy jsou něco mezi a v našem případě je ukládat nebudeme, jelikož je není úplně jednoduché rozlišit. Budeme ukládat pouze zobrazení stránek a počet UIP z nich později jednoduše zjistíme tak, že si vybereme jen unikátní zobrazení za určitý časový úsek.

Databáze

Zobrazení tedy budeme ukládat do databáze. Při každém zobrazení stránky na našem webu vložíme do databáze řádek s aktuálním datem a IP adresou návštěvníka. Daly by se ukládat i další věci, jako prohlížeč nebo jazyk, ale to zanedbáme.

U hodně navštěvovaných webů se návštěvnost neukládá do databáze při každém zobrazení stránky, jelikož by to databázi příliš zatěžovalo. Zobrazení se logují do textového souboru a za nějaký čas se spustí skript, který je ze souboru uloží do databáze. K DB tedy není přistupováno tak často a zátěž je nižší. V našem případě toto můžeme určitě zanedbat a budeme ukládat zobrazení rovnou do databáze.

Zakládací skripty

Vytvořme si databázovou tabulku zobrazeni, která bude mít 3 sloupce:

  • zobrazeni_id (int, AI, primární klíč)
  • ip (varchar 40)
  • datum (int)
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Datum a čas zde uložíme jako celé číslo. Je to druhá alternativa oproti databázovému typu DATETIME. Já osobně ji používám více, tak si alespoň zkusíme zas něco jiného. Datum uložíme jako počet vteřin od roku 1970. Dělá se to tak často a rok 1970 není náhodný, jedná se o začátek Unixové epochy. PHP na to má samozřejmě funkce.

Tabulku si klidně naklikejte v PHPMyAdmin:

MySQL tabulka pro počítadlo návštěv

Případně zde máte zakládací skripty:

CREATE TABLE IF NOT EXISTS `zobrazeni` (
  `zobrazeni_id` int(11) NOT NULL AUTO_INCREMENT,
  `ip` varchar(40) COLLATE utf8_czech_ci NOT NULL,
  `datum` int(11) NOT NULL,
  PRIMARY KEY (`zobrazeni_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=1 ;

Databázi máme připravenou.

První seznámení s PDO

Minule jsme si vysvětlili, že se v PHP pro práci s databází používá téměř výhradně objektový ovladač PDO. PDO je třída, která je součástí jazyka PHP. Ukažme si, jak by vypadalo připojení se k databázi a vložení nového řádku do tabulky zobrazeni pomocí tohoto ovladače.

Připojení

Vytvoříme si úplně nový projekt (novou složku, třeba s názvem pocitadlo) a dovnitř umístíme index.php. Do indexu vložíme následující řádky:

<?php

$nastaveni = array(
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
);

$spojeni = new PDO("mysql:host=localhost;dbname=pocitadlo_db", 'root', '', $nastaveni);

Nejprve si vytvoříme pole s nastavením pro PDO. První klíč je způsob, jakým chceme, aby byly zpracovávány chyby. Zvolili jsme výjimky (exceptions), k těm se dostaneme dále v seriálu. Ten druhý určuje, že nechceme, aby PDO emulovalo prepared statements pro starší verze MySQL, které ho nepodporovaly. Bez tohoto nastavení bychom nemohli používat např. parametry v klauzuli LIMIT. Třetí klíč je inicializační příkaz pro databázi, zde chceme nastavit kódování na UTF-8.

Klíčové je vytvoření spojení, což provedeme jako vytvoření instance PDO. První parametr konstruktoru PDO je řetězec obsahující připojovací údaje. Prvním je host (localhost), druhým název databáze (u mně pocitadlo_db). Další 2 parametry konstruktoru jsou uživatelské jméno (u mne root) a heslo (u mne prázdné). Jako poslední parametr předáme naše nastavení. Pokud vám to po zapsání tohoto řádku nevypsalo žádnou chybu, jste úspěšně připojení k DB. Pokud ne, opravte si připojovací údaje.

Dotazy

Jakmile máme instanci PDO spojení, můžeme na ni volat databázové dotazy. Na rozdíl od zastaralých ovladačů podporuje PDO tzv. prepared statements. Jedná se o oddělení vkládání samotného dotazu a parametrů do tohoto dotazu. Jelikož je dotaz od svých parametrů oddělený, nemůže dojít k SQL injekci. Databáze si přijaté parametry sama ošetřuje. V minulosti se v PHP pro podobnou ochranu používaly funkce jako mysql_real_es­cape_string(), na které už můžete zapomenout :)

Připišme do index.php další řádky:

$dotaz = $spojeni->prepare('INSERT INTO `zobrazeni` (`ip`, `datum`) VALUES (?, ?)');
$parametry = array($_SERVER['REMOTE_ADDR'], time());
$dotaz->execute($parametry);

Kód si popišme. Nejprve si vytvoříme instanci dotazu. Tu nám vrátí metoda prepare() na instanci PDO spojení. Do parametru metody napíšeme normálně SQL dotaz jako textový řetězec. Namísto parametrů dotazu však vložíme otazníky. Nikdy nebudeme vkládat proměnné nebo hodnoty přímo do dotazu! Jedná se o bezpečnostní riziko.

Parametry potom vložíme do nového pole v tom pořadí, v jakém jsou otazníky v dotazu. $_SERVER['REMO­TE_ADDR'] obsahuje IP adresu (na lokálním počítači budete mít dost možná hodnotu :1 nebo něco podobného). Funkce time() vrátí aktuální čas jako UNIX timestamp (počet sekund od 1.1.1970).

Vytvořený dotaz nakonec spustíme metodou execute(), které předáme pole s parametry, které se do dotazu mají vložit. Zkuste index.php navštívit a podívat se do tabulky, bude tam nový řádek.

POZOR! Pokud máte v PHP zapnuté chybové hlášky a máte nějakou chybu v dotazu, vypíše se chybová zpráva. Ovladač PDO vyhazuje při chybách výjimky (což je správně) a jelikož se ty vypisují spolu se stopou stacku, mohou zobrazit spolu s částí kódu i vaše heslo k databázi! Je velmi důležité, abyste o tom věděli a měli vypnuté chyby na produkčním serveru (kde samozřejmě vypnuté být mají).

To by bylo pro dnešek vše. V příští lekci, Objektové počítadlo návštěv v PHP - dokončení, budeme v počítadle pokračovat a vytvoříme si objekt, který bude návštěvy zaznamenávat, analyzovat a vypisovat. Dnešní zdrojový kód včetně exportu DB je jako vždy připojen pod článkem ke stažení.


 

Stáhnout

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

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
25 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Předchozí článek
Statika v PHP do třetice
Všechny články v sekci
Objektově orientované programování (OOP) v PHP
Miniatura
Následující článek
Objektové počítadlo návštěv v PHP - dokončení
Aktivity (7)

 

 

Komentáře
Zobrazit starší komentáře (8)

Avatar
Tomáš Bezecný:18.10.2017 21:28

Chtěl bych se ještě zeptat: Co musím smazat, aby mi to zobrazovalo jen počet navštívení Celkem/Mesic/Tyden?
Díky moc a hezký zbytek večera

 
Odpovědět 18.10.2017 21:28
Avatar
Odpovídá na Tomáš Bezecný
Tomáš Bezecný:18.10.2017 21:32

Hotovo, omlouvám se, nejde mi příspěvek editovat, když odejdu z webu a vrátím se zpět :(

 
Odpovědět 18.10.2017 21:32
Avatar
Jan Straka
Člen
Avatar
Jan Straka:19. ledna 17:24

Nefunguje

 
Odpovědět 19. ledna 17:24
Avatar
Michal Suchánek:2. července 18:19

Šlo by použít ovladač PDO i pro připojení k MS databázi? Díky

 
Odpovědět 2. července 18:19
Avatar
Jaroslav Smrž
Redaktor
Avatar
Odpovědět 2. července 19:02
I have no idea what it is doing but I´m scared to delete it... xD
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Ondřej Vaňkát:16. července 1:17

"Nikdy nebudeme vkládat proměnné nebo hodnoty přímo do dotazu! Jedná se o bezpečnostní riziko."...Ty proměnné chápu, ale proč ani hodnoty ? Kdybych dal konkrétní ip adresu do dotazu, normálně jí tam napsal, bez proměnné, je to také riziko ? Díky

 
Odpovědět 16. července 1:17
Avatar
Odpovídá na Ondřej Vaňkát
Michal Šmahel:16. července 13:43

Ahoj, narozdíl od proměnných (což v tomto případě IP adresa je) hodnoty není nutné předávat zvlášť přes předpřipravený dotaz. Myslím tím samozřejmě absolutní hodnoty, které sám zadáš v kódu (10, "Y", true, ...). Tyto hodnoty nikdy nemohou nabýt jiného stavu, než sám zadáš (kromě přetypování). Tím pádem nemohou ani nijak omezit bezpečnost. V praxi se ale často stává, že se kvůli mísení absolutních hodnot s proměnnými dosazuje "přes otazníky" vše. Sjednotí to zápis a může to pomoct s přehledností. Navíc, když chceš potom hodnotu prohodit za proměnnou, je to mnohem jednodušší.

Odpovědět 16. července 13:43
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
Odpovídá na Michal Šmahel
Ondřej Vaňkát:16. července 13:55

Jasné, chápu, díky.

 
Odpovědět 16. července 13:55
Avatar
Neci Neco
Člen
Avatar
Neci Neco:19. července 10:17

Ahoj, moc se mi tento seriál libí, hodlám dokoupit lekce 15+, ale v db "zobrazeni.sql" vidim datum 4.9.2013! Skoro 6let stará databáze a tedy skoro 6let starý tutoriál?! Jako začátečník nerozpoznám, zda je něco out nebo ne a doposud byla moje důvěra 100% :D.
Probíhá nějaká aktualizace článků? Díky za info.

 
Odpovědět 19. července 10:17
Avatar
Milan Turyna
Redaktor
Avatar
Odpovídá na Neci Neco
Milan Turyna:19. července 10:22

Ahoj, neboj tenhle tutoriál ještě "out" není, teda jak pro koho, někdo to jako out brát může, někdo nemusí, ale z hlediska funkčnosti a bezpečnosti out není. Jinak pokud vím tak tady aktualizování článku neprobíhá, nebo aspoň jsem to nepostřehl.

Editováno 19. července 10:23
 
Odpovědět 19. července 10:22
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.

Zobrazeno 10 zpráv z 18. Zobrazit vše