E N C Y K L O P E D I E ENCYKLOPEDIE WEBDESIGNERA
W. Jason Gilmore
KOMPENDIUM ZNALOSTÍ PRO ZAČÁTEČNÍKY I PROFESIONÁLY
První vydání této knihy z roku 2005 bylo v poměrně k rátké době rozebráno a kniha se zařadila mezi bestseller y vydavatelství Zoner Press. Nové vydání knihy je výrazně rozšířeno a doplněno, přibylo více než 150 stran a 7 nových kapitol: tři z nich jsou věnované specifickým tématům PHP – probírají se v nich PEAR (PHP Extension and Application Repository), funkcionalita související s dat em a s časem a rozšíření PDO (PHP Data Objec ts). Ve čtyřech dalších k apitolách najdete výklad rozšíření mysqli PHP 5 a novou funkcionalitu MySQL 5 – uložené rutiny, triggery a pohledy na data (views). Upraveny a doplněny byly i původní kapitoly knihy, které jsou věnovány klíčovým schopnostem PHP i MySQL počínaje instalací a konfigurací jak na platformě Linux, tak i Windows, práci s proměnnými, datovými typy, poli i funkcemi, ale také např. využití šablon Smarty a webových služeb, až po pokročilé rysy objektově orientovaného programování, zpracování výjimek nebo detekci chyb. Práci s databáz emi se v ěnuje téměř polovina knihy, pozornost je zaměřena především na M ySQL a SQLit e, nechybí však ani inf ormace o spolupráci s jinými databázovými systémy. Vedle již zmíněných novinek v knize najdete kapitoly věnované např. možnostem indexování, tvorbě databázových dotazů a řadě dalších praktických témat. Všechny ukázkové příklady najdete buďto na webu původního vydavatele www.apress.com, nebo na str ánkách našeho v ydavatelství www.zonerpress.cz v sekci Download.
www.zoner.cz © Foto: Jiří Heller, www.heller.cz
Věrným čtenářům je určen výhodný PRÉMIOVÝ PLUS PROGRAM.
Fotografie z nabídky fotobanky HELLER.CZ
E N C Y K LO P E D I E W E B D E S I G N E R A
DOPORUČENÁ CENA: 650 KČ KATALOGOVÉ ČÍSLO: ZR617
Zoner Press tel.: 532 190 883 fax: 543 257 245 e-mail: knihy@zoner.cz http://www.zonerpress.cz
VELKÁ
KNIHA
PHP MySQL SQL 5
KOMPENDIUM ZNALOSTÍ PRO ZAČÁTEČNÍKY I PROFESIONÁLY /přepracované, doplněné a rozšířené vydání publikace z roku 2005/
© Foto: Jiří Heller
W. Jason Gilmore
ISBN 80-86815-53-6
ZONER software, s.r.o., Nové sady 18, 602 00 Brno 9 7 8 8 0 8 6
PHP_sec.indd 1
kompendium znalostí pro začátečníky a profesionály
ZONER software, s.r.o. významný producent software v oblasti digitální fotografie, počítačové grafiky a multimédií, poskytovatel internetových služeb, souvisejících s prezentací na internetu a e-komercí, a nakladatelství odborné literatury.
VELKÁ KNIHA
PHP & MySQL 5
PHP MySQL 5
W. Jason Gilmore
VELKÁ KNIHA
Pod tímto logem vycházejí publikace určené pro každého, kdo se zajímá o t vorbu webových stránek. Od r yze praktických příruček a průvodců až po komplexní publikace o všem, co potřebuje webdesignér při každodenní práci. Na vydavatelský plán a výhody, které můžete získat, se informujte na adrese vydavatelství.
W E B D E S I G N E R A
8 1 5 5 3 4
www.zonerpress.cz
15.12.2006 15:53:57
VELKÁ KNIHA
PHP a MySQL 5 KOMPENDIUM ZNALOSTÍ PRO ZAČÁTEČNÍKY I PROFESIONÁLY /přepracované, doplněné a r ozšířené vydání publikace z r oku 2005/
W. Jason Gilmore
Beginning PHP and MySQL 5: From Novice to Professional, Second Edition Copyright © 2006 by W. Jason Gilmore Original English language published Apress L.P., 2560 Ninth Street, Suite 219, Berkeley, CA 9 47 10 USA. Copyright © 2006 by Apress L.P. CZECH language edition copyright © 2006 by ZONER software, s.r.o. All rights reserved. No part of this book ma y be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Apress L.P. Originál v anglickém jaz yce vydal Apress L.P., 2560 Ninth Street, Suite 219, Berkeley, CA 9 47 10 USA. C opyright © 2006 Apress L.P. České vydání Copyright © 2006 ZONER software s.r.o.. Všechna práva vyhrazena. Žádná část t éto publikace nesmí být reprodukována nebo předávána žádnou formou nebo způsobem, elektronicky ani mechanicky, včetně fotokopií, natáčení ani žádnými jinými systémy pro ukládání bez výslovného svolení Apress L.P.
Velká kniha PHP a MySQL 5 kompendium znalostí pro začátečníky i profesionály přepracované, doplněné a rozšířené vydání publikace z roku 2005 Autor: W. Jason Gilmore Copyright © ZONER software, s.r.o. Vydání první v roce 2007. Všechna práva vyhrazena. Zdrojový kód příkladů uvedených v knize je k dispozici na adrese http://www.apress.com v sekci Source Code nebo na adrese http://www.zonerpress.cz v sekci Download. Zoner Press KATALOGOVÉ ČÍSLO: ZR617 ZONER software, s.r.o. Nové sady 18, 602 00 Brno Překlad: RNDr. Jan Pokorný Odpovědný redaktor: Miroslav Kučera, Pavel Kristián Šéfredaktor: Ing. Pavel Kristián DTP: Filip Božoň © Cover foto: Jiří Heller, HELLER.CZ s.r.o., www.heller.cz © Cover a layout: Ing. Pavel Kristián Informace, které jsou v t éto knize zveřejněny, mohou byt chráněny jako patent. Jména produktů byla uvedena bez záruky jejich volného použití. Při tvorbě textů a vyobrazení bylo sice postupováno s maximální péčí, ale přesto nelze zcela vyloučit možnost výskytu chyb. Vydavatelé a autoři nepřebírají právní odpovědnost ani žádnou jinou záruku za použití chybných údajů a z toho vyplývajících důsledků. Všechna práva vyhrazena. Žádná část této publikace nesmí být reprodukována ani distribuována žádným způsobem ani prostředkem, ani reprodukována v databázi či na jiném záznamo vém prostředku či v jiném systému bez výslovného svolení vydavatele s výjimkou zveřejnění krátkých částí textu pro potřeby recenzí. Veškeré dotazy týkající se distribuce směřujte na: Zoner Press ZONER software, s.r.o. Nové sady 18, 602 00 Brno tel.: 532 190 883, fax: 543 257 245 e-mail: knihy@zoner.cz http://www.zonerpress.cz
ISBN 80-86815-53-6
Kniha je věnována památce Dr. Giovanni „Nino“ Sanzi (1929-2004). Addio, caro amico.
Stručný obsah Kapitola 1 Kapitola 2 Kapitola 3 Kapitola 4 Kapitola 5 Kapitola 6 Kapitola 7 Kapitola 8 Kapitola 9 Kapitola 10 Kapitola 11 Kapitola 12 Kapitola 13 Kapitola 14 Kapitola 15 Kapitola 16 Kapitola 17 Kapitola 18 Kapitola 19 Kapitola 20 Kapitola 21 Kapitola 22 Kapitola 23 Kapitola 24 Kapitola 25 Kapitola 26 Kapitola 27 Kapitola 28 Kapitola 29 Kapitola 30 Kapitola 31 Kapitola 32 Kapitola 33 Kapitola 34 Kapitola 35 Kapitola 36 Kapitola 37
Úvod do PHP Instalace a konfigurace Apache a PHP Základy PHP Funkce Pole Objektově orientované programování v PHP Vyspělé schopnosti OOP Zpracování chyb a výjimek Řetězce a regulární výrazy Práce se systémem souborů a s operačním systémem PEAR Datum a čas Formuláře a navigační pomůcky Autentizace Upload souborů Networking PHP a LDAP Zpracovatelé sezení Šablony se Smarty Webové služby Bezpečné programování v PHP SQLite Úvod do PDO Úvod do MySQL Instalace a konfigurace MySQL Klienti MySQL Ukládací enginy MySQL a datové typy Zabezpečení MySQL Rozšíření mysql v PHP Rozšíření mysqli v PHP Uložené rutiny Triggery MySQL Pohledy Databázové dotazy v praxi Indexy a vyhledávání Transakce Import a export dat Rejstřík
31 39 69 115 127 153 177 197 211 247 277 289 319 341 359 373 409 431 451 475 515 533 551 569 579 603 625 655 681 709 733 755 767 779 801 817 831 845
Obsah O autorovi O odborném recenzentovi Poděkování
25 25 26
Pošlete nám váš názor Zdrojové soubory Úvod
27 27 29
Kapitola 1
Úvod do PHP
Historie PHP 4 PHP 5
31 31 32 34
Všeobecné rysy jazyka Upotřebitelnost Vyspělost Možnosti
35 35 36 36
Cena Shrnutí
37 37
Kapitola 2
Instalace a konfigurace Apache a PHP
39
Instalace Obstaráme si distribuce Proces instalace Otestování instalace Přizpůsobení vybudované distribuce pro Unix Přizpůsobení vybudované distribuce pro Windows Běžné potíže Prohlížení a stažení dokumentace
39 39 41 46 47 47 48 48
Konfigurace Správa konfiguračních direktiv PHP Konfigurační direktivy PHP Shrnutí
49 49 51 68
Kapitola 3
Základy PHP
Únik k PHP Výchozí syntax Krátké značky Styl <script>
69 69 70 70 71
8
Obsah Styl ASP Vkládání několika bloků kódu
71 71
Komentáře Syntax jediného řádku z C++ Syntax shellu Komentář na několika řádcích ve stylu C
72 72 72 72
Výstup print() echo() printf() sprintf()
73 73 74 74 75
Typy dat Skalární datové typy Složené datové typy Resource Přetypování Žonglování s typy Funkce vztahující se k typům
76 76 77 79 80 81 82
Identifikátory Proměnné Deklarace proměnné Obor proměnné Superglobální proměnné PHP Proměnné proměnné
83 84 84 85 88 93
Konstanty Výrazy Operandy Operátory
93 94 94 94
Interpretace řetězců Uvozovky Apostrofy heredoc
100 100 101 102
Řídící struktury Příkazy, které řídí vykonávání Podmínkové příkazy Příkazy cyklu Příkazy pro vkládání souborů
102 103 104 106 111
Shrnutí
113
Velká kniha PHP a MySQL 5
Kapitola 4
9
Funkce
115
Volání funkcí Vytvoření funkce Předávání argumentů hodnotou Předávání argumentů odkazem Výchozí hodnoty argumentů Nepovinné argumenty Návratové hodnoty funkcí Vracení více hodnot najednou Vnořování funkcí Rekurzivní funkce Funkce jako proměnná
115 116 116 117 118 118 119 120 120 121 123
Knihovny funkcí Shrnutí
124 125
Kapitola 5
Pole
127
Co je pole? Výstup polí Jak se vytvoří pole Test, zda se jedná o pole
128 129 130 132
Přidávání a odstraňování prvků pole Vyhledávání prvků v poli
133 134
Procházení polí Zjištění velikosti a jedinečných hodnot pole Setřídění prvků polí Kombinace, sloučení, extrakce a porovnání Další užitečné funkce pro práci s poli Shrnutí
136 140 141 146 150 152
Kapitola 6
Objektově orientované programování v PHP
153
Zisky plynoucí z OOP Zapouzdření Dědění Polymorfizmus
154 154 155 155
Klíčové pojmy OOP Třídy Objekty Členské proměnné
156 156 157 157
10
Obsah Vlastnosti Konstanty Metody
160 163 163
Rada pro typ Konstruktory a destruktory Konstruktory Destruktory
167 168 168 171
Statické členy tříd Klíčové slovo instanceof Pomocné funkce Automatické načítání objektů Shrnutí
172 173 173 175 176
Kapitola 7
Pokročilé schopnosti OOP
177
Schopnosti OOP nepodporované v PHP Klonování objektů Příklad klonování Metoda _ _clone()
178 178 178 180
Dědění Dědění třídy Dědění a konstruktory
181 181 183
Rozhraní Dědění jednoho rozhraní Implementace více rozhraní
185 186 187
Abstraktní třídy Reflexe Shrnutí
188 189 195
Kapitola 8
Zpracování chyb a výjimek
197
Konfigurační direktivy Protokolování chyb Zpracování výjimek Proč je zpracování výjimek prospěšné Implementace zpracování výjimek v PHP
198 201 203 203 205
Shrnutí
209
Kapitola 9
Řetězce a regulární výrazy
Syntaxe se složenými závorkami {}
211 211
Velká kniha PHP a MySQL 5
11
Regulární výrazy Syntax regulárních výrazů ve stylu POSIX Syntax regulárních výrazů ve stylu Perlu
212 213 218
Další funkce pro práci s řetězci Určování délky řetězce Porovnávání dvou řetězců Úpravy velikosti písmen Převádění řetězců do HTML a z HTML Alternativy pro funkce regulárních výrazů Doplňování a zkracování řetězce Počítání znaků a slov
225 226 226 228 229 234 241 242
Využití předností balíku Validate_US PEAR Instalace balíku Validate_US Jak se používá balík Validate_US
244 245 245
Shrnutí
246
Kapitola 10 Práce se systémem souborů a s operačním systémem
247
Soubory a adresáře Analýza cest k adresářům Typy souborů a odkazy Zjišťování velikosti souboru, adresáře a disku Časy posledního přístupu a modifikace
248 248 250 253 256
Vlastnictví souborů a povolení Vstupní a výstupní (I/O) operace se soubory Pojem prostředek Znak pro nový řádek Konec souboru Otevření a uzavření souboru Čtení ze souboru Přesouvání ukazatele souboru Zapisování do souboru Čtení obsahu adresářů
257 259 259 260 260 260 262 267 268 268
Vykonávání příkazů shellu Vykonávání programů na systémové úrovni Shrnutí
270 271 275
Kapitola 11 PEAR Populární balíky PEAR Konverze číselných formátů
277 277 279
12
Obsah Instalace a aktualizace PEAR Instalace PEAR PEAR a hostitelské firmy Aktualizace PEAR
280 280 282 282
Jak se pracuje s manažerem balíků PEAR Jaké balíky jsou nainstalované Jak získáte další informace o nainstalovaném balíku Instalace balíku Jak se pracuje s balíkem Modernizace balíku Odinstalování balíku Přechod na starší verzi balíku
282 283 283 284 286 287 287 288
Shrnutí
288
Kapitola 12 Datum a čas
289
Časová známka Unixu Knihovna PHP pro datum a čas Bojové umění „Date Fu“ Zobrazení lokalizovaného data a času Zobrazení data poslední modifikace webové stránky Zjištění počtu dní aktuálního měsíce Určení data vzdáleného x dní od aktuálního data Vytvoření kalendáře
289 290 297 297 301 301 302 303
PHP 5.1 Základní informace o Date Konstruktor Date Accessory a mutátory Validátory Manipulační metody
306 307 307 308 311 311
Shrnutí
317
Kapitola 13 Formuláře a navigační pomůcky PHP a webové formuláře Jednoduchý příklad Předávání dat formuláře do funkce Práce s vícehodnotovými komponentami formuláře Generování formulářů s PHP Automatický výběr na formuláři PHP, webové formuláře a JavaScript
319 320 320 321 322 324 326 327
Velká kniha PHP a MySQL 5
13
Navigační pomůcky Uživatelsky přívětivé URL Navigační stopy Vytváření vlastních zpracovatelů chyb
329 329 333 337
Shrnutí
339
Kapitola 14 Autentizace
341
Pojmy autentizace HTTP Autentizace PHP Proměnné autentizace Různé metodologie autentizace Autentizace založená na IP adrese Využití PEAR: Auth_HTTP
341 342 343 344 348 349
Administrace přihlašování uživatelů Ustanovení hesel Testování jak snadno lze uhádnout heslo s knihovnou CrackLib Jednorázové URL a obnova hesla
352 352 354 356
Shrnutí
358
Kapitola 15 Upload souborů
359
Nahrávání souborů přes protokol HTTP Nahrávání na server s PHP Direktivy PHP pro nahrávání souborů a pro prostředky Pole $_FILES Funkce PHP pro nahrávání na server Chybové zprávy týkající se nahrávání Ukázky nahrávání souborů
359 360 360 362 363 364 365
Dejte přednost PEAR: HTTP_Upload Instalace HTTP_Upload Získáme informace o nahraném souboru Přesun nahraného souboru na cílové umístění Nahrávání více souborů najednou
368 368 369 370 370
Shrnutí
371
Kapitola 16 Networking DNS, služby a servery DNS Služby
373 374 374 377
14
Obsah Zřizování soketových připojení
378
Pošta Konfigurační direktivy Odeslání e-mailu, který obsahuje jen čistý text Odeslání e-mailu s dodatečnými záhlavími Odeslání e-mailu více příjemcům Odeslání e-mailu formátovaného jako HTML Jak se odešle příloha
380 380 381 382 382 383 384
IMAP, POP3 a NNTP Požadavky Zřízení a uzavření připojení Další informace o poštovních přihrádkách a poště Získávání zpráv Sestavení zprávy Odeslání zprávy Administrace poštovní přihrádky Administrace zpráv
385 385 386 388 390 397 398 398 400
Proudy Obaly proudů a kontexty Filtry proudů
400 401 402
Běžné síťové úkoly Zvonění na server Skener portu Konvertor podsítě Testování šířky pásma uživatele
404 404 405 405 407
Shrnutí
408
Kapitola 17 PHP a LDAP
409
Úvod do LDAP Další informace o LDAP
410 411
PHP a LDAP Připojení k serveru LDAP Vázání k serveru LDAP Uzavření připojení k serveru LDAP Získávání dat LDAP Práce s hodnotami položek Počet získaných položek Získávání atributů Řazení a porovnávání položek LDAP
411 411 412 413 414 415 416 417 420
Velká kniha PHP a MySQL 5 Práce s položkami Dealokace paměti Vkládání dat LDAP Aktualizace dat LDAP Odstraňování dat LDAP Konfigurační funkce Znakové sady Práce s distingovaným názvem Zpracování chyb Shrnutí
Kapitola 18 Zpracovatelé sezení
15 421 423 424 425 426 426 428 428 429 430
431
Co je to zpracování sezení? Cookies Přepisování URL Proces zpracování sezení
431 432 432 432
Konfigurační direktivy Klíčové pojmy Startování sezení Likvidace sezení Získávání a nastavování ID sezení Vytváření a odstraňování proměnných sezení Zakódování a dekódování dat sezení
433 438 438 439 439 440 440
Praktické ukázky zpracování sezení Automatizované přihlašování Seznam naposled prohlížených dokumentů
442 442 444
Vytváření vlastních zpracovatelů sezení Včlenění vlastních funkcí sezení do logiky PHP Vlastní zpracovatelé sezení založení na MySQL
445 446 447
Shrnutí
450
Kapitola 19 Šablony se Smarty Co je stroj na šablony? Úvod do Smarty Instalace Smarty Práce se Smarty Prezentační logika Smarty Komentáře
451 452 453 454 456 458 458
16
Obsah Modifikátory proměnné Řídící struktury Speciální příkazy
458 461 465
Vytváření konfiguračních souborů Odkazy na konfigurační proměnné
468 469
CSS v součinnosti se Smarty Ukládání stránek do cache Doba života stránek uložených v cache Eliminace režijních nákladů na zpracování s is_cached() Vytvoření několika cache pro jednu šablonu Několik slov závěrem k ukládání do cache
470 471 472 472 473 474
Shrnutí
474
Kapitola 20 Webové služby
475
Proč webové služby? Real Simple Syndication Syntax RSS MagpieRSS
476 478 480 481
SimpleXML Funkce SimpleXML Metody SimpleXML
488 489 490
SOAP NuSOAP Rozšíření SOAP PHP 5
493 494 503
Použití klienta C# s webovou službou PHP Shrnutí
512 514
Kapitola 21 Bezpečné programování v PHP
515
Bezpečná konfigurace PHP Bezpečný mód Další konfigurační direktivy vztahující se bezpečnému módu
516 516 518
Skrývání podrobností konfigurace Skrytí Apache a PHP
520 520
Skrývání citlivých dat Dbejte řádně o kořen dokumentů Zamítněte přístup k souborům s určitými příponami
522 522 523
Desinfekce dat uživatele Vymazání souborů
523 524
Velká kniha PHP a MySQL 5 Skriptování přes weby Desinfekce vstupu od uživatele: řešení
17 524 526
Šifrování dat Šifrovací funkce PHP mhash MCrypt
528 528 529 530
Shrnutí
532
Kapitola 22 SQLite
533
SQLite Instalace SQLite Práce v rozhraní příkazového řádku SQLite
533 534 534
Knihovna SQLite PHP Direktivy SQLite Jak se otevře připojení Vytvoření tabulky v paměti Uzavření připojení Dotazy na databázi Analýza sad výsledků Získávání podrobností o sadě výsledků Manipulace s ukazatelem sady výsledků Informace o struktuře tabulky Práce s binárními daty Vytváření a překrývání funkcí SQLite Vytváření agregačních funkcí
536 536 536 537 538 538 539 542 544 545 546 547 548
Shrnutí
549
Kapitola 23 Úvod do PDO Zase další databázová abstraktní vrstva? Jak se pracuje s PDO Instalace PDO Podpora databází v PDO Připojení k databázovému serveru a výběr databáze Získávání a nastavování atributů Zpracování chyb Vykonání dotazu Připravené příkazy Získávání dat Nastavování vázaných sloupců
551 552 553 554 554 555 557 557 558 560 564 567
18
Obsah Transakce Shrnutí
Kapitola 24 Úvod do MySQL
568 568
569
Proč je MySQL tak populární? Flexibilita Výkon Flexibilní licenční možnosti (Hyper) aktivní komunita uživatelů
569 570 570 572 573
MySQL 4 MySQL 5 Prominentní uživatelé MySQL craigslist Yahoo! Finance Wikipedia
574 575 575 575 576 576
Shrnutí
577
Kapitola 25 Instalace a konfigurace MySQL
579
Licence PHP a MySQL Linux Windows
579 580 580
Stažení MySQL Instalace MySQL Linux Windows
580 582 582 586
Nastavte heslo administrátora MySQL Start a zastavení MySQL Ruční ovládání démona Automatické startování a zastavování MySQL
589 589 589 591
Konfigurace a optimalizace MySQL mysqld_safe Konfigurační a optimalizační parametry Soubor my.cnf
594 594 595 599
Shrnutí
602
Kapitola 26 Klienti MySQL
603
Standardní volby klientů Volby týkající se připojení
603 604
Velká kniha PHP a MySQL 5
19
Všeobecné volby mysql Klíčové volby mysql Práce s mysql v interaktivním režimu Prohlížení konfiguračních proměnných a stavu systému Práce s mysql v dávkovém režimu Užitečné tipy k mysql
605 605 606 608 610 611 612
mysqladmin Příkazy mysqladmin
614 614
Další utility mysqldump mysqlshow mysqlhotcopy mysqlimport myisamchk mysqlcheck
615 615 616 616 617 618 619
Klientské programy jiných výrobců Administrátor MySQL phpMyAdmin Prohlížeč dotazů MySQL Navicat
619 619 621 622 624
Shrnutí
624
Kapitola 27 Ukládací enginy MySQL a datové typy
625
Ukládací enginy InnoDB MyISAM MEMORY MERGE BDB FEDERATED ARCHIVE CSV EXAMPLE BLACKHOLE Časté otázky týkající se ukládacích enginů
625 626 627 629 631 631 631 633 633 634 634 634
Datové typy a atributy Datové typy Datové typy pro datum a čas
636 636 636
20
Obsah Datové typy pro řetězce Atributy datových typů
640 642
Práce s databázemi a s tabulkami Práce s databázemi Práce s tabulkami Změny ve struktuře tabulky Databáze INFORMATION_SCHEMA
645 645 647 650 650
Shrnutí
653
Kapitola 28 Zabezpečení MySQL
655
Co byste měli udělat nejdřív Zabezpečení démona mysqld Systém přístupových oprávnění MySQL Jak systém přístupových oprávnění funguje Kde jsou informace o přístupových oprávněních uložené?
656 657 657 657 659
Správa uživatelů a přístupových oprávnění Prohlížení oprávnění
668 675
Limity na konzumaci prostředků uživateli Bezpečná připojení MySQL Volby příkazu GRANT, které se týkají bezpečných připojení Volby SSL
675 676 677 678
Shrnutí
680
Kapitola 29 Rozšíření mysql v PHP
681
Předběžné informace Jak se zpřístupní rozšíření mysql na Linuxu Jak se zpřístupní rozšíření mysql na Windows Přístupová oprávnění uživatelů Ukázková data
681 681 682 682 682
Příkazy MySQL v PHP Zřízení a uzavření připojení Uložení informací o připojení do separátního souboru Zabezpečení informací o připojení
683 683 685 685
Volba databáze Dotazy na MySQL Získávání a zobrazování dat Vkládání dat Modifikace dat
686 686 688 691 693
Velká kniha PHP a MySQL 5
21
Odstraňování dat Vybrané řádky a ovlivněné řádky Získávání informací o databázi a tabulce Získávání informací o sloupcích Prohlížení vlastností tabulky Získávání informací o chybách
695 696 697 698 702 703
Pomocné funkce Shrnutí
704 707
Kapitola 30 Rozšíření mysqli v PHP
709
Předběžné informace Jak se zpřístupní rozšíření mysqli na Unixu Jak se zpřístupní rozšíření mysqli na Windows Ukázková data
710 710 710 711
Jak se pracuje s rozšířením mysqli Připojení k serveru MySQL Zprávy o chybách připojení Výběr databáze MySQL Uzavření připojení
711 711 712 715 716
Dotazy Vykonání dotazu Zotavení paměti dotazu Příprava sady výsledků pro zpracování Analýza výsledků Vykonávání několika dotazů za sebou Připravené příkazy
716 716 718 718 720 723 724
Databázové transakce Shrnutí
731 732
Kapitola 31 Uložené rutiny
733
Měli bychom používat uložené rutiny? Přednosti uložených rutin Nevýhody uložených rutin
734 734 734
Jak MySQL implementuje uložené rutiny Tabulky přístupových oprávnění uložených rutin Jak se vytvoří uložená rutina Deklarace a nastavování proměnných Jak se vykoná uložená rutina
735 735 737 739 741
22
Obsah Uložené rutiny složené z několika příkazů Volání rutiny z jiné rutiny Modifikace uložené rutiny Odstranění uložené rutiny Prohlížení stavu rutiny Prohlížení syntaxe rutiny Podmínky a zpracovatelé
741 748 749 749 750 751 751
Integrace rutin do webových aplikací Vytvoření rozhraní pro bonus zaměstnanců Získávání více řádků
752 752 753
Shrnutí
753
Kapitola 32 Triggery MySQL
755
Úvod do triggerů Proč používat triggery? Vykonání akce před událostí Vykonání akce po události Triggery spouštěné „před“ versus triggery spouštěné „po“
755 756 756 757 758
Podpora triggerů v MySQL Jak se vytvoří trigger Prohlížení existujících triggerů Modifikace triggeru Odstranění triggeru Kaskádové triggery
758 759 761 762 762 763
Integrace triggerů do webových aplikací Shrnutí
764 766
Kapitola 33 Pohledy
767
Úvod do pohledů Podpora pohledů v MySQL Vytváření a vykonávání pohledů Prohlížení informací o pohledu Modifikace pohledu Odstranění pohledu Aktualizace pohledů
768 768 769 774 776 776 776
Začlenění pohledů do webových aplikací Shrnutí
777 778
Velká kniha PHP a MySQL 5
Kapitola 34 Databázové dotazy v praxi
23
779
Ukázková data Vytváření tabulárních výstup s PEAR Instalace HTML_Table Jak se vytvoří jednoduchá tabulka Vytváření lépe čitelného výstupu řádků Vytvoření tabulky z dat databáze Zobecnění výstupního procesu
780 780 781 781 782 784 785
Seřazení výstupu Vytvoření výstupu se stránkováním Číslování stránek výpisu Poddotazy Porovnávací operace s poddotazy Určování existence s poddotazy Údržba databáze pomocí poddotazů Používání poddotazů v PHP
787 788 791 793 794 794 796 796
Kurzory Základy práce s kurzory Vytvoření kurzoru Otevření kurzoru Práce s kurzorem Uzavření kurzoru Jak se kurzor používá s PHP
797 797 798 798 798 799 799
Shrnutí
800
Kapitola 35 Indexy a vyhledávání
801
Indexování databází Primární klíče Jedinečné indexy Normální indexy Fulltextové indexy Doporučené praktiky pro práci s indexy
801 802 803 804 806 810
Vyhledávání pomocí formuláře Jednoduché hledání Rozšíření vyhledávacích možností Fulltextové vyhledávání
811 811 812 814
Shrnutí
815
24
Obsah
Kapitola 36 Transakce
817
Co je transakce? Možnosti MySQL pro transakční zpracování Systémové požadavky Vytvoření tabulky Konfigurační parametry InnoDB
817 818 818 819 819
Ukázkový projekt Ukázková data Vykonáme konkrétní transakci Zálohování a obnova tabulek InnoDB Tipy pro práci s transakcemi
822 822 823 825 825
Budování transakčních aplikací s PHP Směna zboží za hotové ještě jednou
826 826
Shrnutí
830
Kapitola 37 Import a export dat
831
Ukázková tabulka Touha po inteligentním médiu Export dat Příkaz SELECT INTO OUTFILE
831 832 832 833
Import dat Import dat příkazem LOAD DATA INFILE Import dat s mysqlimport Načítání dat do tabulky s PHP
836 836 839 842
Shrnutí
843
Rejstřík
845
Kapitola 2
Instalace a konfigurace Apache a PHP V této kapitole se dozvíte, jak se nainstaluje a nakonfiguruje PHP, a v průběhu tohoto procesu se dozvíte, jak nainstalovat webový server Apache. Jestliže doposud nemáte k dispozici fungující server Apache/ PHP, je látka probíraná zde pro vás neocenitelná, abyste totiž mohli pracovat s příklady v pozdějších kapitolách, o vašich vlastních experimentech nemluvě. Konkrétně se v této kapitole dozvíte
• Jak se nainstaluje Apache a PHP jako modul serveru Apache, a to na dvou platformách, Unix i Windows.
• • • •
Jak otestujete svou instalaci, abyste se přesvědčili, že všechny komponenty pracují řádně. O běžných instalačních potížích a jak se řeší. Jaký mají účel, obor a výchozí hodnoty běžně používané konfigurační direktivy PHP. Různé způsoby, jimiž lze modifikovat konfigurační direktivy PHP.
Instalace V tomto oddílu projdeme všechny potřebné kroky k instalaci funkčního serveru Apache/PHP. Důsledkem bude, že budete moci na serveru spouštět skripty PHP a prohlížet jejich výsledky v prohlížeči.
Obstaráme si distribuce Než začnete s instalací, musíte stáhnout zdrojový kód. V tomto oddílu dostanete pokyny, jak to udělat.
Stažení Apache Popularita Apache a licence otevřeného zdrojového kódu podnítily prakticky všechny vývojáře Unixu, aby zabalili tento software do svých distribucí. Vzhledem ke svižnému rozvrhu nových vydání Apache se však musíte obrátit na webové stránky Apache a stáhnout nejnovější verzi. V době, kdy jsem psal tyto řádky, se na následující stránce nabízelo 260 zrcadel umístěných v 53 zemích světa: http://www.apache.org/mirrors
40
Kapitola 2 – Instalace a konfigurace PHP
Přejděte na tuto stránku a zvolte vhodné zrcadlo tím, že kliknete na patřičný odkaz. Výsledná stránka bude obsahovat všechny projekty kryté deštníkem Apache Software Foundation. Zvolte odkaz httpd. Tím přejdete na stránku obsahující odkazy na nejnovější vydání Apache a r ůzné k nim s e vztahující projekty a utility. Distribuce je dostupná ve dvou formátech:
• Zdrojový (source). Je-li vaší cílovou platformou Unix, doporučuji, abyste si stáhli zdrojový kód. Přestože jistě není nic špatného na tom, když využijete některou ze skvostně vybudovaných binárních verzí, čas navíc, který budete investovat, abyste se naučili kompilovat ze zdrojového kódu, vám v dlouhodobé perspektivě poskytne větší flexibilitu. Je-li vaší cílovou platformou systém Windows, a rádi byste kompilovali ze zdrojového kódu, lze stáhnout separátní zdrojové balení pro platformu Win32. Připomínám však, že se v kapitole neprobírá proces instalace pro platformu Win32 ze zdrojového kódu. Soustředíme se na mnohem běžnější (a doporučovaný) binární instalátor.
• Binární (binary). V době, kdy jsem psal tyto řádky, byly binární distribuce k dispozici pro 15
operačních systémů. Je-li vaší cílovou platformou systém Windows, doporučuje se, abyste si stáhli relevantní binární verzi. Na ostatních platformách zvažte kompilaci ze zdrojového kódu, protože v dlouhodobé perspektivě poskytne větší flexibilitu.
Poznámka V době, kdy jsem psal tyto řádky, nebyla ještě k dispozici binární verze Apache 2 s podporou SSL, přestože je možné, že v době, kdy tyto řádky čtete vy, je už situace jiná. Jestliže ale ne a vy požadujete na Windows podporu SSL, budete muset budovat ze zdrojového kódu.
Takže, kterou verzi Apache byste si měli stáhnout? Přestože byl Apache 2 vydán už před více než třemi lety, stále se všeobecně používá verze 1.X. Skutečně, zdá se, že většinu ISP sdílených serverů teprve čeká migrace k verzi 2.X. Neochota modernizovat nemá nic společného s problémy týkajícími se verze 2.X, spíše je to důkaz báječné stability a vyspělosti verze 1.X. Při standardním používání jsou vnější rozdíly mezi oběma verzemi prakticky nezjistitelné; proto uvažujte o práci s Apache 2 tehdy, potřebujete-li využívat jeho zdokonalenou stabilitu. Skutečně, hodláte-li provozovat Apache pod Windows, buď pro vývojové, nebo pro rozmisťovací účely, doporučuje se, abyste zvolili verzi 2, protože byla oproti předchozí distribuci Windows kompletně přepsána a je signifikantně stabilnější než její předchůdkyně.
Stažení PHP Přestože je v dnešní dob ě už PHP do v ětšiny distribucí Linuxu zabudovaný, doporučuje se, abyste si z webových stránek PHP stáhli nejnovější stabilní (stable) verzi. Abyste zkrátili dobu stahování, zvolte příhodné zrcadlo z více než sta zrcadel sídlících ve více než padesáti zemích. Seznam zrcadel najdete na adrese http://www.php.net/mirrors.php. Jakmile zvolíte nejbližší zrcadlo, přejděte na stránku, ze které se stahuje (downloads) a zvolte vhodný formát. Celkem jsou tři:
• Zdrojový (source). Je-li vaší cílovou platformou Unix, nebo hodláte kompilovat ze zdroje na
platformě Windows, zvolte zdrojový formát. Budování ze zdrojového kódu na Windows se nedoporučuje a v knize se tím nezabývám. Pokud se nenacházíte v situaci s opravdu velmi speci-
Velká kniha PHP a MySQL 5
41
álními okolnostmi, měla by vašim potřebám uspokojivě vyhovovat předem vybudovaná binární distribuce pro Windows. Tato distribuce je komprimovaná ve formátech bz2 a gz. Uvědomte si ale, že jejich obsah je identický; různé komprimační formáty jsou tu jen pro vaše pohodlí.
• Windows zip package. Distribuce obsahuje binární CGI a různé verze modulu serveru. Plánuje-
te-li využívat PHP v součinnosti s Apache, měli byste stáhnout tuto verzi, protože k ní se vztahují pozdější instalační pokyny uvedené v knize.
• Windows Installer. Distribuce obsahuje pouze CGI a nabízí pohodlné rozhraní instalačního
programu pro Windows, v němž nainstalujete a nakonfigurujete PHP. Obsahuje také podporu pro automatickou konfiguraci serverů IIS, PWS a Xitami. Přestože můžete tuto verzi používat v součinnosti s Apache, nedoporučuje se to. Použijte místo ní verzi Windows zip package.
Chcete-li si pohrát s nejnovějšími vývojovými fázemi PHP, můžete si na adrese http://snaps.php.net stáhnout zdrojovou i binární verzi. Mějte na paměti, že některé z verzí, které jsou dostupné přes tento web, nejsou určené pro rutinní provoz.
Proces instalace Protože se kapitola soustřeďuje především na PHP, ne na s erver Apache, vyčerpávající (ale i ú vodní) výklad všech možných schopností, které jsou během procesu budování Apache k dispozici, přesahuje rámec této kapitoly. Potřebujete-li dodatečné informace týkající se těchto schopností, doporučuji vám, abyste nějaký čas věnovali studiu dokumentace Apache, nebo si obstarejte publikaci Pro Apache, Third Edition, napsal Peter Wainwright, vydalo Apress 2004.
Poznámka Licenční konflikty mezi PHP a MySQL měly za následek, že byly knihovny MySQL z PHP 5 odstraněny. Proto, chcete-li používat PHP 5 a MySQL pospolu (což je dost pravděpodobné, když čtete tuto knihu), musíte podniknout patřičné kroky, abyste pro PHP 5 zpřístupnili knihovny MySQL. Tato látka se podrobněji probírá v kapitole 25. V ní si také určitě pročtěte informace, které se vztahují k různým licenčním scénářům, chcete-li používat PHP a MySQL dohromady
Instalace Apache a PHP na Linuxu/Unixu Na Unixu vybudujeme Apache a PHP ze zdrojového kódu. Potřebujete slušný kompilátor ANSI-C a systém, dva prvky, jejichž dostupnost je dnes p ro drtivou většinu distribucí samozřejmostí. PHP kromě toho vyžaduje balíky Flex (http://www.gnu.org/software/flex/flex.html) a Bison (http://www. gnu.org/software/bison/bison.html), Apache vyžaduje Perl alespoň verze 5.003. Opět všechny tři prvky jsou běžně rozšířené, když ne na vš ech, tak na většině moderních platformách Unix. Konečně potřebujete oprávnění úrovně root k cílovému serveru, abyste byli sto proces budování dokončit. Než zahájíte proces instalace, zvažte, zda byste neměli kvůli většímu pohodlí umístit oba balíky na společné místo, například /usr/src/. Pak začněte s instalací podle následujících pokynů. 1. Rozbalte Apache a PHP (operace gunzip a tar):
42
Kapitola 2 – Instalace a konfigurace PHP %>gunzip httpd-2_X_XX.tar.gz %>tar xvf httpd-2_X_XX.tar %>gunzip php-XX.tar.gz %>tar xvf php-XX.tar.
2. Zkonfigurujte a vybudujte Apache. Předat je třeba minimálně dvě volby. První z nich, --enable-so, sdděluje Apache, aby zapnul schopnost načítat sdílené moduly. Druhá, --with-mpm=worker, sděluje Apache, aby použil vícevláknový modul paralelního zpracování (threaded multiprocessing module), známý jako zpracovatelský proces (worker). Na základě svých konkrétních potřeb zvažte, zda byste neměli také používat modul prefork paralelního zpracování. Další informace týkající se této důležité záležitosti si vyhledejte v dokumentaci Apache. %>cd httpd-2_X_XX %>./configure --enable-so [další volby] %>make
3. Nainstalujte Apache: %>make install
4. Zkonfigurujte, vybudujte a nainstalujte PHP (informace ohledně modifikací výchozích instalačních hodnot a začlenění rozšíření cizích výrobců do PHP viz oddíly „Přizpůsobení vybudované instalace pro Unix“, resp. „Přizpůsobení vybudované instalace pro Windows, podle toho, pod jakým operačním systémem pracujete). %>cd ../php-X_XX %>./configure --with-apxs2=/usr/local/apache2/bin/apxs [další volby] %>make %>make install
Upozornění Verze PHP pro Unix se spoléhá na několik utilit, bez nichž se řádně nezkompiluje. Proces konfigurace se proto nezdaří, jestliže nejsou přítomné na serveru. Zmínit je třeba především to, že tato balení obsahují Bison parser generator, Flex lexical analysis generator, GCC compiler collection a m4 macro processor. Bohužel, četné distribuce je automaticky nenainstalují, takže je nezbytné ručně tyto balíky přidat v době, kdy se instaluje operační systém, nebo před instalací PHP. Proto, objeví-li se nějaké chyby týkající se zmíněných balíků, mějte na paměti, že je to zcela typické, a podnikněte nezbytné kroky, abyste je nainstalovali na váš systém.
5. Zkopírujte soubor php.ini-dist na jeho výchozí umístění a přejmenujte na php.ini. je hlavní konfigurační kanál. Účel a obsah php.ini podrobně prozkoumáme v příštím oddílu, „Konfigurace“. Soubor php.ini obsahuje stovky direktiv, jimiž se přizpůsobuje chování PHP. V pozdějším oddílu „Konfigurace“ prozkoumáme podrobně účel a obsah php.ini. Připomínám, že tento konfigurační soubor můžete umístit, kamkoli chcete, zvolíte-li však nějaké nestandardní umístění, budete muset také nakonfigurovat PHP pomocí volby --with-config-filepath. Dál připomínám, že máte k dispozici ještě jeden konfigurační soubor, který se jmenuje
Kapitola 3
Základy PHP Máme za sebou pouhé dvě kapitoly, a už jsme p robrali poměrně dost základních informací o jazyku PHP. Seznámili jste se s pozadím a historií vzniku jazyka a hluboko jste se zavrtali do pojmů a postupů souvisejících s instalací a konfigurací. Tím jste si vytvořili dobrou výchozí pozici k tomu, co je jádrem zbývající části knihy: vytváření vyspělých aplikací PHP. Jejich výklad teď začíná, uvádí se v něm mnoho základních schopností jazyka. Konkrétně se budou probírat následující témata:
• Jak se odděluje kód PHP, což umožňuje enginu pro analýzu určit, které oblasti skriptu má analyzovat, a které má ignorovat.
• Jak se do kódu vkládají komentáře pomocí různých metodologií, které jsou vypůjčené ze skriptování shellu Unixu a jazyků C a C++.
• Jak dostanete data na výstup pomocí příkazů echo(), print(), printf() a sprintf(). • Výklad typů dat PHP, proměnných, operátorů a příkazů. • Podrobné pojednání o klíčových řídících strukturách a příkazech PHP: if-else-elseif, while, foreach, include/require, break, continue a declare.
V kapitole si osvojíte nejen vědomosti nezbytné k tomu,k abyste mohli vytvářet sice jen zák ladní, ale přesto prospěšné aplikace PHP. Pochopíte také to, co vám umožní vytěžit co nejvíce z lá tky probírané v následujících kapitolách.
Únik k PHP Jednou z předností PHP je, že jeho k ód můžete vkládat přímo do statických stránek HTML. Aby ale kód mohl něco dělat, musí se stránka předat enginu PHP, který ji bude interpretovat. Při interpretaci kódu by ale bylo hodně neefektivní, kdyby se měl každý řádek brát jako potenciální příkaz PHP. Proto parser potřebuje nějaké prostředky, aby mohl okamžitě určit, které oblasti na stránce představují kód PHP. To se logicky docílí tím, že s e kód PHP oddělí. Existují čtyři varianty, jak lze k ód oddělit. Jejich popis následuje.
70
Kapitola 3 – Základy PHP
Výchozí syntax Výchozí syntax oddělení kódu začíná znaky <?php a končí znaky ?>, jako zde: <h3>Vítejte!</h3> <?php print "<p>Tohle je ukázka PHP.</p>"; ?> <p>Zde se nacházejí nějaké statické informace...</p>
Uložíte-li kód uvedený výše jako test.php a zavoláte ho z nějakého webového serveru, který má zapnutou podporu PHP, uvidíte výstup jako na obrázku 3-1:
Obrázek 3-1 Ukázka výstupu PHP
Krátké značky Pro lenochy je k dispozici ještě kratší syntax oddělovačů. Říká se jí krátký styl značek (short-tags). Obejde se bez odkazu php, který vyžaduje výchozí syntax. Chcete-li ale p oužívat krátké značky, musíte zapnout direktivu short_open_tag PHP. Příklad: <? print "Tohle je další ukázka PHP."; ?>
Upozornění Přestože jsou krátké značky pohodlné, mějte na paměti, že kolidují s XML, a tedy i se syntaxí XHTML. Proto se kvůli souladu doporučuje, abyste používali výchozí syntax..
Velká kniha PHP a MySQL 5
71
Informace se obvykle zobrazují příkazy print nebo echo. Když jsou zapnuté krátké značky, můžete se bez těchto příkazů obejít, a využít variantu výstupu známou jako zkrácená výstupní syntax: <?="Tohle je další ukázka PHP.";?>
Což je funkčně ekvivalentní oběma následujícím variantám: <? print "Tohle je další ukázka PHP."; ?> <? php print "Tohle je další ukázka PHP";?>
Styl <script> Z historických příčin měly některé editory, konkrétně editor FrontPage společnosti Microsoft, potíže s únikovou syntaxí, kterou se obracíme na PHP. Proto byla do PHP začleněna ještě jedna varianta oddělovací syntaxe, <script>: <script language="php"> print "Tohle je další ukázka PHP."; </script>
Tip Editor FrontPage společnosti Microsoft rozpoznává oddělovací syntax ve stylu ASP, která následuje.
Styl ASP Stránky ASP společnosti Microsoft používají obdobnou strategii. Také oddělují statickou syntax od dynamické pomocí předem definovaného vzorku znaků. Dynamická syntax se uvozuje znaky <% a ukončuje znaky %>. Přicházíte-li z krajiny ASP a rádi byste i nadále používali tuto syntax, PHP ji podporuje. Podívejte se na ukázku: <% print "Tohle je další ukázka PHP."; %>
Vkládání několika bloků kódu Na PHP se můžete obracet na dané stránce kolikrát, kolikrát jenom chcete. Například, následující ukázka je formálně zcela v pořádku: <html> <head> <title><?php echo "Vítejte na mém webu!";?></title> </head> <body> <?php $date = "18. září 2004"; ?>
72
Kapitola 3 – Základy PHP
<h3>Dnes je </body> </html>
<?=$date;?></h3>
Připomínám, že jakékoli proměnné, které se deklarují před blokem kódu, se „zapamatují“ pro potřeby následných bloků, což je v našem příkladu případ proměnné $date.
Komentáře Zdůraznit, jak je důležité prokládat kód pečlivými komentáři, není nikdy zbytečné. PHP pro komentáře nabízí několik syntaktických variant, jejichž popis následuje.
Syntax jediného řádku z C++ Pro komentář často stačí jediný řádek. Protože je komentář krátký, není třeba ho ukončovat speciálním ukončovacím oddělovačem, protože tuto roli uspokojivě zvládne znak pro nový řádek (\n). PHP podporuje jednořádkové komentáře ve stylu C++, které jsou uvozené dvěma lomítky (//), jako zde: <?php // Titulek: Můj program PHP // Autor: Jason print "Tohle je program PHP"; ?>
Syntax shellu PHP také podporuje alternativu k syntaxi ve stylu C++, které se říká syntax shellu. Komentář je uvozen znakem hash (#). Předchozí ukázka pak vypadá takto: <?php # Titulek: Můj program PHP # Autor: Jason print "Tohle je program PHP"; ?>
Komentář na několika řádcích ve stylu C Často je žádoucí vložit obšírnější popis, jak daná část kódu funguje, nebo jiné poznámky ke kódu. Takové vysvětlení se obvykle na jediný řádek nevejde. Přestože byste mohli postupovat tak, že byste každý řádek zahájili oddělovači ve stylu C++ nebo shellu, nabízí PHP pohodlnější variantu s uvozovacím a ukončovacím oddělovačem komentáře. Podívejte se na několikařádkový komentář: <?php /* Titulek: Můj program PHP Autor: Jason
Velká kniha PHP a MySQL 5
73
Datum: 10. října 2005 */ ?>
Syntax komentáře na několika řádcích se hodí zejména tehdy, když z kódu generujete dokumentaci, protože nabízí možnost, jak odlišit skutečné komentáře od okomentovaného kódu, což není tak snadné, jako když se používá jednořádková syntax komentářů.
Výstup Většina webových aplikací je značně interaktivních. Dobře napsané skripty trvale komunikují s uživateli, a to přes nástroje rozhraní, i prostřednictvím odpovědí na požadavky. PHP nabízí pro zobrazování informací řadu prostředků, jejichž popis následuje.
print() boolean print(argument print(argument) )
Účelem příkazu print je poskytnout uživateli zpětnou vazbu. Umí zobrazit prosté řetězce i obsah proměnných. Všechny následující příkazy jsou akceptovatelné příkazy print: <?php print("<p>Zbožňuji léto.</p>"); ?> <?php $obdobi = "léto"; print "<p> Zbožňuji $obdobi.</p>"; ?> <?php print "<p> Zbožňuji léto.</p>"; ?> <?php $obdobi = "léto"; print "<p> Zbožňuji ".$obdobi.".</p>"; ?>
Všechny příkazy vypíší: Zbožňuji léto.
Zatímco tři první varianty jsou patrně velmi snadno pochopitelné, poslední z nich tak zřejmá být nemusí. V poslední variantě jsem totiž zřetězil tři řetězce do jediného pomocí tečky, která slouží v tomto kontextu jako operátor řetězení. Je to technika, která se běžně používá při řetězení proměnných, konstant a statických řetězců. S uvedenou strategií se budete průběžně setkávat na různých místech knihy.
74
Kapitola 3 – Základy PHP
Poznámka Přestože nás oficiální syntax vybízí, abychom argument dávali do závorek, máte možnost je vynechat. Mnozí programátoři je neuvádějí prostě proto, že je cílový argument zřejmý i bez nich. .
echo() void echo(string argument1 [, ...string argumentN])
Příkaz echo funguje obdobně jako print, ale se dvěma odlišnostmi. Zaprvé nemůže být částí složitějšího výrazu, protože vrací void, zatímco print vrací hodnotu typu boolean. Zadruhé echo umí vypsat několik řetězců. Prospěšnost té druhé vymoženosti je problematická, vypadá to, že je to více než cokoli jiného, jen otázka osobních preferencí. Nicméně je k dispozici, pokud pocítíte neodolatelnou potřebu ji použít. Tady máte ukázku: <?php $heavyweight = "Lennox Lewis"; $lightweight = "Floyd Mayweather"; echo $heavyweight, " a ", $lightweight, " jsou skvělí bojovníci."; ?>
Kód vyprodukuje následující výstup: Lennox Lewis a Floyd Mayweather jsou skvělí bojovníci.
Tip Co je rychlejší, echo() nebo print()? To, že jsou funkčně zaměnitelné, způsobuje, že si mnozí kladou tuto otázku. Odpověď zní, že funkce echo() je nepatrně rychlejší, protože nic nevrací, kdežto print() vrací booleovskou hodnotu, kterou informuje volajícího, zda příkaz zvládl výstup úspěšně, nebo ne. Je zcela nepravděpodobné, že byste si všimli nějakého rozdílu v rychlosti, takže se můžete rozhodnout podle toho, co vám více vyhovuje stylisticky.
printf() boolean printf (string format [, mixed args args]) ])
Funkce printf() je funkčně identická s print(). Jde o výstup argumentů specifikovaných v args, ale výstup se naformátuje podle format. To umožňuje získat značnou kontrolu nad výstupem dat, pokud jde o takové věci, jako jsou zarovnání, přesnost, typ či pozice. Argument se může skládat až z pěti komponent, které se musejí ve format objevit ve stanoveném pořadí:
• Specifikátor doplnění: volitelná komponenta, která určuje, jakým znakem se výstup doplní na
správnou délku řetězce. Výchozí znak je mezera. Alternativní znak se specifikuje tak, že se před něj napíše apostrof.
• Specifikátor zarovnání: volitelná komponenta, která určuje, zda má být výstup zarovnaný
doleva nebo doprava. Výchozí je doprava. Zarovnání vlevo vynutíte tím, že uvedete znaménko minus.
Velká kniha PHP a MySQL 5
75
• Specifikátor délky: volitelná komponenta, která určuje minimální počet znaků, který má výstup z funkce obsahovat.
• Specifikátor přesnosti: volitelná komponenta, která určuje, kolik se má zobrazit desetinných míst. Má vliv pouze na data typu float.
• Specifikátor typu: určuje, jak se argument přetypuje. Podporované specifikátory typu jsou uvedené v tabulce 3-1.
Tabulka 3-1. Podporované specifikátory typu. Typ
Popis
%b
Argument se považuje za celé číslo, zobrazí se jako binární číslo.
%c
Argument se považuje za celé číslo, zobrazí se znak odpovídající dané hodnotě ASCII.
%d
Argument se považuje za celé číslo, zobrazí se jako dekadické číslo se znaménkem.
%f
Argument se považuje za číslo v pohyblivé řádové čárce a tak se také zobrazí.
%o
Argument se považuje za celé číslo, zobrazí se jako oktalové číslo.
%s
Argument se považuje za řetězec, zobrazí se jako řetězec.
%u
Argument se považuje za celé číslo, zobrazí se jako dekadické číslo bez znaménka.
%x
Argument se považuje za celé číslo, zobrazí se jako hexadecimální číslo s malými písmeny.
%X
Argument se považuje za celé číslo, zobrazí se jako hexadecimální číslo s velkými písmeny
Podívejte se na několik ukázek: printf("$%01.2f", 43.2); // $43.20 printf("%s je %d lahví piva", "Ve sklepě", 100); // Ve sklepě je 100 lahví piva printf("%15s", "Nějaký text"); // Nějaký text
Někdy se hodí změnit výstupní pořadí argumentů, nebo zopakovat výstup některého konkrétního argumentu, aniž byste ho museli opakovaně uvádět v seznamu argumentů. To se dělá tak, že se odkážete na argument, a zároveň na jeho pozici. Například, %2$ vyjadřuje argument umístěný v seznamu argumentů na druhé pozici, zatímco %3$ vyjadřuje třetí. Když to však umístíte do řetězce format, musíte před znak dolar uvést obrácené lomítko, například %2\$. Dvě ukázky: printf("Náš %2\$s rád %1\$s", "štěká", "pes"); // Náš pes rád štěká printf("Náš %1\$s říká: %2\$s, %2\$s.", "pes", "haf"); // Náš pes říká: haf, haf.
sprintf() string sprintf (string format [, mixed arguments arguments]) ])
Funkce sprintf() se funkčně shoduje s printf() až na to, že se výstup přiřadí do řetězce, nejde přímo na standardní výstup. Ukázka: $cena = sprintf("$%01.2f", 43.2); // $cena = $43.20
76
Kapitola 3 – Základy PHP
Typy dat Datový typ je obecný název přiřazený nějaké množině dat, která sdílí nějakou společnou množinu charakteristik. Mezi běžné datové typy patří řetězce, celá čísla, čísla v pohyblivé řádové čárce a booleovské hodnoty. PHP už dlo uho nabízí bohatou sadu datových typů. K nim p řibyly ve verzi 5 další. V tomto oddílu projdu jednotlivé datové typy, které lze všechny rozdělit do tří kategorií: skalární, složené a speciální.
Skalární datové typy Skalární datové typy mohou obsahovat jen jediný prvek informace. Sem spadá několik datových typů: boolean, integer, float a string.
Boolean Datový typ boolean se jmenuje po matematikovi George Booleovi (1815–1864), který je pokládám za jednoho ze zakladatelů teorie informace. Booleovská proměnná reprezentuje pravdivost, a podporuje tedy pouze dvě hodnoty: TRUE (pravda) nebo FALSE (nepravda); na velikosti písmen nezáleží. Alternativou je reprezentovat FALSE hodnotu nula, a TRUE reprezentovat jakoukoli nenulovou hodnotou. $jenazivu $jenazivu $jenazivu $jenazivu $jenazivu
= = = = =
false; 1; -1; 5; 0;
# # # # #
$jenazivu $jenazivu $jenazivu $jenazivu $jenazivu
je je je je je
false. true. true. true. false.
Integer Typ integer vyjadřuje prostě celé číslo, neboli takové číslo, které nemá desetinnou část. Sem spadají čísla dekadická (o základu 10), oktalová (o základu 8) a hexadecimální (o základu 16). Několik ukázek: 42 -678900 0755 0xC4E
# # # #
dekadické dekadické oktalové hexadecimální
Jaké je největší podporované celé číslo, závisí na platformě, i když obvykle je to plus nebo minus 231. Pokusíte-li se tento limit v nějakém skriptu PHP překročit, převede se takové číslo automaticky do pohyblivé řádové čárky (na float). Ukázka: <?php $val = 45678945939390393678976; echo $val + 5; ?>
Výsledek bude: 4.567894593939E+022
Kapitola 7
Pokročilé schopnosti OOP V kapitole 6 jste absolvovali základy objektově orientovaného programování v PHP. V této kapitole budeme na těchto základech stavět. Seznámíte se s několika vyspělejšími schopnostmi OOP, které byste si měli zařadit do svého repertoáru hned poté, co budete mít v malíku základy. Konkrétně se v kapitole hovoří o pěti schopnostech:
• Klonování objektů. Jedním z hlavních zdokonalení modelu OOP v PHP verze 5 je to, že se
všechny objekty považují za odkazy, ne za hodnoty. Jak se pak ovšem vypořádáme s úlohou vytvořit kopii objektu, když se všechny objekty považují za odkazy? Klonováním objektu, což je nová schopnost v PHP 5.
• Dědění. Jak už bylo zmíněno v kapitole 6, je schopnost budovat hierarchie tříd prostřednictvím dědění klíčovým pojmem OOP. Dozvíte se, co je to dědění, jakou má v PHP 5 syntax, a uvidíte několik příkladů, které předvádějí tuto klíčovou schopnost OOP.
• Rozhraní. Rozhraní je nějaká kolekce neimplementovaných definic metod a konstant. Slouží
jako jistý náčrt třídy. Rozhraní přesně definují, co se může ve třídě dělat, ale nezatěžují se konkrétními podrobnostmi implementace. V této kapitole se dozvíte, jakou podporu poskytuje PHP 5 pro rozhraní, a uvidíte také několik příkladů, které předvádějí tuto klíčovou schopnost OOP.
• Abstraktní třídy. Abstraktní třída je v podstatě taková třída, ze které se nedají vytvářet instance.
Účelem abstraktních tříd je to, aby se z nich odvozovaly třídy, jejichž instance se už dají vytvářet (říká se jim někdy konkrétní třídy). Abstraktní třídy lze implementovat plně, nebo implementovat jen částečně, nebo neimplementovat vůbec. V této kapitole se uvádějí všeobecné pojmy, které se točí okolo abstraktních tříd spolu s úvodem, jak se abstraktní třídy implementují v PHP 5.
• Reflexe. Jak jste se dozvěděli v kapitole 6, skrývání „odpudivých“ podrobností aplikace přívěti-
vými rozhraními (zapouzdření) je jedním z hlavních pilířů OOP. Nicméně programátoři ovšem potřebují nějaké pohodlné prostředky, jimiž se dá prozkoumávat chování třídy. Tuto schopnost poskytuje pojem reflexe, který se zde vysvětluje.
178
Kapitola 7 – Pokročilé vlastnosti OOP
Schopnosti OOP nepodporované v PHP Máte-li zkušenosti s jinými objektově orientovanými jazyky, možná p o přečtení výše uvedeného seznamu nespokojeně potřásáte hlavou, a p táte se, proč v něm c hybí jedna neb o několik konkrétních schopností OOP, které důvěrně znáte z jiných jazyků. Je docela dobře možné, že je to kvůli tomu, že PHP tuto schopnost nepodporuje. Takže abyste si hlavu úplně nevyviklali z pantů, jsou v následujícím výčtu uvedena ta vyspělá témata OOP, která PHP nepodporuje, a proto jejich výklad v kapitole nenajdete.
• Jmenné prostory (namespace). Přestože byly původně do PHP 5 naplánované, od začlenění
jmenných prostorů bylo brzo upuštěno. Není jasné, zda bude podpora jmenných prostorů integrována do nějaké budoucí verze.
• Přetěžování metod (overloading). Možnost docílit polymorfického účinku prostřednictvím přetěžování funkcí PHP nepodporuje a podle diskuse na webových stránkách Zend Technologies, patrně ani nikdy podporovat nebude. Více se o tom můžete dozvědět na adrese http://www. zend.com/php/ask_experts.php.
• Přetěžování operátorů. Možnost přiřadit dodatečné významy stávajícím operátorům na základě typu dat, která se pokoušíte modifikovat, zatím není na pořadu dne. Podle výše zmíněné diskuse na webu Zend Technologies, není pravděpodobné, že by se tato schopnost někdy v budoucnu implementovala.
• Vícenásobné dědění. PHP nepodporuje vícenásobné dědění. Implementace více rozhraní se však podporuje.
Jen čas ukáže, budou-li se v budoucnu některé z těchto schopností v PHP podporovat.
Klonování objektů Jednou z nejv ětších stinných stránek objektově orientovaných schopností PHP 4 b yla skutečnost, že zacházel s objekty jako s jinými datovými typy. Tato praxe byla překážkou využití mnohých běžných metodologií OOP, jako jsou návrhové vzory. Takové metodologie závisejí na možnosti předávat objekty do jiných metod třídy odkazem, ne hodnotou, což byla výchozí praktika v PHP. Naštěstí byla tato záležitost v PHP 5 vyřešena, a nyní se standardně se všemi objekty zachází jako s odkazy. Protože se ale nyní se všemi objekty zachází jako s odkazy, ne jako s hodnotami, je zase obtížnější udělat kopii objektu. Pokusíte-li se zkopírovat odkazovaný objekt, bude prostě ukazovat zpět na adresované umístění původního objektu. PHP se s tím vypořádal tak, že nabízí explicitní prostředek pro klonování objektu.
Příklad klonování Klon objektu vytvoříte tak, že před ním uvedete klíčové slovo clone, jako zde: cílový_objekt = clone zdrojový_objekt zdrojový_objekt; ;
Vyčerpávající příklad klonování objektu nabízí výpis 7-1. V p říkladu jsem vytvořil ukázkovou třídu s názvem parazitFirmy, která obsahuje dva členy (idZamestnance a barvaKravaty), a jejich odpovídající gettery a settery. V příkladu se vytvoří instance parazitFirmy a použije se jako základna pro předvedení, jaké účinky má operace klonování.
Velká kniha PHP a MySQL 5 Výpis 7-1. Klonování objektu pomocí klíčového slova clone <?php class parazitFirmy { private $idZamestnance ; private $barvaKravaty; // Definuje setter a getter pro $idZamestnance function nastavitIdZamestnance ($idZamestnance ) { $this->idZamestnance = $idZamestnance ; } function ziskatIdZamestnance() { return $this->idZamestnance ; } // Definuje setter a getter pro $barvaKravaty function nastavitBarvuKravaty ($barvaKravaty) { $this->barvaKravaty = $barvaKravaty; } function ziskatBarvuKravaty() { return $this->barvaKravaty; } } // Vytvoří nový objekt parazita firmy $parazit1 = new parazitFirmy(); // Nastaví člen idZamestnance parazita 1 $parazit1->nastavitIdZamestnance ("12345"); // Nastaví člen barvaKravaty parazita 1 $parazit1->nastavitBarvuKravaty ("červená"); // Vytvoří klon parazita 1 $parazit2 = clone $parazit1; // Nastaví člen idZamestnance parazita 2 $parazit2->nastavitIdZamestnance ("67890"); // Výstup členů prvního a druhého parazita echo "parazit1 id zaměstnance: ".$parazit1->ziskatIdZamestnance ()."<br />"; echo "parazit1 barva kravaty: ".$parazit1->ziskatBarvuKravaty()."<br />"; echo "parazit2 id zaměstnance: ".$parazit2->ziskatIdZamestnance ()."<br />"; echo "parazit2 barva kravaty: ".$parazit2->ziskatBarvuKravaty()."<br />"; ?>
179
180
Kapitola 7 – Pokročilé vlastnosti OOP
Když kód spustíte, vrátí: parazit1 id zaměstnance: 12345 parazit1 barva kravaty: červená parazit2 id zaměstnance: 67890 parazit2 barva kravaty: červená
Jak vidíte, $parazit2 se stal objektem typu parazitFirmy a zdědil hodnoty členů z $parazit1. Aby se zdůraznilo, že je $parazit2 opravdu typu parazitFirmy, nastavil se znovu i jeho člen idZamestnance.
Metoda _ _clone() Při klonování objektu si dokonce můžete přizpůsobit chování tohoto procesu, když si ve třídě objektu definujete metodu _ _clone(). Kromě toho, že se do cílového objektu zkopírují všechny existující členy objektu, vykoná se také vše, co je umíst ěné v této metodě. Upravte třídu parazitFirmy tak, že do ní přidáte metodu: function _ _clone() { $this->barvaKravaty = "modrá"; }
Až s tím budete hotovi, vytvořte nový objekt parazitFirmy, přidejte hodnotu členu idZamestnance, udělejte klon objektu, a nakonec vypište potřebná data, abyste si ověřili, že se barvaKravaty klonovaného objektu skutečně nastavila prostřednictvím metody _ _clone(). Příklad vidíte ve výpisu 7-2. Výpis 7-2. Rozšíření možností klíčového slova clone metodou _ _clone() // Vytvoří objekt nového parazita firmy $parazit1 = new parazitFirmy(); // Nastaví člen idZamestnance parazita 1 $parazit1->nastavitIdZamestnance ("12345"); // Vytvoří klon objektu $parazit1 $parazit2 = clone $parazit1; // Nastaví člen idZamestnance parazita 2 $parazit2->nastavitIdZamestnance ("67890"); // Výstup členů obou parazitů echo "parazit1 id zaměstnance: ".$parazit1->ziskatIdZamestnance ()."<br />"; echo "parazit2 id zaměstnance: ".$parazit2->ziskatIdZamestnance ()."<br />"; echo "parazit2 barva kravaty: ".$parazit2->ziskatBarvuKravaty()."<br />";
Když kód vykonáte, vypíše: parazit1 id zaměstnance: 12345 parazit2 id zaměstnance: 67890 parazit2 barva kravaty: modrá
Velká kniha PHP a MySQL 5
181
Dědění Lidé mají docela dobrou výbavu pro uvažování v takových termínech, jakým je třeba uspořádaná hierarchie, proto není nijak překvapující, že je takové nahlížení na správu mnoha aspektů našeho každodenního života široce rozšířené. Struktury managementu firmy, daňový systém Spojených Států, i náš pohled na říše rostlin a živočichů, to je jen několik příkladů systémů, které se převážně spoléhají na hierarchie. Protože je objektově orientované programování založeno na premise, že my lidé dokážeme velmi dobře modelovat vlastnosti a c hování prostředí skutečného světa, které se snažíme implementovat pomocí kódu, dá se z toho rozumně usoudit, že jsme také schopni znázorňovat tyto hierarchické vztahy. Předpokládejme například, že vaše aplikace potřebuje třídu nazvanou Zamestnanec, jejíž účelem má být reprezentace charakteristik a chování, jaká člověk může očekávat od nějakého zaměstnance. Mezi členy takové třídy by mohly patřit
• • • •
jmeno: jméno zaměstnance vek: věk zaměstnance plat: plat zaměstnance zamestnan_let: počet let, které daný zaměstnanec u firmy pracuje.
Mezi metody třídy Zamestnanec by mohly patřit:
• • •
vykonatPraci: vykoná nějakou práci související se zadaným úkolem. snistObed: vezme si přestávku na oběd. vzitDovolenou: týká se nejcennějších týdnů v roce.
Tyto charakteristiky a chování budou relevantní pro všechny druhy zaměstnanců, bez ohledu na účel nebo pozici zaměstnance v organizaci. Je zřejmé, že budou mezi zaměstnanci také jisté rozdíly; například, pracovník exekutivy může mít v držení jist é akcie firmy, a bude sto společnost tunelovat, zatímco jiní zaměstnanci takové výdobytky nemají. Sekretářka musí umět napsat dopis a vedoucí prodejny musí umět udělat inventuru. Navzdory těmto rozdílům by ale bylo velmi neefektivní, kdybyste museli vytvářet a udržovat redundantní struktury tříd pro ty atributy, které sdílejí všichni zaměstnanci. Vývoj schematu OOP to bere v úvahu. Umožňuje dědit z existujících tříd a dále na nich budovat.
Dědění třídy V PHP se dědění třídy dociluje klíčovým slovem extends .Předvádí je výpis 7-3, kde se nejprve definuje třída Zamestnanec, pak se vytvoří třída Vedouci, která bude dědit ze třídy Zamestnanec.
Poznámka Třídě, která dědí z jiné třídy, se říká dceřiná (child) třída, podtřída nebo odvozená třída. Dceřiná třída dědí ze své rodičovské (parent), neboli základní (base) třídy.
182
Kapitola 7 – Pokročilé vlastnosti OOP
Výpis 7-3. Dědění ze základní třídy <?php # Definuje třídu Zamestnanec class Zamestnanec { private $jmeno; # Definuje funkci set vlastnosti pro soukromý člen $jmeno. function nastavitJmeno($jmeno) { if ($jmeno == "") echo "Jméno nesmí zůstat prázdné!"; else $this->jmeno = $jmeno; } # Definuje funkci get vlastnosti pro soukromý člen $jmeno function ziskatJmeno() { return "Jmenuji se ".$this->jmeno."<br />"; } } #konec třídy Zamestnanec # Definuje třídu Vedouci, která bude dědit z třídy Zamestnanec class Vedouci extends Zamestnanec { # Definuje metodu jedinečnou pro Zamestnanec function tunelovatFirmu() { echo "Prodám aktiva firmy, abych mohl financovat svou jachtu!"; } } #konec třídy Vedouci # vytvoří nový objekt Vedouci $exec = new Vedouci(); # zavolá metodu nastavitJmeno(), která je definovaná ve třídě Zamestnanec $exec->nastavitJmeno("Richard"); # Zavolá metodu ziskatJmeno() echo $exec->ziskatJmeno(); # zavolá metodu tunelovatFirmu() $exec->tunelovatFirmu(); ?>
Kód vrátí Jmenuji se Richard. Prodám aktiva firmy, abych mohl financovat svou jachtu!
Kapitola 23
Úvod do PDO Počet dostupných softwarových řešení je zároveň požehnáním i prokletím. I když je jejich nadbytečná hojnost skvělá pro konečné uživatele, protože si mohou vyhledat takový produkt, který nejlépe vyhovuje jejich konkrétním potřebám, už dlouho je prokázané, že je to noční můra pro vývojáře a systémové administrátory, protože se od nich požaduje, aby dva nebo více odlišných produktů transparentně vzájemně komunikovaly. I když to, že se ctí různé standardy, jako je třeba XML, značně přispívá v úsilí o interoperabilitu, jsme stále roky vzdáleni od nějakého obecně akceptovatelného řešení. Tento problém se projeví zvlášť velmi zřetelně tehdy, když aplikace požadují jako datovou základnu nějakou databázi. Zatímco všechny hlavní databáze ctí standard SQL, přestože s různými odchylkami, rozhraní, na nichž jsou závislí programátoři, chtějí-li s databází komunikovat, mohou být značně odlišná (dokonce i tehdy, když jsou dotazy z valné části stejné). Proto bývají aplikace téměř vždy svázané s nějakou konkrétní databází, čímž nutí uživatele, aby si také nainstalovali a udržovali tu hlavní databázi, pokud ji ještě nevlastní. Nebo musejí zvolit alternativní, nějaké patrně méně vyspělé řešení, které bude kompatibilní s jejich stávajícím prostředím. Předpokládejme například, že vaše organizace požaduje aplikaci, která se bude provozovat výlučně na Oracle, ale vaše organizace je přitom standardizovaná na nějakou databázi open-source. Odhodláte se investovat značné prostředky, které bude nutno vložit do nákupu nezbytných licencí Oracle, jste ochotni udržovat tuto databázi jen kvůli tomu, aby se mohla provozovat jedna jediná konkrétní aplikace? Aby se programátoři velkých korporací nějak s t ěmito dilematy vypořádali, začali vyvíjet abstraktní databázové vrstvy, které mají sloužit k tomu, aby se mohla oddělit logika aplikace od logiky komunikace s databází. Když se všechny příkazy související s databází mohou prohnat nějakým ze všeobecněným rozhraním, může pak aplikace používat jedno z několika databázových řešení, za předpokladů, že daná databáze podporuje schopnosti, které aplikace požaduje, a že abstraktní vrstva nabízí ovladač kompatibilní s danou databází. Graficky je popisovaný proces znázorněn na obrázku 23-1. Patrně už něco víte o některých rozšířenějších implementacích, z nichž několik je uvedeno v následujícím výčtu:
• DB: DB je databázová abstraktní vrstva napsaná v PHP a k dispozici jako balík PEAR. (Další
informace o PEAR viz kapitola 11.) V současné době podporuje FrontBase, InterBase, Informix, Mini SQL, MySQL, Oracle, ODBC, PostgreSQL, SQLite a Sybase.
552
Kapitola 23 – Úvod do PDO
Obrázek 23-1 Oddělení aplikačních a datových vrstev pomocí abstraktní databázové vrstvy
• JDBC: jak název implikuje, umožňuje standard Java Database Connectivity (JDBC) programá-
torům Javy komunikovat s jakoukoli databází, pro kterou je k dispozici ovladač JDBC. Patří sem mj. MSSQL, MySQL, Oracle a PostgreSQL.
• ODBC: rozhraní Open Database Connectivity (ODBC) je v současnosti jedna z nejrozšířeněj-
ších abstraktních implementací, podporuje ji široká škála aplikací a jazyků, včetně PHP. ovladače ODBC nabízejí všechny hlavní databáze, mezi nimi také ty, které jsou uvedené v odrážce JDBC výše.
• Perl DBI: modul Perl Database Interface je standardizovaný prostředek Perlu pro komunikaci s databází, a sloužil jako inspirace při tvorbě balíku DB PHP.
Jak vidíte, mají uživatelé PHP p o ruce řešení DB i ODBC, proto se může zdát, že js ou vaše potřeby vyřešené, co se týče databázové abstrakce, vyvíjíte-li aplikace poháněné PHP, není-liž pravda? I když jsou tato (a mnohá jiná) řešení hotová a po ruce, už nějakou dobu se vyvíjí ještě lepší řešení, které bylo oficiálně vydané s PHP 5.1. Je známé jako abstraktní vrstva PDO (PHP Data Objects).
Zase další databázová abstraktní vrstva? Jak PDO v posledních dvou letech dozrával, dost okolo toho hudrali vývojáři, kteří buď byli zainteresováni ve vývoji nějakých jiných databázových abstraktních vrstev, nebo patrně byli příliš soustředěni na schopnosti databázové abstraktní vrstvy PDO, než na celou paletu vybavení, které nabízí. Skutečně, PDO poslouží jako ideální náhrada balíku DB a obdobných řešení. PDO je však ve skutečnosti mnohem dál, není to jen pouhá další databázová abstraktní vrstva:
• Konsistentní kódování: protože různá databázová rozšíření, která jsou k dispozici pro PHP, psali různí hostující přispěvovatelé, neexistuje jednotnost v kódování, navzdory faktu, že všechna tato rozšíření nabízejí v zásadě stejné schopnosti. PDO tuto nejednotnost odstraňuje, protože nabízí jediné rozhraní, které se používá vždy, bez ohledu na to, o jakou databázi se jedná. Navíc
Velká kniha PHP a MySQL 5
553
rozšíření je rozděleno do dvou zřetelně vymezených komponent: jádro PDO obsahuje většinu kódu specifického pro PHP, takže se jednotlivé ovladače mohou soustředit výhradně na data. Dále, vývojáři PDO využili svých vědomostí a zkušeností při budování různých databázových rozšíření v posledních letech, takže mohli těžit z toho, co se osvědčilo, to zařadili, a zároveň se pečlivě vystříhali toho, aby zařazovali něco, co se neosvědčilo.
• Flexibilita: protože PDO načítá potřebný databázový ovladač až při běhu, není třeba překonfigurovat a překompilovat PHP pokaždé, když se používá jiná databáze. Například potřebujete-li náhle přejít z Oracle na PostgreSQL, prostě načtěte ovladač PDO_PGSQL a pracujte (jak se to udělá, o tom více později).
• Objektově orientované schopnosti: PDO využívá objektově orientovaných schopností PHP, což vede na vyspělejší a efektivnější databázovou komunikaci.
• Výkon: PDO je napsaný v C a vkompilovaný do PHP, což samo o sobě, budou-li všechny ostatní faktory rovnocenné, poskytuje značný nárůst výkonu oproti řešením napsaným v PHP.
Vzhledem k t ěmto přednostem, proč to nezkusit? V této kapitole se dostatečně obeznámíte s PD O a s myriádami schopností, které nabízí.
Jak se pracuje s PDO PDO se až p ozoruhodně podobá všem databázovým rozšířením, která už dlo uhou dobu podporuje PHP; proto, jestliže jste už používali PHP v součinnosti s nějakou databází, bude vám látka prezentovaná v tomto oddílu připadat důvěrně známá. Jak už bylo zmíněno, PDO byl vybudován tak, že jeho tvůrci měli stále na mysli ty nejlepší schopnosti předchozích databázových rozšíření, takže není divu, že v jeho metodách najdete značné podobnosti s tím, co už zn áte. Oddíl zahájíme stručným přehledem procesu instalace PDO, pak následuje přehled databázových serverů, které se podporují v současné době. V příkladech kapitoly budeme používat následující tabulku MySQL: CREATE TABLE product ( rowid SMALLINT NOT NULL AUTO_INCREMENT, sku CHAR(8) NOT NULL, name VARCHAR(35) NOT NULL, PRIMARY KEY(rowid) );
Poznámka překladatele SKU je zkratka Stock Keeping Unit, v online obchodování jednoznačný identifikátor výrobku na skladě nebo v katalogu
Tabulku naplňte dále uvedenými výrobky: rowID 1
SKU ZP457321
Name Painless Aftershave
2 3 4
TY232278 PO988932 KL334899
AquaSmooth Toothpaste HeadsFree Shampoo WhiskerWrecker Razors
554
Kapitola 23 – Úvod do PDO
Instalace PDO Jak už bylo zmíněno, je PDO standardně zabalený do PHP 5.1 a no vějších verzí, takže provozujete-li tuto verzi, nemusíte podnikat vůbec žádné další kroky. Pracujete-li s nějakou verzí starší než 5.1, i t ak můžete pracovat s PDO, když si ho stáhnete z PECL; protože však PDO využívá plně nových objektově orientovaných schopností PHP 5, není možné ho používat v součinnosti s verzí, která je starší než 5.0. Ale ať je to tak či onak, když konfigurujete PHP, musíte přesto explicitně specifikovat ovladače, které chcete zařadit (výjimkou je ovladač SQLITE, který je zařazený standardně). Například chcete-li zapnout podporu ovladače MySQL PDO,přidejte do příkazu configure následující přepínač: --with-pdo-mysql=/cesta/k/instalaci/mysql
Potřebujete-li se dozvědět víc o jednotlivých ovladačích PDO, vydejte příkaz configure --help. Pracujete-li s PHP 5.1 nebo novější verzí na platformě Windows, tak v době, kdy jsem psal tyto řádky, nebyly ovladače začleněné do distr ibuce. Proto přejděte na http://snaps.php.net/win32/, zadejte patřičný adresář PECL a stáhněte si DLL PDO do adresáře, který máte vyznačený v direktivě extension_dir PHP. Pak musíte přidat odkazy na ovladače rozšíření do souboru php.ini. Například chcete-li zapnout podporu MySQL, přidejte do sekce Windows Extensions řádek: extension=php_pdo_mysql.dll
Podpora databází v PDO Když jsem psal tyto řádky, podporoval PDO devět databází kromě všech těch, které jsou přístupné přes FreeTDS a ODBC:
• Firebird: přístupná přes ovladač FIREBIRD. • FreeTDS: to není databáze, ale sada knihoven Unixu, které umožňují programům založených na Unixu hovořit s databázemi MSSQL a Sybase. Přístupná přes ovladač DBLIB.
• • • •
IBM DB2: přístupná přes ovladač ODBC. Interbase 6: přístupná přes ovladač FIREBIRD. Microsoft SQL Server: přístupná přes ovladač MSSQL. MySQL 3.X/4.0: přístupná přes ovladač MYSQL. Připomínám, že v době, kdy jsem psal tyto řádky, nebylo dostupné rozhraní pro MySQL 5. Protože je jasné, že je to v seznamu priorit vývojářů hodně vysoko, bude to patrně brzy vyřešeno.
• ODBC v3: není databáze sama o sobě, ale umožňuje PDO používat v součinnosti s jakoukoli databázi kompatibilní s ODBC, která není uvedena v tomto seznamu. Přístupná přes ovladač ODBC.
• • • •
Oracle: přístupná přes ovladač OCI. PostgreSQL: přístupná přes ovladač PGSQL. SQLite 3.X: přístupná přes ovladač SQLITE. Sybase: přístupná přes ovladač SYBASE.
Velká kniha PHP a MySQL 5
555
Tip Které ovladače PDO máte dostupné ve svém prostředí můžete zjistit tak, že si v prohlížeči zobrazíte výstup z phpinfo() a podíváte se do sekce PDO. Nebo zavolejte funkci pdo_drivers(), jako zde: <?php print_r(pdo_drivers()); ?>.
Připojení k databázovému serveru a výběr databáze Než můžete začít komunikovat s databází přes PDO, musíte zřídit připojení k serveru a vybrat databázi. Udělá se to konstruktorem PDO. Jeho prototyp vypadá takto: PDO PDO::_ _construct(string DSN [, string username [, string password [, array driver_opts driver_opts]]]) ]]])
Parametr DSN (Data Source Name) se skládá ze dvou prvků: název požadovaného databázového ovladače a vš echny nezbytné proměnné databázového připojení, jako jsou název hostitele, port a náze v databáze. Parametry username a passw ord specifikují uživatelské jméno a heslo , které se použijí při připojení k databázi. Konečně, pole driver_opts specifikuje jakékoli další volby, které by se mohly požadovat nebo jsou žádoucí pro připojení. Seznam dostupných voleb je uveden na konci tohoto oddílu. Konstruktor lze volat několika způsoby, které si teď uvedeme.
Vložíte parametry do konstruktoru Při prvním způsobu volání konstruktoru PDO se parametry vloží přímo. Například byste ho mo hli zavolat třeba takto (jedná se konkrétně o databázi MySQL): $dbh = new PDO("mysql:host=localhost;dbname=corporate", "websiteuser", "secret");
Umístíte parametry do souboru PDO využívá schopnost PHP pracovat s proudy, což otevírá možnost umístit řetězec DSN do s eparátního souboru, který bude na nějakém místním nebo vzdáleném umístění. Na něj se pak odkážete v konstruktoru, jako zde: $dbh = new PDO("uri:file://usr/local/mysql.dsn");
Zajistěte ale, aby soubor vlastnil stejný uživatel, který vykonává skript PHP, a aby tento uživatel měl udělena patřičná přístupová oprávnění.
Odkážete se na soubor php.ini Je také možné udržovat informace o DSN v souboru php.ini, když je přiřadíte do konfiguračního parametru pdo.dsn.aliasname, kde aliasname je zvolené alias pro DSN, které následně dodáte do konstruktoru. Například v následující ukázce je alias DSN mysqlpdo: [PDO] pdo.dsn.mysqlpdo = "mysql:dbname=corporate;host=localhost"
Alias pak následně uvedete ve volání konstruktoru PDO, jako v: $dbh = new PDO("mysqlpdo", "websiteuser", "secret");
Podobně jako v předchozím způsobu, ani tento neumožňuje zařadit do DSN uživatelské jméno a heslo.
556
Kapitola 23 – Úvod do PDO
Volby PDO vztahující se k připojení Existuje několik voleb vztahujících se k připojení, jimiž můžete připojení přizpůsobit svým potřebám. Předávají se v poli driver_opts. Dostupné volby jsou uvedené v následujícím výčtu:
•
PDO_ATTR_AUTOCOMMIT: určuje, zda bude PDO potvrzovat změny hned po vykonání každého
•
PDO_ATTR_CASE: PDO můžete donutit, aby převáděl získané názvy sloupců na samé velká nebo na samá malá písmena, nebo aby používat názvy sloupců přesně v tom tvaru, v jakém jsou v databázi. Volba se nastavuje na jednu ze tří hodnot: PDO_CASE_UPPER, PDO_CASE_LOWER a PDO_CASE_NATURAL.
•
PDO_ATTR_ERRMODE: PDO podporuje tři módy oznamování chyb, PDO_ERRMODE_EXCEPTION,
dotazu, nebo zda bude čekat, až se vykoná metoda commit().
PDO_ERRMODE_SILENT a PDO_ERRMODE_WARNING. Určují, za jakých okolností PDO oznámí chybu. Volba se nastavuje na jednu ze tří výše uvedených hodnot, výchozí chování je PDO_ERRMODE_EXCEPTION. Tato volba se probírá podrobněji v pozdějším oddílu “Zpracování chyb”.
•
PDO_ATTR_ORACLE_NULLS: je-li nastavena na TRUE, způsobí, že se budou získané prázdné řetězce převádět na NULL. Výchozí hodnota je FALSE.
• •
PDO_ATTR_PERSISTENT: určuje, zda je připojení trvalé. Výchozí hodnota je FALSE.
•
PDO_ATTR_TIMEOUT: tato volba nastavuje dobu v sekundách, po kterou se bude čekat, než se
PDO_ATTR_PREFETCH: jedná se o databázovou schopnost, při které se získává několik řádků,
i když klient požaduje v daném okamžiku jen jeden řádek, a to na základě filozofie, že pokud klient požádal o jeden řádek, je pravděpodobné, že bude postupně žádat ještě o další. To snižuje počet požadavků obracejících se na databázi a zvyšuje efektivitu. Volba nastavuje velikost získávané sady v kilobajtech, u těch ovladačů, které tuto schopnost podporují. skončí.
Další čtyři atributy umožňují dozvědět se dodatečné informace o klientovi, serveru a o stavu připojení. Hodnoty těchto atributů lze získat metodou getAttribute(), která se probírá v pozdějším oddílu “Získávání a nastavování atributů”.
•
PDO_ATTR_SERVER_INFO: obsahuje specifické informace o databázovém serveru. V případě MySQL jsou to data vztahující se k době provozu serveru, kolik bylo celkem dotazů, průměrný počet vykonaných dotazů za sekundu a další důležité informace.
• • •
PDO_ATTR_SERVER_VERSION: obsahuje informace o čísle verze databázového serveru. PDO_ATTR_CLIENT_VERSION: obsahuje informace o čísle verze klienta databáze. PDO_ATTR_CONNECTION_STATUS: obsahuje informace o stavu připojení k databázi. Například pra-
cujete-li s MySQL, tak po úspěšném připojení atribut obsahuje „localhost via TCP/IP“, zatímco při práci s PostgreSQL obsahuje „Connection OK; waiting to send“.
Jakmile zřídíte připojení, můžete ho začít používat, a to je téma zbývající části kapitoly.
Kapitola 31
Uložené rutiny V průběhu práce s knihou jste viděli poměrně dost příkladů, v nichž se dotazy MySQL vkládaly přímo do skriptu PHP. U menších aplikací je to jistě v pořádku, jak ale slo žitost a velikost aplikací narůstá, mohlo by pokračování v takové praxi skončit až fiaskem. Například co když máte rozmístit dvě podobné aplikace, jednu desktopovou a druhou webovou, které obě používají databázi MySQL a provádějí mnoho stejných úkolů? Když je tu a tam třeba změnit nějaký dotaz, budete muset provést patřičné modifikace všude, kde se daný dotaz objevuje, a to ne v jedné, ale ve dvou aplikacích! Jinou výzvou, které čelíte, když pracujete se složitými aplikacemi, zvlášť když je vyvíjíte v týmu, je poskytnout každému členu týmu příležitost, aby mohl přispívat ke zdaru projektu na základě svých odborných znalostí a kvalifikace, aniž by přitom šlapal po úsilí ostatních. Typické je, že ti lidé, kteří jsou zodpovědní za vývoj databáze a údržbu (známí jako databázoví architekti), jsou neobyčejně erudovaní v psaní efektivních a bezpečných dotazů. Ale jak může takový databázový architekt psát a udržovat tyto dotazy, aniž by nelezl do zelí vývojáři aplikace, když jsou dotazy vložené přímo do kódu? Navíc, jak se může databázový architekt spolehnout na to, že vývojář následně „nezdokonalí“ tyto dotazy, a potenciálně tím otevře dveře infiltracím v podobě útoků injektáží SQL (které spočívají v tom, že se modifikují data odesílaná do databáze se záměrem, aby se pak dal spustit nějaký škodlivý kód SQL)? Jedním z nejběžnějších řešení těchto výzev je databázová schopnost, které se říká uložená rutina – stored routine. Uložená rutina je nějaká sada příkazů SQL, která je uložená na databázovém serveru a vykonává se tak, že se zavolá prostřednictvím dotazu názvem, který jí byl přiřazen. V mnohém je to obdoba funkce, protože ta také zapouzdřuje nějakou sadu příkazů, které se vykonají poté, co se funkce zavolá svým názvem. Uložená rutina se dá udržovat za bezpečnými zdmi databázového serveru a na kód aplikace nemusíte ani sáhnout. Od verze 5.0 už MySQL konečně podporuje tuto dlouho toužebně očekávanou schopnost. V této kapitole se dozvíte vše potřebné o tom, jak MySQL implementuje uložené rutiny. Probereme syntax a uvidíte, jak se uložené rutiny vytvářejí, spravují a vykonávají. Také se naučíte začleňovat uložené rutiny do svých webových aplikací. Na začátku se však chvilku zastavme u formálnějšího souhrnu jejich výhod a nevýhod.
734
Kapitola 31 – Uložené rutiny
Měli bychom používat uložené rutiny? Není žádoucí, abyste se naslepo nadšeně vrhli do módních vln uložených rutin. Vyplatí se, když v krátkosti posoudíme jejich přednosti a stinné stránky, zejména proto, že jejich užitečnost je v da tabázové komunitě předmětem vášnivých debat. V tomto oddílu najdete souhrn pro a proti, uvažujete-li o začlenění uložených rutin do své vývojářské strategie.
Přednosti uložených rutin Uložené rutiny mají mnoho předností, nejvýznačnější z nich jsou zdůrazněné zde:
• Eliminuje se redundance. Když mnoho aplikací napsaných v různých jazycích vykonává stejné databázové úkoly, tak shromáždění těchto úkolů do uložených rutin podobných funkcím redukuje jinak běžnou redundanci vývojových procesů.
• Vyšší výkon. Kompetentní databázový administrátor je pravděpodobně ten nejkompetentnější
člen týmu, když jde o to, jak psát optimalizované dotazy. Proto je rozumné, když se tvorba velmi komplikovaných operací, které se týkají databáze, přenechá tomuto individuu tím, že se takové operace udržují jako uložené rutiny.
• Větší bezpečnost. Když pracujete ve zvlášť citlivých prostředích, jako jsou bankovnictví, zdra-
votnictví nebo obrana státu, je někdy oficiálně nařízeno, aby byl přístup k datům přísně restriktivní. Uložené rutiny nabízejí skvělý způsob, jak zajistit, aby měli vývojáři přístup jen k těm informacím, které nezbytně potřebují k řešení svých úkolů..
• Snazší údržba rozsáhlých aplikací. Přestože diskuse o výhodách vícevrstevných architektur
přesahuje rámec této knihy, používání uložených procedur v součinnosti s vrstvou dat může dost usnadnit údržbu rozsáhlých aplikací. Chcete-li se o tomto tématu dozvědět víc, zadejte ve svém webovém vyhledávači termín „n-tier architecture“.
Nevýhody uložených rutin Přestože vás předchozí výčet předností přesvědčil, že jsou uložené rutiny ta cesta, kterou se vydáte, zamyslete se chvilku nad jejich nevýhodami:
• Vyšší spotřeba prostředků. Mnozí argumentují tím, že jediný účel databáze je ukládat data
a udržovat relace mezi nimi, ne vykonávat kód, který by jinak vykonala aplikace. Kromě toho, že se tím narušuje jediný hlavní účel databáze, vykonávání takové logiky z databáze spotřebovává také dodatečné prostředky procesoru a paměti.
• Menší zdatnost. Jak se brzy dozvíte, jazykové konstrukce SQL nabízejí bohatou výbavu i znač-
nou flexibilitu; většina vývojářů však přišla na to, že budovat tyto rutiny je snadnější i pohodlnější, když se to dělá v nějakém vyspělém plnohodnotném jazyku, jakým je PHP.
• Horší udržovatelnost rutin. Přestože se dají pro správu uložených rutin používat utility s gra-
fickým uživatelským rozhraním , jako je MySQL Query Browser (viz kapitola 26), psaní kódu i ladění uložených rutin je o hodně obtížnější, než když píšete funkce PHP ve zdatném integrovaném vývojovém prostředí.
Velká kniha PHP a MySQL 5
735
• Obtížnější přenositelnost. Protože uložené rutiny často používají syntax, která je specifická pro danou databázi, určitě se vynoří nějaké potíže s přenositelností, budete-li potřebovat používat aplikaci v součinnosti s jiným databázovým produktem
Nuže, i potom, co jste se seznámili s výhodami i nevýhodami, možná si stále nejste jisti, zda jsou uložené rutiny pro vás to pravé. Asi nejlepší rada, kterou je možno v tomto ohledu poskytnout, je, abyste si přečetli tuto kapitolu a podnikli všelijaké experimenty s četnými příklady, které v ní najdete.
Jak MySQL implementuje uložené rutiny Přestože se všude okolo omílá termín uložené procedury, MySQL ve skutečnosti implementuje dvě varianty procedur, na které se odkazuje společně jako na uložené rutiny:
• Uložené procedury. Uložené procedury podporují vykonávání příkazů SQL jako jsou SELECT,
INSERT, UPDATE a DELETE. Mohou také připravovat parametry, na které se dá odkazovat později, vně procedury.
• Uložené funkce. Uložené funkce podporují vykonávání pouze příkazů SELECT, akceptují jen
vstupní parametry a musejí vracet právě jednu hodnotu. Kromě toho můžete vložit uloženou funkci přímo do příkazu SQL tak, jak to děláte se standardními funkcemi MySQL, jako jsou count() a date_format().
Všeobecně řečeno, uložené procedury byste měli používat tehdy, když potřebujete pracovat s daty nacházejícími se v databázi, třeba získávat řádky, vkládat, odstraňovat nebo aktualizovat hodnoty, zatímco s pomocí uložených funkcí byste měli s t ěmito daty manipulovat nebo provádět speciální výpočty. Syntax prezentovaná v průběhu kapitoly je ovšem pro obě varianty prakticky identická, kromě toho, že se přepíná termín „procedura“ a „funkce“. Například, příkazem DROP PROCEDURE název_procedury se odstraní existující uložená procedura, kdežto příkazem DROP FUNCTION název_funkce se odstraní existující uložená funkce.
Tabulky přístupových oprávnění uložených rutin Ti z vás, kdo už s MySQL nějaký čas pracujete, dobře víte, že v databázi mysql přibyly nové tabulky. Dvě z nich, proc a procs_priv, slouží ke správě uložených rutin a přístupových oprávnění, která se požadují, chcete-li je vytvářet, vykonávat, měnit nebo odstraňovat.
proc V tabulce proc jsou uložené informace o uložené rutině, mezi něž pa tří její syntax, datum, kdy byla vytvořena, seznam jejích parametrů a další věci. Její strukturu prezentuje tabulka 31-1. Tabulka 31-1. Tabulka proc databáze mysql Sloupec
Datový typ
Null
Výchozí hodnota
db
char(64)
Ano
Není
name
char(64)
Ne
Není
type
enum('FUNCTION','PROCEDURE')
Ne
Není
736
Kapitola 31 – Uložené rutiny
Sloupec
Datový typ
Null
Výchozí hodnota
specific_name language
char(64)
Ne
Není
enum('SQL')
Ne
SQL
sql_data_access
enum přístupu k datům
Ne
CONTAINS_SQL
is_deterministic
enum('YES', 'NO')
Ne
NO
security_type
enum('INVOKER','DEFINER')
Ne
DEFINER
param_list
blob
Ne
Není
returns
char(64)
Ne
Není
body
longblob
Ne
Není
definer
char(77)
Ne
Není
created
timestamp
Ano
CURRENT_TIMESTAMP
modified
timestamp
Ano
0000-00-00 00:00:00
sql_mode
mmožina módů sql
Ne
Není
comment
char(64)
Ne
Není
Aby nebyl sloupec tabulky pro datový typ zoufale široký, je termín enum přístupu k datům datům zástupce skutečného výčtu enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA')
a termín množina módů sql zastupuje množinu set('REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE').
Všechny sloupce se podrobněji probírají v oddílu „Jak se vytvoří uložená rutina“.
procs_priv V tabulce procs_priv jsou uloženy informace o přístupových oprávněních vyjadřující, kteří uživatelé mohou komunikovat s rutinami definovanými v tabulce proc. Struktura tabulky procs_priv je uvedena v tabulce 31-2. Tabulka 31-2. Tabulka procs_priv databáze mysql Sloupec
Datový typ
Null
Výchozí hodnota
Host
char(60)
Ne
Není
Db
char(64)
Ne
Není
User
char(16)
Ne
Není
Routine_name
char(64)
Ne
Není
Routine_type
enum('FUNCTION', 'PROCEDURE')
Ne
Není