Na stránce www.phpbench.com, která je
bohužel plná zavádějících měření, jsem narazil na zajímavou
konstrukci:
Funguje to od PHP 4 a jde vlastně o obdobu
Vůbec jsem netušil, že za as
může následovat podobný
výraz. Podíval jsem se do souboru zend_language_parser.output
(najdete ve zdrojácích PHP) a ono je možné dokonce vytvářet konstrukce
jako foreach ($arr as $key[fce($obj->x)] => $val[$y])
.
Praktické využití mě nenapadá, dívky tím neohromíte, ale blognout jsem
to musel 🙂
Ať je alespoň něčím tento spot užitečný: víte, že funkce array_keys má tři parametry?
Ještě ke stránce The PHP Benchmark: snaha autora i vizuální provedení
je rozhodně chválihodné, bohužel některé výsledky bez patřičného
komentáře vyvolávají dojem, že ta či ona konstrukce je zbytečně pomalá.
Pro pochopení je ale potřeba důkladná znalost vnitřností PHP (viz Půvab optimalizace rychlosti,
Černá magie optimalizace,
Derick Rethans: Understanding
the PHP Engine).
Že je Delphi for
PHP absolutní propadák, se už nějakou dobu ví. Prohra je to naprosto
zasloužená. Borland (respektive jeho pobočka CodeGear) totiž vypustil
produkt, kde prakticky nic nefungovalo. Zatímco Arthur už dal Delphi
sbohem u první verze, já neodolal svodům CodeGearu a zkusil si
nainstalovat docela čerstvou verzi 1.5. Mohu tak potvrdit, že ani v ní si
aplikaci nespustíte! (to si nedělám srandu)
Je mi upřímně smutno z toho, kam to společnost, ke které jsem
vzhlížel už jako dítě, kam to dotáhla. Byl to Borland, kdo dal světu
IDE,
kdo přišel s revolučním Turbo Vision a ustál i smrtící přechod na
Windows. Sbohem a šáteček.
Ještě než jsem Delphi for PHP odinstaloval, zlákal mou pozornost
zdrojový kód frameworku VCL for
PHP (pro PHP 5), který má webové aplikace pohánět. Kdyby mě někdo
v tu chvíli natáčel, zaznamenal by desetiminutový plynulý morphing
od němého úžasu k hlasitému smíchu.
Ať se pobavíte taky:
Fakt by mě zajímalo, který zoufalec by na tom vybudoval aplikaci 🙂
p.s. CodeGear neusnul na vavřínech a už ohlásil IDE pro Ruby on Rails
nazvané 3rdRail. Připouštím, dělal jsem si z Rubystů občas
srandu, ale tohle bych jim nikdy nepřál!
Výstupem PHP skriptu bývá nejčastěji HTML stránka. S jejím
generováním na úrovni značek může pomoci třeba knihovna NHtml. Ale ať už výstup
generujete jakkoliv, je třeba mít na paměti, že každý řetězec se musí
ošetřit funkcí htmlSpecialChars. To ji staví do
pozice téměř nejdůležitější funkce, škoda proto, že nemá kratší
název. Ačkoliv i to se dá napravit:
Nojo, ale co když potřebujeme ve stránce vygenerovat JavaScriptový kód?
Jakou funkcí v něm ošetříme řetězce?
Je to s podivem, ale až do verze PHP 5.2.0 s touto eventualitou tvůrci
nepočítali. Žádnou funkci pro „escapování“ řetězců jazyk
nenabízel. Jako náhrada se občas používá addSlashes, jenže ta nevkládá lomítka
na všechna potřebná místa a navíc je závislá na nastavení direktivy
magic_quotes_sybase
. Teprve s příchodem verze 5.2 přišla
spása nazvaná json_encode.
Poznámka: pokud píšete v XHTML a obsah skriptu uzavíráte mezi značky
<![CDATA[
a ]]>
, je třeba ještě zajistit, aby
se v textu skriptu neobjevila koncová značka. Ale lepší spíš bude se
těmto Xvěcem vyhnout.
Sice za několik dní už žádného správného vývojáře verze nižší
než 5.2.0 zajímat nebudou 😉, než k tomu
však dojde, podělím se s vámi o alternativní řešení. To umí nejen
sanitizovat řetězce, ale je plnohodnotnou náhradu funkce json_encode
(potřebujete-li ošetřit pouze řetězce, stačí vám část za
if (is_string($val))
):
Tato funkce se oproti předloze liší v tom, že neodhalí rekurzivně
zanořené pole nebo objekty. V případě polí by se jednalo o docela
netriviální úkol a tudíž nejlepším řešením je ho
neřešit vůbec.
Kromě základní třídy Exception
disponuje PHP počínaje verzí 5.1.0 celou škálou dalších
předpřipravených výjimek. Než si tedy vytvoříte novou třídu, zkuste se
podívat, jestli by vám nevyhovovala některá z těchto:
- LogicException – předvídatelné již při návrhu programu
- BadFunctionCallException – chyba při volání funkce; funkce
nenalezena; volání nepovoleno
- BadMethodCallException – totéž pro metody
- InvalidArgumentException – špatný argument
předaný funkci
- OutOfRangeException – index mimo rozsah pole či kolekce
- LengthException – hodnota překračuje povolenou délku
- DomainException – hodnota nespadá do požadované domény,
rozsahu
- RuntimeException – zjistitelné pouze za běhu programu
- OverflowException – přetečení bufferu či aritmetické operace;
více dat než očekáváno
- UnderflowException – podtečení bufferu či aritmetické operace;
méně dat než očekáváno
- OutOfBoundsException – index mimo rozsah pole či kolekce
- RangeException – hodnota nespadá do požadovaného rozsahu
- UnexpectedValueException – neočekávaná hodnota (např.
návratová hodnota funkce)
…pokračování
Interpretovat nastavení konfiguračních direktiv
nemusí být vůbec snadné. V případě logických hodnot sice dokumentace tvrdí, že se vždy vrací
1
, 0
nebo prázdný řetězec, ale není tomu tak
v případě, že hodnotu nastavíme souborem .htaccess či httpd.conf a
direktivou php_value:
php_value magic_quotes_gpc On
V takovém případě ini_get vrátí přímo řetězec On
.
Konfiguraci je proto lepší zjišťovat účelovou funkcí, jako je třeba
get_magic_guotes_gpc()
. V případě, že žádná funkce
k dispozici není, můžete použít tuto:
Vkládání skriptů přes include
nebo require
není vždy transparentní, protože programátoři často neví, z jakého
adresáře se skript načte. Pravidla jsou následující:
- pokud je cesta absolutní, nic se nedohledává
- pokud cesta začíná na
./
nebo ../
, hledá se
vůči aktuálnímu
adresáři (neplést s adresářem s právě prováděným skriptem!)
- v ostatních případech:
- prohledají se všechny cesty z
include_path
relativně
vztažené k aktuálnímu adresáři
- hledá se od adresáře s právě prováděným skriptem
„Na jistotu“ lze obecně vkládat pouze přes absolutní cesty. K tomu
se užívá tato formule:
Následující trik ukazuje, jak se lze volání funkce dirname zbavit (nedoporučuju
používat)
PHP 5.3 má novou magickou konstantu __DIR__
, která nahradí
volání dirname(__FILE__)
:
Pár postřehů k DOM API v PHP 5. Jde
o funkce pro parsování, generování a manipulaci s XML a HTML soubory.
Chování se může v různých verzích lišit.
Načtení XML souboru
- metody
$dom->load($fileName)
,
$dom->loadXML($string)
- konfigurační vlastnosti:
$dom->resolveExternals
– načíst externí entity z DTD
deklarace? Výchozí: false
$dom->strictErrorChecking
– throws DOMException on
errors? Výchozí: true
$dom->validateOnParse
– načíst a validovat oproti DTD?
Vychozí: false
$dom->preserveWhiteSpace
– zachovat redundantní white
space? Výchozí: true
$dom->substituteEntities
– zaměnit jmenné entity?
Výchozí: false
- validování nebo resolveExternals stahuje DTD – extrémně
pomalé!
- aby se nestahovalo DTD:
- ponechat nastavené
resolveExternals = validateOnParse = false
- nebo použít XML
Catalogs (nepovedlo se mi rozchodit)
- nebo modifikovat URL v
<!DOCTYPE>
na lokální
kopii DTD
- zpracování DTD je pomalé (tj. i bez stahování)
- načtení XHTML dokumentu trvá cca 50× déle
- validování už pak zpomalí jen mírně
- bez zpracování DTD:
$dom->encoding
určuje XML deklarace
…pokračování
Víte, že rodné číslo nemusí být dělitelné 11? Že
algoritmus ministerstva vnitra pro ověřování IČ je špatný? A že jej
používá celá řada aplikací? A co na to Jan Tleskač?
Je užitečné, pokud aplikace (nejen webové) umí ověřit platnost
různých identifikátorů, jako je třeba e-mail, rodné číslo, IČ a
podobně. Naopak průseroidní je, když ověřovací algoritmus obsahuje chybu
a digitální nepřítel pak tvrdošíjně odmítá vaše nacionále. Ukecat se
nenechá, třísknout ho nemůžete.
Zrovna ohledně ověřování rodných čísel a IČ se obávám, že
chybných bude většina implementací. Problém je v nedostatečném
zdokumentování algoritmů, takže programátoři často spoléhají na
neověřené informace. Jako skutečně kvalitní studnici vědění bych
doporučil:
Hned si jej stáhněte!
…pokračování
Článek upozorňuje na smutný fakt, že i v nových
verzích PHP se umí objevit chyba, díky kterým přestanou fungovat základní
jazykové konstrukce a funkce.
PHP je jazyk plný překvapení. Takové Kinder Surprise pro dospělé
programátory. Psaní aplikací v PHP je adrenalinovým sportem –
i pojišťovny k tomu tak přistupují.
Naivní prosťáček nebo PHP laik by při pohledu na tento kód…
…mohl mít pocit, že ví, co se vypíše. Ale ostřílený profesionál by
nejprve kontroval otázkou: „V jaké verzi PHP?“ A rozhodně by se
nespokojil s odpovědí „V pětce.“ Když se ptá na verzi, zajímá ho
každá setinka. Protože třeba PHP 5.1.2 odstraní (unset
)
z pole jiný prvek, než verze 5.1.3. Stejně tak 4.4.2 versus 4.4.3.
To je péhápé. To se ví!
V aplikacích psaných pod PHP nestačí neuvádět minimální požadovanou
verzi, vhodnější je zmínit výčet verzí, pod kterými dost možná
i funguje. Třeba pokud používáte overloading…
…tak vězte, že nemusí korektně fungovat v PHP 5.2.0. Nicméně
v předchozích i následujících verzích ano. Obzvláště pikantní je,
že overloading miluje Zend Framework, takže kupříkladu jejich Zend_Session
je pětdvanulkou taktéž ochromen. Doporučují
upgradovat na 5.2.1, ovšem ani to nemusí být gór dobrý nápad. Proč?
Procházíte ve své aplikaci pole pomocí foreach
a
používáte funkci key
? Pak vám nemusí fungovat
v PHP 5.2.1 a novějších. Přitom v minulosti z podobných důvodů
nefungovalo třeba Texy v PHP 4.4.1. Historie se opakuje.
Simply PHP
Programovat v Javě umí kdekdo. O ASP.NET ani nemluvě. Jen v PHP píši
skuteční hrdinové. Renesanční bytosti. Fascinující a neskutečně
trpěliví lidé. Trpěliví od slova trpět.
Třeba já.
A teď jedna dobrá zpráva ze světa zpracování XML dokumentů v PHP.
S příchodem verze 5.2.0 se řady funkcí DOM rozšířily
o nováčka jménem registerNodeClass()
. K čemu však slouží?
Dokumentace to úzkostlivě tají, dokonce i strýček Google cudně mlčí.
Tak to se asi nedozvíme. Nejspíš půjde o nějakou hloupost…
The end
Ještě tu jste?
Tak to, ukecali jste mě, prozradím vám význam registerNodeClass. Tato
funkce bezpochyby přináší svěží vítr do celé problematiky XML a
nastavuje zrcadlo dosavadnímu systému zpracování. Možná více než slova
napoví malý příklad.
Jednotlivé třídy DOM je možné v PHP dále rozšiřovat. Například
takto si rozšíříme DOMElement o tři šikovné metody:
První z nich přetaví uzel na objekt SimpleXML, druhá jej zase odstraní
ze stromu dokumentu. A třetí funkce je tuze šikovná, protože zbaví
element všech potomků a to vskutku elegantně, bez složitých iterací.
Tohle všechno je velmi krásné, skoro až báječné, nebýt jednoho
drobného detailu. Výhod dgxElement
využijeme pouze tehdy, pokud
element vytvoříme skriptem. V případě, že XML dokument naparsujeme ze
souboru, tak bude tvořen pouze standardními objekty DOMElement,
DOMAttr, atd.
Této vady na kráse si všimli i američtí inženýři. Po krátké
poradě se rozhodli jednat a brzy přišli s řešením. Dali mu politicky
korektní název registerNodeClass. A nyní opět pohovořme
v jazyce PHP:
Paráda, ne?