13. díl - Funkce pro práci s řetězci v PHP

PHP Základní konstrukce Funkce pro práci s řetězci v PHP American English version English version

V minulém dílu seriálu tutoriálů se základy PHP jsme si ukázali práci s polem pomocí cyklu. V dnešním dílu řetězce dobereme a ukážeme si PHP funkce, které s nimi pracují.

Textové řetězce a UTF-8

Část PHP funkcí pro práci s řetězci začíná prefixem mb_. Je to z toho důvodu, že tyto funkce podporují UTF-8 kódování (MB jako MultiByte). V kódování UTF-8 se píše naprostá většina webů, protože umí většinu znaků většiny národních abeced. Není tedy problém na webu použít češtinu, dále citovat něco rusky nebo používat speciální znaky jako ☺ ♥. Většina IDE (např. NetBeans) tvoří projekty vždy jako UTF-8. Pokud UTF-8 nepoužíváte, setkáte se časem s velkými problémy, např. tehdy, když budete chtít použít nějakou cizí knihovnu. Její autor totiž určitě počítá s tím, že UTFko používáte.

Jakmile v aplikaci používáme tyto funkce, musíme často nejprve nastavit kódování, jinak nebudou korektně fungovat ve starších verzích PHP. Kódování stačí nastavit jen jednou v každém požadavku. Pokud se celý váš web zobrazuje přes index, jak jsme si zde ukazovali, stačí nastavení vložit pouze na začátek indexu.

mb_internal_encoding("UTF-8");

Délka řetězce

Délku řetězce ve znacích získáme pomocí funkce mb_strlen(). Udělejme si malou ukázku, samozřejmě si nad ní vložte ještě řádek výše, který nastaví kódování.

$text = "Černé díry jsou tam, kde bůh dělil nulou";
$delka = mb_strlen($text);
echo("Délka textu je $delka znaků.");

Výstup:

Délka textu je 40 znaků.

Pozn.: V zastaralých učebnicích a tutoriálech naleznete použití funkcí bez prefixu mb_. Tedy místo mb_strlen() jen strlen(). Tyto funkce nikdy nepoužívejte, jelikož neumí UTF-8 a budou vám vracet špatný výstup. Např. "Č" je v UTF kódování uloženo jako 2 znaky (2 bajty, jako háček a c). Funkce s prefixem mb_ bere č jako jeden znak, funkce bez tohoto prefixu ho bere jako 2 znaky. Vrací tedy špatně délku řetězců s diakritikou a nedokáže rozeznat o která písmena se jedná. PHP obsahuje z důvodu zpětné kompatibility mnoho funkcí, které UTF kódování nepodporují, měli byste se vždy podívat, zda je funkce tzv. multibyte-safe a případně najít její multibyte variantu.

Práce s podřetězci

Určitému úseku řetězce říkáme podřetězec. Ukažme si nějaké příklady s podřetězci, jelikož s těmi budeme často pracovat.

Zjištění pozice podřetězce

Pokud chceme zjistit, na jaké pozici se v řetězci nachází konkrétní podřetězec nebo zda ho text vůbec obsahuje, použijeme funkci mb_strpos(). Abychom si to udělali zajímavější, budeme chtít, aby nám nezáleželo na velikosti písmen. Z toho důvodu nejprve celý řetězec převedeme na velká písmena pomocí funkce mb_strtoupper() a poté v něm budeme hledat podřetězec, též velkými písmeny.

$retezec = mb_strtoupper('PHP tutoriály na Devbooku.');
$podretezec = mb_strtoupper('devbook');

if (mb_strpos($retezec, $podretezec) !== false)
        echo "Nalezeno";
else
        echo("Nenalezeno");

Výstup:

Nalezeno

mb_strpos() vrací 0 v případě, že je podřetězec na první pozici a false v případě, že nebyl nalezen. Z tohoto důvodu je nutné výsledek porovnávat i s ohledem na datový typ, jak jsme se to učili u podmínek. Jinak by bylo false a 0 vyhodnoceno stejně a podřetězec by nebyl nalezen v případě, že by jím řetězec začínal.

K funkci mb_strpos() existuje ještě funkce mb_strrpos() (r navíc jako reverse), která funguje úplně stejně, jen vyhledává od konce řetězce. Hodí se např. když zjišťujeme příponu souboru.

V problematice vyhledávání podřetězců se řetězci často říká kupka sena (haystack) a podřetězci jehla (needle).

Získání podřetězce podle pozice

Podřetězec získáme pomocí funkce mb_substr(), která bere v parametrech řetězec, index, od kterého podřetězec začíná a délku podřetězce. Zkusme si to:

$text = "Černé díry jsou tam, kde bůh dělil nulou.";
echo mb_substr($text, 6, 4);

Výstup:

díry

Získali jsme podřetězec od 7. znaku, dlouhý 4 znaky.

Přístup k určitému znaku

S textovými řetězci lze v novějších verzích PHP pracovat jako s polem a to tímto způsobem:

$text = "Nějaký text";
echo $text[0];

Podobného výsledku šlo docílit v minulosti i pomocí složených závorek, ale tato syntaxe byla z PHP odstraněna. Kód výše vypíše 1. znak. Bohužel tento způsob ještě nepodporuje Unicode (UTF-8) a proto ho nepoužívejte. Pokud potřebujete přistoupit k nějakému znaku, jednoduše ho zkopírujte jako podřetězec pomocí výše zmíněné funkce mb_substr().

Nahrazení podřetězce

V textu můžeme velmi jednoduše nahradit nějaký podřetězec jiným. Docílíme toho použitím funkce str_replace a můžeme tak jednoduše zabezpečit např. emailovou adresu před spamboty tak, že znak zavináče nahradíme textem "(zavináč)". Roboti pak nepoznají, že se jedná o email a nebudou vám nabízet výhodné půjčky :)

$adresa = 'devbook@devbook.cz';
$osetrenaAdresa = str_replace('@', '(zavináč)', $adresa);
echo $osetrenaAdresa;

Výstup:

devbook(zavináč)devbook.cz

Pokud by v textu bylo více takových podřetězců, funkce nahradí všechny.

Nahrazení podle slovníku

Pokud potřebujeme provést více nahrazení, PHP nabízí funkci strtr (jako STRing TRanslate, ano, pojmenování mnoha funkcí je v PHP velmi zavádějící). Funkce bere v parametrech řetězec a slovník, kde jsou jako klíče podřetězce, které chceme nahradit a jako hodnoty řetězce, kterými je chceme nahradit.

Funkce se často používá k nahrazení textových smajlíků v nějakém textu za HTML obrázky. Zkusme si to:

$slovnik = array(
        ':)' => '<img src="usmev.png" alt="úsměv" />',
        ':D' => '<img src="smich.png" alt="smích" />',
);
echo strtr('Ahoj :) Je mi fajn, protože jsem objevil devbook :D', $slovnik);

Výstup:

Ahoj <img src="usmev.png" alt="úsměv" /> Je mi fajn, protože jsem objevil devbook <img src="smich.png" alt="smích" />'

Rozdělení řetězce na pole podřetězců

Velmi užitečnou dvojicí funkcí jsou expresivně pojmenované explode() a implode(). Explode() rozdělí řetězec na pole podřetězců pomocí určitého oddělovače. Implode() naopak spojí podřetězce v poli do jednoho dlouhého řetězce a mezi podřetězce vloží oddělovač. Oddělovači se někdy expresivně říká lepidlo.

Níže uvedený jednoduchý program bere na vstupu řetězec s několika čísly, které jsou oddělené čárkou. Z těchto čísel následně vypočítá součet.

$vstup = "1,5,87,65,42,4,456,8,5,98,54,89";
$cisla = explode(',', $vstup);
echo array_sum($cisla);

Explode() rozdělí řetězec podle čárky a vrátí pole jeho částí. Pomocí funkce array_sum() následně získáme součet prvků v poli. Pokud přicházíte z nějakého nízkého jazyka, asi se divíte, jak je v PHP vše jednoduché. Je to z toho důvodu, že PHP je tzv. vysoký jazyk. Právě díky tomu můžeme svou energii zaměřit na vývoj aplikace a ne na řešení základních problémů.

PHP funkce pro práci s řetězci

Na závěr si uveďme seznam těch nejdůležitějších funkcí, které nám PHP pro práci s řetězci nabízí. Každou si můžete rozkliknout a podívat se, jak se používá. Opět je nemusíte umět nazpaměť, stačí vědět, že tam jsou a že si je v případě potřeby můžete vyhledat.

mb_internal_en­coding Nastavení kódování.
mb_strlen Získá délku řetězce.
mb_strpos Najde pozici prvního výskytu podřetězce v řetězci.
mb_substr Vrátí podřetězec od startovní pozice s určitým počtem znaků.
mb_strtoupper Převede všechna písmena v rětězci na velká.
mb_strtolower Převede všechna písmena v rětězci na malá.
trim Odstraní bílé místo na okolo řetězce.
htmlspecialchars Převede speciální znaky v textu na HTML entity.
htmlspecialchar­s_decode Převede entity v textu zpět na speciální znaky.
strip_tags Odstraní z daného řětězce HTML tagy.
nl2br Nahradí konce řádků (\n) tagem <br />
str_replace Nahradí všechny výskyty podřetězce v řetězci daným podřetězcem.
strtr Přeloží podřetězce podle slovníku.
parse_str Rozbalí proměnné z textového řetězce ve tvaru QUERY stringu.
explode Převede řetězec na pole podřetězců.
implode Zabalí pole do textového řetězce.
hash Vypočítá otisk (hash) řetězce, což budeme potřebovat pro ukládání hesel.

V příštím dílu si ukážeme, jak v PHP deklarovat vlastní funkce.


 

  Aktivity (3)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (10 hlasů) :
4.74.74.74.74.7


 


Miniatura
Předchozí článek
Cvičení k 12. lekci PHP
Miniatura
Všechny články v sekci
Základní konstrukce jazyka PHP
Miniatura
Následující článek
Cvičení k 13. lekci PHP

 

 

Komentáře

Avatar
Samuel Illo
Redaktor
Avatar
Samuel Illo :

Zaujíma ma jedna vec :D

$retezec = mb_strtoupper('PHP tutoriály na Devbooku.');
$podretezec = mb_strtoupper('devbook');

if (mb_strpos($retezec, $podretezec) **!== false**)
        echo "Nalezeno";
else
        echo("Nenalezeno");

prečo tam je !== false, keď to funguje aj s == true?
True je podľa mňa jednoduchšie na zapísanie...
Dik za odpoveď.

Editováno 28.7.2014 13:41
Odpovědět  +1 28.7.2014 13:40
www.samuelillo.com; lamka02sk(zavináč)samuelillo.com, www.point.samuelillo.com, www.csgorig.eu
Avatar
Matúš Petrofčík
Šéfredaktor
Avatar
Odpovídá na Samuel Illo
Matúš Petrofčík:
dačo !== false

je to isté ako

dačo === true

v tomto prípade je tam ale false zámerne!
podľa www.php.net - mb_strpos — Find position of first occurrence of string in a string
teda, funkcia mb_strpos vráti pozíciu kde sa nachádza hľadané slovo, a ak tam to slovo nenájde vráti false

problém je, že ak by bolo hľadané slovo hneď na začiatku prehľadávaného stringu, vypísalo by 0 (nula) čo je síce tiež false, ale práve preto v podmienke použijeme !== false namiesto != false

True by si mohol použiť, ale ak by to hľadané slovo bolo hneď na začiatku stringu, tak by sa vrátilo pozícia/číslo 0, čo znamená false, a tým by došlo k chybe

Odpovědět  +2 28.7.2014 13:49
obsah kocky = r^2 ... a preto vlak drnká
Avatar
Samuel Illo
Redaktor
Avatar
Odpovědět 28.7.2014 14:00
www.samuelillo.com; lamka02sk(zavináč)samuelillo.com, www.point.samuelillo.com, www.csgorig.eu
Avatar
Matúš Petrofčík
Šéfredaktor
Avatar
Odpovídá na Samuel Illo
Matúš Petrofčík:

zamálo, snáď som ti dal pravdivé informácie :D

Odpovědět 28.7.2014 18:05
obsah kocky = r^2 ... a preto vlak drnká
Avatar
Jaroslav Polívka:

Ahoj, porovnávám dva řetězce a napadají mě dvě možnosti:

$var1 = "Hello";
$var2 = "Hello";
if (strcmp($var1, $var2) !== 0)
echo 'Neshoda';
else
echo 'Shoda';

a

$retezec='domovník';
$podretezec='domov';
echo('<br>');
if ( (mb_strpos($retezec, $podretezec) === 0) && (mb_strlen($retezec) === mb_strlen($podretezec)) )
        echo "Shoda";
else
        echo("Neshoda");

Vím, že Dave v článku nedoporučuje užití non mb_ fcí, je strcmp() nebezpečná, popř. jak jinak porovnávat shodu dvou řetězců?

Díky

Odpovědět 22. února 12:14
Velice často si věci žijí svým životem
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Jaroslav Polívka:

Hmm Marťas, asi jo, ale ošívám se nad tím :-) , string nerad porovnávám takhle přímo typovým operátorem rovná se, ono tohle asi php snese, ale třeba z JAVY a C mám zažito, že na string vždy metodami.

Díky

Odpovědět 22. února 16:48
Velice často si věci žijí svým životem
Avatar
Odpovídá na Jaroslav Polívka
Martin Konečný (pavelco1998):

je pravda, že jinde se to řeší jinak a popravdě ani nevim proč. Taky si nejsem jistý, zda ti to klasické porovnání vezme jakékoliv řetězce, ale nikdy jsem s tím v PHP problém neměl.
Ale jestli ti to udělá radost a chceš to řešit metodami, také jsem slyšel o funkci strcasecmp a bylo to od pana Vrány :D

 
Odpovědět 22. února 17:21
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 8 zpráv z 8.