Počítadlo přes SQL?

Nejprve si zkusíme jen zobrazit číslo, zadané formulářem. Formulář bude jednoduchý:

<form action="zobraz.php" method="get">
Zadejte celé číslo (chyby nejsou ošetřeny!):&nbsp;
<input type="text" name="cislo">
<br>
<input type="submit" name="submit" value="odeslat">
</form>

Protože na WebZdarma je zapnutá funkce register_globals, získáme proměnnou $cislo. Připravte si vhodný .gif soubor, který bude obsahovat deset číslic od nuly po devítku. Číslice by měly být uspořádány neproporcionálně. Já jsem to zkoušel na následujícím obrázku, který je ale naprosto nevhodný, protože je to jpeg:

Jednotlivá čísla mají rozměr 25 bodů na šířku x cca 39 bodů na výšku. Obrázek je větší, abychom při chybném volání funkce nedostávali chybné údaje. Například číslici pět na pozici 2 z obrázku $src do obrázku $dst nám nakopíruje funkce:

imagecopy($dst, $src, 2*25, 0, 5*25, 0, 25, 39);

Z toho je vidět, že skupiny jsou číslované od nuly. Počet číslic zvolíme tím, jak velký bude výstupní obrázek. Nám by mohly stačit čtyři číslice. Obrázek pro výstup by tedy mohl vytvořit příkaz:

$dst = imagecreatetruecolor(25*4, 39);

Poslední číslici zjistíme snadno, je to zbytek po celočíselném dělení deseti:

$c = $cislo % 10;

Horší to je s ostatními. Nyní bychom podle osvědčeného způsobu, jaký používáme například v Delphi nebo C-Builderu, číslo celočíselně podělit deseti. Překvapivě v php není celočíselné dělení. Musíme použít opis:

$cislo = ($cislo - ($cislo % 10)) / 10;

resp. $cislo = ($cislo - $c) / 10; , protože zbytek po dělení již jsme počítali. Také by šlo zavolat funkci floor, která zaokrouhluje na nejbližší nižší (pozor na záporná!) celé číslo. Dělení je rychlejší, u funkce je zase záruka, že vyjde celé číslo.

Jiná možnost je převést $cislo zpět na text funkcí sprintf(%d, $cislo); a rozložit na jednotlivá písmena, například funkcí

$pismenka = str_split($str, 1);

Každé písmeno ale musí být pro použití jako souřadnice převedeno na číslo; jedna z možostí je využít funkce scanf( ), jiná je vyjít z čísla znaku v ASCII - víme, že číslice jsou za sebou a ord("0") je 48:

$cislice[3] = ord($pismenka[3])-48;

Další možností je použít funkci intval( ) - toto řešení je asi nejvhodnější; pro převod na text ale nemohu doporučit strval( ), protože řetězec by nemusel mít správnou délku. Připravené ukázky na serveru webzdarma ale vycházejí z celočíselného dělení. Cyklus bude vypadat:

for ($i=3, $i>=0, $i--) {
  $c = $cislo % 10;
  $cislo = ($cislo - $c) / 10;
  imagecopy($dst, $src, $i*25, 0, $c*25, 0, 25, 39);
}

K inicializaci obrázku nutno podotknout, že by se měla nastavit výchozí barva pozadí. Pokud se tak nestane, asi to nebude na závadu.

Způsob generování obrázku jsme zkoušeli minule (medvedi.htm).

Připravený skript je možné zavolat souborem pocitadlo.htm (pocitadlo.htm), nebo přímo odkazem jako je http://zpp.wz.cz/zobraz.php?cislo=3573 (lze napsat do adresní řádky prohlížeče). Na serveru Webzdarma je zapnutá funkce register_globals, proto nemusíme psát $_GET["cislo"].

Nyní bychom se měli věnovat SQL, aby bylo kam psát aktuální hodnotu. Nejsnazší je si udělat tabulku o jediném políčku, a to číst. Abychom se měli čeho chytit, doporučuji do sousedního políčka (to už tabulka bude mít dvě buňky) si zaznamenat nějaký klíč ("key"). Ukázka tabulky s náhodným číslem:

cislo key
57 77

V hodním řádku jsou názvy sloupců, v dolním hodnoty. Doporučuji předvyplnit. Otevřeme databázi, přečteme hodnotu do naší proměnné, a ihned zapíšeme hodnotu o jednu vyšší tamtéž:

mysql_connect('mysql.webzdarma.cz','zpp','tudlenudle')
   or die('chyba:'.mysql_error() );
mysql_select_db('zpp');
$result=mysql_query('select * from pocitadlo where key=77');
$cislo=intval(mysql_result($result,0,"cislo"));

//zvetseni a zapis zpet:
$cislo++;
$result=mysql_query('update pocitadlo set cislo='.$cislo.' where key=77;');
mysql_close();     
Poznámka. Původně jsem chtěl klíč označit slovně, ale dvě stejná slova se na serveru WebZdarma nerovnají. Jak by takový select měl vypadat, napovídá příkaz, který si server vygeneroval pro smazání řádky (příkaz se týká až odladěné konečné podoby tabulky po tomto cvičení; "limit 1" omezuje počet smazaných řádek pro případ duplicit na jedinou):

DELETE FROM `pocitadlo` WHERE `cislo` = '88' AND `klic` = '1' AND CONVERT( `ipaddr` USING utf8 ) = '147.32.162.175' LIMIT 1 ;

Pak můžeme doplnit grafický výstup (na další řádky php).

V některých případech by bylo zajímavé si zapsat, na kterém počítači se počítadlo zobrazilo. Protože počítadlo se použije jako obrázek, o který si říká prohlížeč, získáme ip adresu, ze které se původní stránka četla. Škoda, že dnes to již většinou bude adresa proxy serveru. Tabulku ale uděláme jinak - každý přístup způsobí zápis do tabulky, kde tedy bude číslo a příslušná ip-adresa. Šlo by použít autoinkrement, ale není to třeba; stejně bychom se museli ptát funkce select, které číslo je největší (sloupeček s adresou se může jmenovat "ip"):

$result=mysql_query('select max(cislo) as minuly from pocitadlo');
$cislo=intval(mysql_result($result,0,"minuly"));

//zvetseni a zapis zpet:
$cislo++;
$result=mysql_query('insert into pocitadlo values ('.$cislo.',"'.$_SERVER["REMOTE_ADDR"].'");');

"select max(cislo)" není funkce, ale zvláštní způsob volání příkazu SELECT, který vybere největší hodnotu ze sloupce "cislo". Navíc byl použit obrat "as", který způsobí přejmenování výsledku v asociativním poli, které vrací mysql_result - je to jen z důvodu přehlednosti dalšího řádku, aby tam nebylo dvakrát napsáno "cislo".

Neopisuji vše, otevření a uzavření databáze si doplníte sami. Pozor, nyní musí být druhý sloupec tabulky textový o alespoň 16 znacích!

Myslím, že výklad je úplný a obrázek, který bude počítat, si můžete napsat a použít na webové stránce.

Poznámka - jak uděláme více počítadel? Pro nás by bylo asi nejjednodušší vytvořit více tabulek a pro každé počítadlo nakopírovat (a poopravit) php skript pod jiným jménem.

Domácí úkol: Opravte počítadlo tak, aby každou IP adresu započítalo jen jednou. Ještě před deseti lety, v dobách reálných ip, by to v zásadě fungovalo...

http://zpp.wz.cz/0pocitadlo.php, resp. http://zpp.wz.cz/1pocitadlo.php - pokud si je nechcete vyzkoušet, ale jen prohlédnout, zkuste lokální kopie na serveru Fsinet: 0pocitadlo.php, resp. 1pocitadlo.php .