Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Silná konkurence pro GeSHi?

Pokud jste se někdy zajímali o zvýrazňování syntaxe u publikovaných zdrojových kódů, nejspíš jste narazili na knihovnu GeSHi. Tento počin dvacetiletého Novozélanďana Nigela McNie si získal velkou oblibu a také jsem jej použil pro zvýrazňování kódu v Texy a zde na La Trine.

Jak je z tohoto příkladů patrné, GeSHi má velké problémy s kódováním UTF-8 (bohužel, autorův nativní jazyk je angličtina). Někdy vyhodí zcela nevalidní UTF řetězec, což představuje smrt pro striktní XML parser. GeSHi také není žádný rychlík, což by mi zas tak nevadilo – kešuji, kudy chodím.

Narazil jsem ale na jiný zvýrazňovač FSHL, jehož autor je „soused“ Slovák Juraj ‚hvge‘ Ďurech. Už na první pohled je patrné, že FSHL toho umí opravdu hodně. Všimněte si, jak ladně přechází mezi ‚podzimním‘ PHP do ‚jarního‘ HTML a ‚zimního‘ CSS. Barevné ladění je velmi příjemné. I když o to tady nejde.

A rychlost? Podle prvních měření je FSHL cca 10× rychlejší než GeSHi. Zbývá jen zjistit, jak je to s podporou UTF. A pak FSHL nasadím.

Aktualizováno: FSHL jsem už nasadil. Podpora UTF-8 se zdá být ok, jen je třeba nahradit volání htmlEntities(...) za htmlEntities(..., ENT_COMPAT, 'UTF-8').

clock 18. 3. 2005 pencil PHP comments Komentáře: 3


Regulární korektura Intervalu.cz

Regulární výrazy jsou vynálezem amerického matematika Stephena Kleene a troufám si tvrdit, že jsou starší než většina čtenářů La Trine. Pro nezasvěcené působí jako tajemné formule s magickou silou. Zdrojů, ze kterých se dají vědomosti o výrazech získat, je dost. Od vyčerpávající nápovědy v PHP, přes články až po knihy.

Člověk omámený kouzlem regulárních výrazů často propadne jejich nadužívání. Proto je škoda, že neexistují i tituly jako „Deset případů, kde se regexp absolutně nehodí“ nebo „Zpověď programátora: Už týden jsem nepoužil regulární výraz“ :-)

Nebudu zde vysvětlovat principy regulárních výrazů – všechny zájemce bych rád odkázal na seriál Miroslava Pecky, který právě vychází na Intervalu. Protože jsme v něm narazil na určitou nesrovnalost, připojuji tuto svou korekturu.

Kde se vloudila chyba?

V části věnované subvýrazům a zpětným referencím autor uvádí, že zpětné reference se zapisují ve tvaru \\n, kde n je číslo subvýrazu. K tomu mám vážnou námitku: zapisují se ve tvaru \n.

Svá slova potvrzuji tímto příkladem. Jasně demonstruje, že při užití \2 \1 vše funguje dle očekávání, zatímco \\2 \\1 ke zdárnému cíli nevede. Tedy rozdíl v jednom lomítku je skutečně zásadní.

Poznámka: V regulárních výrazech nesmírně záleží na každém znaku, včetně mezer, a tudíž není možné tolerovat jakoukoliv nejasnost. Hledání chyb ve výrazech je mravenčí práce a může vést až k nervovým kolapsům včetně nepříjemného regurgitačního uvolnění organismu.

Něco tu nehraje

Co je zajímavé, příklady uvedené v článku Miroslava Pecky skutečně fungují, i s oním dvojitým lomítkem. Jak je to možné? Je to díky určité shodě okolností.

Každý programátor PHP by měl perfektně ovládat zápis řetězců. PHP k tomuto účelu nabízí hned tři způsoby, nejčastěji se používají tyto dva: uvození řetězce do jednoduchých a dvojitých uvozovek. Důležité je vědět, že takto zapsaný řetězec ještě PHP určitým způsobem transformuje do finální podoby.

V těchto transformacích hrají důležitou roli právě zpětná lomítka. Pohledem na příslušné místo v dokumentaci PHP zjistíte, že zápis "\50" podléhá transformaci (viz escapování) a PHP jej nahradí za znak s kódem 50 v osmičkové soustavě, což je mimochodem levá závorka. Naopak při použití jednoduchých uvozovek k transformaci nedojde:

echo "\50";   // vypíše (
echo "\\50";  // vypíše \50
echo '\50';   // vypíše \50

Z příkladu je vidět, že nechtěné transformaci se lze vyhnout zdvojením zpětného lomítka nebo (lépe) nahrazením dvojitých uvozovek za jednoduché.

A tím se dostáváme zpět ke kritizovaným zpětným referencím. Protože autor používá ve všech příkladech řetězce s dvojitými uvozovkami, musí zpětná lomítka zdvojovat. Tedy zdvojení si vynucuje vlastnost PHP, která s regulárními výrazy absolutně nesouvisí. Kdyby použil uvozovky jednoduché, zdvojovat lomítko není třeba (avšak nevadí to). Ve všech dalších případech (syntax heredoc, načítání z databáze nebo souborů, mnou uvedený příklad) už vadit bude a příklady přestanou fungovat.

Závěr: Doporučuji regulární výrazy zapisovat opatrně a nejlépe s použitím jednoduchých uvozovek.

clock 22. 2. 2005 pencil PHP comments Komentáře: 9


Klonování, PHP4 a jeden hack

PHP 4  → 5 Kvůli převaze hostingů podporujících PHP jen do verze 4, programuji zatím stále v této překonané verzi. A je to občas utrpení, cpát všude & a přitom vědět, že v PHP 5 už nemusím.

Nicméně programovat v PHP 4 se dá s vědomím dopředné kompatibility, už jsem o tom jednou psal. Dnes jsem však narazil na zajímavý oříšek.

Potřeboval jsem naklonovat objekt, říkejme mu třeba $dolly. PHP4 má tendenci klonovat jakýkoliv objekt, který mu přijde pod ruku. Tedy stačí napsat $klon = $dolly a je hotovo. Protože však klonování není přesně to, co programátor v naprosté většině případů očekává (a navíc je to v Evropské unii zakázané), je třeba v přiřazení použít symbol reference: $klon = & $dolly. PHP5 tuto nutnost eliminuje a zápis $reference = $dolly vytvoří automaticky referenci. Ale to už určitě dávno víte.

Kompatibilní klonování

Dobrá, a co když skutečně chci v PHP5 $dolly naklonovat? K tomuto účelu slouží zcela nová konstrukce:

$klon = clone $dolly;

Bohužel, PHP4 si na tomto zápisu vyláme zuby, ohlásí Parse error a odporoučí se do věčných lovišť. A teď babo raď, jak napsat kód, který by fungoval v obou verzích?

První myšlenka byla příkaz do zdrojového kódu vložit jako řetězec (vyhnout se parseru) a pak jej spustit přes eval(). Ale nakonec mě napadlo, že přece zápis $dolly a ($dolly) je ekvivalentní. Ozávorkováním nic nezkazím. Takže v PHP5 lze klidně napsat také:

$klon = clone ($dolly);

A co na to PHP4? Ve své dětinské naivitě myslí, že tímto zápisem volám funkci clone(). Takže parse error je zažehnán a stačí jen deklarovat funkci clone(). Samozřejmě jen pro PHP verze 4:

if (PHP_VERSION < 5) eval('
    function clone($obj)
    {
        return $obj;
    }
');

That's all folks…

clock 25. 1. 2005 pencil PHP comments Komentáře: 8


PHP hádanka VI.: zjištění názvu třídy

V těchto věcech si nejsem nikdy jist a občas si musím napsat modelový miniprográmek, abych věděl, jak se PHP zachová. V uvedeném příkladu vypisuji název aktuální třídy pomocí funkce get_class($this) a „magické“ konstanty __CLASS__. Konstanta má tu výhodu, že ji lze užít i ve statické metodě (tam není definováno $this). Otázka je, jestli i ve zděděné třídě vypíší totéž. Tak co, programátoři?

class A {

  function showClassName() {
    echo get_class($this) . ' ' . __CLASS__;
  }
}

class B extends A {
}

$foo = &new B();
$foo->showClassName();

clock 18. 11. 2004 pencil PHP comments Komentáře: 7


PHP hádanka V.

Dnešní pondělní hádanka se týká bitových operací. Následující skript zjišťuje pomocí logického součinu přítomnost druhého nejnižšího bitu v proměnné $foo. Jenže vrací opačné výsledky, než by se očekávalo. Kde je chyba?

// pro 1
$foo = 1;
  // čekám false, ale vrací true!
$isSet = ($foo & 2 == 2);


  // pro 2
$foo = 2;
  // čekám true, ale vrací false!
$isSet = ($foo & 2 == 2);

clock 15. 11. 2004 pencil PHP comments Komentáře: 6


phpFashion © 2004, 2012 David Grudlo webu

Pokud není uvedeno jinak, podléhá obsah těchto stránek licenci Creative Commons BY-NC-ND Creative Commons License BY-NC-ND

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.