Programujete v PHP? Zajděte si na školení Nette!
Pokud programujete v PHP, asi znáte slovo Nette. Je to poměrně nedávno veřejně uvedený framework pro PHP, který má dost odlišný přístup od frameworků konkurenčních.
Autorem frameworku je Nette Foundation, což je vznešený název pro Davida Grudla :-) David se nesnaží stavět mraky nesmírně složitých knihoven pro různá obskurní použití, ale relativně málo dobře promyšlených tříd (zhruba desítku hlavních), které významně vylepšují jazyk samotný a práci s ním.
Na Nette je sympatické, že je můžete ale nemusíte používat celé (kompletní komprimovaný framework má mimochodem příjemných 240KB). Pokud chcete používat jen věci pro rozšíření možností jazyka a ladění aplikací (typicky Object
, Debug
a další), snadno je pár řádky kódu integrujete i do vašeho stávajícího frameworku či CMS.
Postupem času ale asi začnete využívat i výhod Routeru či výborných formulářů, no a od toho je už pouze krůček k MVC třídám.
Obecně - pokud jste programátor v PHP, a přestože máte framework vlastní, zajděte si na školení Nette. Školení je na profesionální úrovni a velice dobře připravené. David má navíc spoustu dobrých nápadů i jejich realizací, a jeho školení Nette a koukání se do kódu je opravdu skvělou inspirací.
A doporučil bych rovnou školení spíše dvoudenní. Osobně jsem absolvoval jednodenní, a pro řadu věcí nebyla (z nedostatku času) možnost jít plně do hloubky, přestože se začínalo v 9:00 a končilo v 19:00.
10 bodů jak migrovat z MySQL na SQL Server 2008 + IIS7 + PHP
Pro několik nových velkých portálových projektů (desítky tisíc registrovaných členů, milióny komentářů pod desítkami tisíc článků, milióny příspěvků v diskusním chatu) budeme používat namísto kombinace Linux + PHP + MySQL + Apache nově tři čtvrtiny Microsoftích technologií, tedy Windows 2008 Server, IIS7, SQL Server 2008 Web/Standard Edition a z open-source tak zůstane jen PHP.
Základem je samozřejmě SQL Server 2008 databáze, která výborně škáluje, je stabilní a je možné ji programovat podstatně lépe než zaostalou MySQL. Výborné jsou i standardně dodávané nástroje pro ladění výkonu - SQL Server Profiler a Database Engine Tuning Advisor.
S prvotními testy s reálnými daty na nové platformě jsem osobně velice spokojen, po optimalizaci SQL dotazů, přepsání části kódu z PHP do T-SQL (na triggery a uložené procedury) je výkon ohromující.
Tam, kde MySQL + Apache zabral podobný (byť relativně neoptimalizovaný) soubor dotazů nad menším datovým objemem cca 0.5 sekundy pro vytvoření jedné stránky, tam kombinace IIS7 + SQL Server 2008 potřebuje jen desítky milisekund (30-50ms) dle stránky. Toto je skutečné živé generování stránky, která se dále ukládá jako statická a server je tedy ještě rychlejší.
Pro připojení PHP na SQL Server používáme SQL Server Driver for PHP 1.0. Ukázal se jako nejstabilnější a nejrychlejší, ve srovnání na občas padající MSSQL či PDO_MSSQL.
Uvedený vývoj a přesun z MySQL na SQL Server není samozřejmě bez problémů, zde je tedy pár poznatků, které se vám budou při migraci aplikace a dat hodit.
Použijte DB konečně naplno - zapomeňte na DB layer
U spousty PHP projektů se člověk setká s databázovým layerem. Na tom není v zásadě nic špatného, objektový layer nad sadou funkcí je nutná věc. Špatné je, že většina těchto layerů "podporuje" více různých DB (ano, to je špatné), a to pochopitelně na úrovni nejnižšího společného jmenovatele. Takže se přes layer umíte připojit k DB, provést SELECT či INSERT, získat další záznam, případně chybové hlášení, a ... to je vlastně všechno.
Neuvěřitelná primitivnost. Jenže dnešní databáze toho umí mnohem více.
Problém je, že pokud se dostanete za hranice primitivního ANSI-92 SQL, 16 let stará věc, tak podobnost databází končí. Pokud definujete uloženou proceduru či funkci v T-SQL, nebude fungovat na Oracle s PL-SQL a už vůbec ne v primitivním MySQL.
Dokonce i trivialita jako je vynucení použití určitých indexů, nebo i návrh VIEW nebude všude fungovat stejně. Definice pro cizí klíče je odlišná. Ani datové typy nejsou stejné. LIMIT x není stejný. Nad Oraclem namísto IDENTITY či AUTOINCREMENT polí budete muset dělat sekvence a triggery pro BEFORE INSERT na daných tabulkách.
Databázové layery, které pracují s více typy databází, mají smysl pro některé open-source projekty. Tam je rychlost nadřazena nad výkon a spolehlivost. Jejich programátoři se poté omezují na nejprimitivnější SQL, "aby to fungovalo všude". Osobně ovšem ze všech projektů, kde jde o výkon, databázový layer pro model více databází odstraňuji (pokud tam je), ponechávám jen DB jedinou a optimalizované objekty pro ni, a snažím se vyždímat z této konkrétní použité databáze maximum.
Pro jeden velký portálový projekt (stovky tisíc pageviews denně) používám SQL Server 2008 a IIS7 právě proto, že T-SQL je mocný nástroj, a to i při propojení na PHP jako back-end. Na výkonu "skriptovaného" PHP zde tak v podstatě nezáleží, použije se jen pro prezentační část, a na to je PHP velice dobré.
Databázový layer pro více DB není znakem pokroku, u projektů postavených pro jeden konkrétní systém je často naopak znakem toho, že daný vývojář zná jen základy SQL a nic víc. Vše ostatní "prasí" na aplikační úrovni, přestože zpracování na serveru bývá rychlejší a výhodnější.
Asi založím "Ligu proti databázovým layerům" s podtitulem "Použijte vaši DB konečně naplno a nativně (a nejenom na primitivní SELECT a INSERT)" :-)
Dnešní rychlokvašná "MySQL generace" totiž vůbec neví, že databáze jsou určené k tomu, aby se v nich programovalo.
Vista x64: SQL Server 2008 driver pro PHP na IIS7
IIS7 je výkonná platforma pro provozování nejenom ASP.NET aplikací, ale s FastCGI modulem také PHP skriptů. Při použití Windows serveru a IIS7 se rovněž nabízí použít jako databázi SQL Server 2008, namísto funkčně zaostalé MySQL 5.x.
PHP pro napojení na SQL Server používá dvě knihovny - mssql
a pdo_mssql
. Ani jedna z nich ovšem není dobrá a funkčně zůstávají někde v roce 1997.
Řešením pro PHP a SQL Server 2008 je nativní driver od Microsoftu - SQL Server 2005 Driver for PHP verze 1.0. Přestože má v názvu 2005, tak je postaven a funguje 100% i pro SQL Server 2008. K instalaci budete potřebovat i SQL Server Native Client, a to ve verzi 2005 (přestože máte instalovaný 2008 Server), 64bitová varianta je ke stažení zde.
Driver bohužel nenabízí nic, co by vám usnadnilo konverzi mezi UCS2LE (nativní kódování pro data v SQL Serveru, které ovšem pro změnu nepodporuje IE ani WebKit - Safari a Google Chrome) a UTF-8.
Buď vám budou stačit jednobajtová kódování jako je CP1250 anebo se musíte postarat o konverzi mezi UTF-16LE (s tímto kódováním pracuje PHP driver) a UTF-8 před uložením do databáze a po načtení dat.
Práce s SQL Server 2008 není v PHP tedy tak dobrá jako v .NET, kde si kódování snadno specifikujete, ale s troškou práce na datové vrstvě můžete tuto databázi používat de-facto na 100%.
Související: dokumentace pro SQL Server Driver for PHP na MSDN
PremiumSoft Navicat - nejlepší správa MySQL DB
Přestože můj názor na MySQL je dosti negativní (viz tento 3 roky starý článek), fakt je ten, že drtivá většina webhostingů implementuje právě tuto databázi, a člověk ji tedy u open-source produktů v podstatě musí používat, a musí zapomenout na pokročilejší věci a funkce prováděné na úrovni DB.
Toto naštěstí plně platilo 3 roky dozadu, dnes to není až tak hrozné, MySQL 5.1 umí "už" i views, stored procedures a další (tedy u jiných DB desítky let běžné) věci.
Na správu MySQL se dá použít webová aplikace phpMyAdmin, nicméně, při větším objemu dat tato rychle narazí na své limity a zkolabuje. Jedna z nejlepších variant pro správu MySQL je poté PremiumSoft Navicat pro MySQL, špičkový produkt s GUI navržený pro Windows, Mac OS X i Linux.
Edice Navicat Windows - Standard stojí US$ 99, verze Enterprise poté US$ 139, takže se při větším projektu zaplatí během pár hodin.
Základní rozhraní Navicat MySQL:
V Navicatu si můžete nadefinovat neomezené množství databází / připojení, podporované jsou i rysy nové MySQL 5.1 a preview 5.2. Připojit se k databázi můžete bez šifrování, pomocí SSL, SSH tunnel, či třeba pomocí stunnelu.
Jednou z nejdůležitějších funkcí je backup a restore, zálohování, funguje na 100%, a na rozdíl od phpMyAdmina umí dělat commit po každém INSERTu, takže se nestane, že na web nahráváte 10MB tar.gz soubor, poté to 10 minut cosi dělá, a nakonec to spadne na timeout (typický problém phpMyAdmina a zpracování více dat).
Částečné vyhodnocení podmínek v PHP
Pokud vás zajímá, zda se PHP chová inteligentně u vyhodnocování podmínek, které mají předem jasný výsledek (jako TRUE or PODMINKA), tak odpověď je ano. Ta část podmínky, kterou není potřeba vyhodnocovat, není vůbec provedena.
Tento kód:
<?php function T(){ echo '- T<br>'; return 1; } function F(){ echo '- F<br>'; return 0; } echo 'T || F<br>'; if (T() || F()) ; echo '<br>T or F<br>'; T() or F() ; echo '<br>F && T<br>'; if (F() && T()) ; echo '<br>F and T<br>'; F() and T() ; ?>
Jak si smazat celodenní práci [selfdestruction]
Celý víkend programuji zbrusu novou fotogalerii. Začal jsem v pátek večer, pokračoval v sobotu do 4:00 do rána, dnes v 10:00 vstával a pracoval na tom opět. Umí to hromadu věcí, neomezený počet sub-galerií, práva uživatelů, privátní a veřejné fotogalerie, automatické thumbnails, má to skvělé administrační rozhraní, a dají se tam kromě obrázků vkládat i FLV, SWF soubory a videa z YouTube.
Přitom jsem si to v sobotu ve 3:00 ráno málem všechno smazal. Začalo to nenápadně. Programoval jsem třídu pro výmaz vnořených sub-galerií a obrázků, jejíž část vypadala nějak takto:
function rmdirr($dirname) { if (!file_exists($dirname)) return false; if (is_file($dirname)) return unlink($dirname); $dir = dir($dirname); while (false !== $entry = $dir->read()) { if ($entry == '.' || $entry == '..') continue; $this->rmdirr($dirname.DIRECTORY_SEPARATOR.$entry); } $dir->close(); return rmdir($dirname); }
Tedy poměrně primitivní kód, který udělá to, že pro předanou cestu smaže všechno, co je v ní a níže. Všechno by fungovalo dobře, kdybych ji místo $this->rmdirr($this->rootdir)
nezavolal, ve 3:00 ráno (tedy totálně unavený), s parametrem $this->rmdirr($rootdir)
. $rootdir je samozřejmě proměnná, která nebyla inicializovaná, což PHP nijak nevadí, použil se tedy adresář běžícího skriptu namísto kořene galerie (PHP 5.2.3 na Ubuntu 7.10), a smazala se tedy půlka PHP projektu.
Skript smazal dokonce i sám sebe. Bylo to vlastně velice půvabné.
Nebylo to tedy taková katastrofa, používám SVN, kam se aktualizuje soubor zcela automaticky při každém uložení v UEStudiu, takže stačilo udělat checkout kódu a během pár minut jsem fungoval dál. Nicméně nedokážu si představit tu katastrofu, kdyby $rootdir
náhodou inicializovaná byla a měla hodnotu $rootdir = '/'
. Tedy obdoba rm -rf
.
Každopádně vše dobře dopadlo, a zbrusu nová multimediální galerie je na světě:
Instalace Apache, MySQL a PHP na Windows
Následující článek by měl reagovat na neustávající příval emailů a otázek na fórech od webdesignérských začátečníků řešících instalaci a zprovoznění Apache, MySQL a PHP na Windows, pro potřeby webdesignu a testování různých skriptů, a to bez použití nějaké "trojkombinace". Instalace jednotlivých komponent je dle mého názoru "čistější" věc, minimálně vám umožní zvolit si detailně jejich jednotlivé verze, a provést ručně a podrobně jejich konfiguraci.
HTTP Apache server
HTTP server Apache existuje v několika základních verzích, dnes již archaické 1.3 (aktuální bugfix release 1.3.37), následně nejpoužívanější 2.0.x (aktuální bugfix 2.0.59), a relativní novinky 2.2.x (aktuální bugfix 2.2.4). Většina webhostingů používá již 2.2.x verzi, a v zájmu kompatibility vašich aplikací bych tedy právě tuto verzi doporučoval k instalaci.
Vlastní stažení všech verzí je dostupné na http.apache.org/download, včetně námi požadované binární verze 2.2.4 pro Windows (doporučuji se ale vždy podívat na první odkaz, je možné, že v době kdy čtete tento článek bude již k dispozici novější bugfix release) [4.3MB].
Adresářová struktura
Osobně si volím pro instalaci Apache, MySQL a PHP následující adresáře:
Instalace aplikací | |
---|---|
Apache 2.2 server instalace | c:\web\prog\Apache2 |
MySQL server instalace | c:\web\prog\MySQL |
PHP instalace | c:\web\prog\php |
Kořenový adresář webu | |
Root www | c:\web\www |
Ostatní adresáře | |
Uložené instalační soubory | c:\web\install |
Manuály a dokumentace | c:\web\manual |
Pomocí aplikace junction si rovněž vytvářím symbolický odkaz c:\work
, který odkazuje na root webu, tedy c:\web\www
, a to příkazem junction c:\work c:\web\www
. Zjednodušuje to přístup k souborům webu například z Total Commanderu.
Vlastní rozdělení adresářů je samozřejmě pouze na vás, uvedené dělení je zde uvedeno pouze pro inspiraci, a jako podklad pro adresáře uváděné při instalaci a konfiguraci.
Pokud použijete jiné adresáře, budete muset konfiguraci patřičně uzpůsobit.
SQLite3 a pár tipů pro vaše aplikace
Pokud převádíte vaše aplikace na použití SQLite databáze v PHP, mám pro vás pár poznatků.
Používejte PDO SQLite, nikoliv sqlite_ funkce
PHP obsahuje dvě sady funkcí pro práci s SQLite databází, jedna sada funkcí začíná na sqlite_ a druhá je implementována formou PDO. Použijte rozhodně PDO, podporuje totiž SQLite verze 2 i 3, s tím, že verze 3 již neobsahuje tolik kritických a nepříjemných bugů jako verze 2.
Vlastní sada funkcí sqlite_ je v praxi téměř nepoužitelná, podporuje jen SQLite2.
SELECT uzamyká celou tabulku
Představte si, že máte následující kód:
SELECT * FROM table LIMIT 0,1 UPDATE table SET id=1 WHERE ...
Prostě triviální kód, kde z tabulky něco načtete přes SELECT a následně na tabulku uděláte UPDATE. Nebude to fungovat.
SQLite3 to nepovoluje, po SELECTu je tabulka uzamčena dokud neprovedete kompletní fetch() předchozího dotazu nebo zavření resource dotazu. Můžete to udělat třeba pomocí funkce unset($resource).
Pokud máte SELECT na více položek a v cyklu děláte UPDATE, jediná slušná možnost jak z tohoto problému ven je v databázovém layeru zavolat funkci fetchAll(), načíst veškeré hodnoty z tabulky do paměti, resource uzavřít, a v cyklu již dělat pouze UPDATE.
Je to opravdu velice nepříjemné omezení, ale SQLite3 je takto primitivní…
VIEW neumí update / insert / delete, TRIGGER na VIEW ale ano
SQLite3 umí vytvořit VIEWs, nicméně, nelze na nich provádět UPDATE, DELETE a INSERT příkazy. Naštěstí se to dá obejít pomocí TRIGGERu s parametrem INSTEAD OF.
Takže můžete psát třeba následující:
CREATE TRIGGER foto_users_delete INSTEAD OF DELETE ON foto_users BEGIN DELETE FROM forum_users WHERE username = OLD.username; END;
PHP vytváří i dnes banda pitomců
Spousta lidí nadává na PHP kvůli naprostému nedostatku koncepce. Někteří lidé říkají, že je to věc minulosti, nedostatečného vzdělání jeho prvotních tvůrců, a že dnes je vše zcela jinak. Nemyslím si to.
Vezměte si třeba základní funkci str_replace(), ta má jako poslední parametr řetězec, v němž se hledají a zaměňují řetězce na první a druhé pozici. Funkce strpos() to má ovšem zcela naopak, první parametr je řetězec, v němž se hledá, a druhý parametr hledaný výsek. Podobný "bordel" (kdy si člověk nikdy není jistý, jaké pořadí parametrů která funkce právě akceptuje) je ve všech starších funkcích PHP, a to nejenom v pořadí parametrů. Problém je i v názvosloví funkcí, onomu str_replace() by daleko více odpovídalo str_pos(), které ovšem neexistuje.
Nekoncepčnost a naprostá zmatenost vývojářů PHP je ovšem vidět i dnes. Například podpora pro MySQL 4.1 a vyšší byla implementována jako zcela nová sada funkcí mysqli(), zcela ignorující existující mysql() řadu funkcí. Nová řada mysqli funkcí je de-facto identická té předchozí, jen má zcela opačné argumenty volání (a také je ji možno volat jako objekt). Takže místo mysql_query($query, $db) píšete nově a úžasně mysqli_query($db, $query).
A to není zdaleka celé. Databázového mišmaše je mnohem více. PHP obsahuje od verze 5.1 vestavěnou podporu pro SQLite, která se volá funkcemi sqlite(). Nicméně, zase to není tak docela pravda, tato podpora je funkční jen pro nestabilní a bugovou SQLite 2.8, takže pokud uvidíte hlášku "DATABASE SCHEMA HAS CHANGED", víte, že musíte použít SQLite 3.x.
Průser je ovšem v tom, že SQLite 3.0 má zase jinou sadu funkcí, přistupuje se k ní jen a pouze přes PDO objekty, tedy například new PDO("sqlite:$db"). Pokud tedy chcete, aby vaše aplikace používající SQLite nepadala až tak často, musíte ji celou zásadně a koncepčně přepsat, zapomenout na sqlite() funkce a používat PDO. Stejně tak musíte zásadně přepsat aplikaci používající MySQL 4.1 namísto MySQL 3.x / 4.0.
Kdyby vývojáři PHP nepostrádali mozek, dávno zavedou alias str_pos() pro funkci strpos(), naprogramují přístup k MySQL 3.x / 4.x / 5.x zcela transparentně, bez zavádění mysqli() funkcí, naprogramují podporu pro SQLite 3.x i pro sqlite() funkce, nikoliv jen pro PDO (ony sqlite funkce mimochodem vyžadují pro svoji funkčnost PDO knihovny!), prostě nebudou zjednodušovat život sobě, ale PHP programátorům.
Bohužel, hlavní cíl vývoje PHP je zřejmě získat jazyk s co možná největším počtem podivných funkcí na každou trivialitu, které nejsou vzájemně kompatibilní. Ať se na to dívám z jakéhokoliv pohledu, musím říci, že nejenom v minulosti, ale i dnes vytváří PHP banda naprostých pitomců.