
PHP a čeština II. - národní specifika, pravopis atd.
V minulé kapitole jsme se zabývali problematikou kódových stránek, konverzí
kódování a souvisejícími věcmi. Nyní přejdeme k dalším záležitostem, které
se v souvislosti (nejen) s češtinou musí řešit - a není toho málo.
Přístup ke vzdáleným souborům
Se vzdálenými soubory se v PHP pracuje obdobně jako s lokálními. Soubor se
otevře a pracuje se s ním (až na určitá omezení) stejně jako se souborem
uloženým na disku. Pro znakové kódování tedy platí podobná pravidla.
Používáme-li protokol FTP, musíme použitou znakovou sadu znát předem. U
protokolu HTTP se sice v hlavičce posílá kódování, ale to při klasické práci
(se standardními příkazy fopen, fgets atd.) nemáme možnost zjistit.
Bylo by to samozřejmě možné řešit použití síťových funkcí (fsockopen atd.),
ale to je zbytečně pracné. Můžeme totiž použít rozšíření CURL (Client URL
Request Library), které má kromě toho podstatně rozsáhlejší možnosti než běžný přístup
ke vzdáleným souborům (mnoho protokolů, ošetření chyb, informace o přenosu
atd.).
Pro použití tohoto rozšíření je třeba ho nejprve nainstalovat. Pak se musí
zkompilovat PHP tak, aby rozšíření fungovalo (pomocí --with-curl).
Vlastní práce s CURL probíhá tak, že se CURL nejdříve inicializuje, pak se
nastaví vše potřebné, provede se transfer a na závěr se CURL uzavře.
Demonstruje to následující příklad:
$id = curl_init("http://192.168.1.1/adr/soubor.txt");
$fp = tmpfile();
$hfp = tmpfile();
curl_setopt($id, CURLOPT_HEADER, 0);
curl_setopt($id, CURLOPT_FILE, $fp);
curl_setopt($id, CURLOPT_WRITEHEADER, $hfp);
curl_exec($ch);
curl_close($ch);
První řádek inicializuje CURL tak, že současně nastaví URL na uvedenou
hodnotu (lze to udělat i později funkcí curl_setopt()). Pak se vytvoří dva
dočasné soubory - jeden pro vlastní data a druhý pro hlavičky. Následující
příkazy zakáží zápis hlaviček do datového souboru a určí soubory pro data a
pro hlavičky. Provede se přenos a CURL se uzavře. Nyní jsou data uložena
v lokálních dočasném souboru a lze s nimi pracovat jako s běžným souborem.
V dalším souboru jsou uloženy hlavičky - ty lze použít mj. ke zjištění
kódové stránky. CURL podporuje samozřejmě také přenos opačným směrem, tedy
na vzdálený počítač. Jako hlavní přednost CURL vidím především možnost
podstatně ovlivnit datový přenos bez nutnosti složitého programování.
U neznámého kódování ještě existuje možnost nechat ho "odhadnout" na základě
heuristické analýzy. Neodhaduje se pouze kódová stránka, ale úplný typ dat
podle specifikace MIME. Slouží k tomu funkce mime_content_type(), která
je obsažena v rozšíření PHP převzatém z modulu mod_mime_magic serveru Apache.
Pro použití funkce je třeba mít PHP zkompilováno s direktivou
--with-mime-magic. I když spolehlivost odhadu samozřejmě není stoprocentní,
zvlaště u delších textů bývá kódování obvykle určeno správně.
Formuláře, odkazy s parametry
Pro interakci WWW stránek s uživateli se často používají HTML formuláře.
Hodnoty z jejich polí lze odesílat na server dvěma různými metodami:
GET a POST. Metoda GET vkládá hodnoty parametrů přímo do URL, metoda POST
je posílá v těle HTTP požadavku. Z hlediska programátora PHP je práce obou
metod ve většině případů shodná. Hodnoty polí formulářů jsou v PHP dostupné
jednak v superglobálních polích ($_GET, $_POST, resp. jejich zavržené
varianty $HTTP_GET_VARS a $HTTP_POST_VARS) a v závislosti na nastavení PHP
případně také přímo jako proměnné s názvy formulářových polí (nebezpečné,
nepoužívat!). Hodnoty se pro přenos kódují a po přenosu automaticky dekódují,
takže jsou k dispozici v původní podobě - a tedy i znakové sadě. Problémy
nastávají tehdy, když se liší kódování dokumentu s formulářem a dokumentu
generovaného na základě získaných informací. Ačkoliv se to může zdát
nepravděpodobné, v praxi jsem se s tím setkal už mnohokrát, a to i na
jinak velmi kvalitních WWW stránkách. Stává se to nejčastěji v případech, kdy
se data z formuláře odesílají na jiný stroj, než z kterého byl formulář
získán - nezřídka mívají stroje různé správce. Jeden z nich pak změní nastavení
kódové stránky a problém je na světě. Je třeba na to myslet a v podobných
situacích postupovat systematicky, aby se pak návštěvník stránek nedivil,
že se například místo "Tomáš" najednou jmenuje "Tomá+".
Někdy se místo formulářů používají odkazy s parametry. Tedy namísto tvorby
GET požadavku obsahujícího hodnoty polí formuláře se tyto hodnoty umístí
přímo do odkazu. Většinou se to sice používá pro číselné hodnoty, ale přesto
může vzniknout potřeba předávat nějaké texty. Ty je nutné vždy explicitně
zakódovat (pokud se nejedná o jednoduché případy, typicky o konstantní
řetězce v situacích, kdy je zjevné, že kódovat nepotřebují). K tomuto účelu
slouží funkce urlencode(), která provede totéž, co vykonávají WWW prohlížeče
při odesílání dat z formulářů. V PHP pak tedy získáme opět stejná data,
jako kdyby se odesílala z formuláře.
Nastavení národních specifik (locale)
Podobně jako operační systémy, umožňuje také PHP přizpůsobit chování funkcí
tak, aby výsledky odpovídaly zvyklostem u různých národů, resp. v různých
oblastech. Nastavit lze celkem 5 parametrů:
- LC_COLLATE - porovnávání řetězců
- LC_CTYPE - klasifikace a konverzi znaků (velká/malá písmena apod.)
- LC_MONETARY - peněžní formáty
- LC_NUMERIC - formátování čísel
- LC_TIME - formátování data a času
- LC_ALL - souhrnné nastavení všech parametrů současně
Parametry LC_COLLATE a LC_MONETARY nejsou v současných verzích PHP
implementovány, což poněkud snižuje "přirozenost" práce PHP z hlediska
národních zvyklostí (vadí to hlavně u LC_COLLATE).
Několik příkladů (pouze pro ilustraci, některé nemají valný smysl):
setlocale("LC_ALL","cs");
setlocale("LC_ALL","cs");
setlocale("LC_TIME","");
setlocale("LC_ALL","cs_CZ");
setlocale("LC_NUMERIC","en_GB");
První příklad ukazuje, jak nastavit česká specifika pro všechny kategorie.
Ve druhém se nastaví opět pro všechny, avšak potom se časové formátování
změní na hodnotu určenou v systémové proměnné (příp. v proměnné LANG).
Ve třetím příkladu se pracuje s variantami jazyků - čeština má pouze jedinou,
ale např. angličtina celou řadu; zde se u formátování času použije nastavení
pro Velkou Británii. Jak všechny příklady ukazují, k nastavení slouží
funkce setlocale(), která umožňuje také zjistit současné nastavení:
echo setlocale("0","");
Formátování čísel a finančních hodnot se dá zjistit také funkcí localeconv().
Tato funkce vrací pole obsahující hodnoty jednotlivých parametrů použitých
při formátování:
$loc = localeconv();
echo $loc["decimal_point"];
Kus kódu, uvedený jako příklad, vypíše aktuálně nastavený oddělovač desetinné
části čísla (tj. obvykle desetinnou čárku či tečku).
Kontrola pravopisu
V některých případech se nám může hodit kontrola pravopisu (resp. kontrola
správnosti zápisu jednotlivých slov). Zde máme přímo v PHP k dispozici dvě
možnosti. O jedné se zmíním pouze krátce - je to množina "aspell" funkcí,
která již není podporována, protože pracuje jen s velmi starými verzemi
knihovny aspell. Proto v dnešní době padne volba jednoznačně na funkce
pspell.
Funkce pspell nejenže pracují s novými verzemi knihovny
aspell, ale umožňují
používat uživatelské slovníky (jak persistentní, tak pouze v rámci session)
a nabízejí mnoho schopností navíc. Z množství funkcí upozorním na ty
nejdůležitější:
pspell_new - načte nový slovník
pspell_new_personal - načte nový slovník s uživatelským seznamem slov
pspell_check - zkontroluje slovo
pspell_suggest - nabídne možné tvary zápisu slova
pspell_store_replacement - uloží správný tvar pro chybně napsané slovo
pspell_add_to_personal - přidá slovo do uživatelského slovníku
pspell_add_to_session - přidá slovo do slovníku pro aktuální session
pspell_save_wordlist - uloží uživatelský slovník do souboru
Při používání slovníku je třeba dodržet určitý postup. Nejprve je nutno
slovník otevřít (čímž se získá odkaz na něj), pak se s ním pracuje dle potřeby
a na závěr obvykle uložíme slovník (aby se změny daly využít příště).
Některé funkce jsou bohaté na parametry, ne všechny je však třeba využít.
$id = pspell_new("cs", "", "", "iso8859-2", PSPELL_FAST);
if (pspell_check($id, $retezec)) {
echo "Správně";
} else {
echo "Chyba - může to být:";
$mozn = pspell_suggest($id, $retezec);
foreach ($mozn as $slovo) {
echo " $slovo";
}
}
Příklad ukazuje jednoduché použití funkcí pspell. Nejdříve se otevře slovník
pro češtinu (další dva parametry se používají pro další upřesnění slovníku,
zde nevyužity) v kódování ISO 8859-2, s využitím rychlého režimu hledání
podobných slov (funkce pspell_new() má zde plný počet parametrů - ale lze si
vystačit třeba i s jedním, např. pspell_new("cs")). Pak se zkontroluje slovo
v řetězci $retezec a vypíše se výsledek kontroly. Je-li slovo zapsáno chybně,
vytiskne se také nabídka možností.
Pro používání kontroly pravopisu bohužel není k dispozici na všech platformách,
například na Windows ho nenajdeme. Navíc je nutné mít k dispozici knihovny
aspell, a zkompilovat PHP se zapnutou podporou pspell. Konečně
poslední nepříjemností je odlišné chování některých funkcí se staršími
knihovnami aspell (aspell+pspell).
Tak to by bylo z této oblasti všechno, přestože tím není daná problematika
zdaleka vyčerpána. Příště se "zakousneme" do implementace vícejazyčných
aplikací. Těm budou věnovány dvě kapitoly, ta první se bude obecnými
záležitostmi a metodami implementace bez použití databáze.
Tento článek vyšel v prvním čísle časopisu PHP Magazín, který vydává společnost Software Media, s.r.o.
Další části seriálu:
|