IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

4. diel - Knižnica StringUtils pre prácu s textom v PHP

V minulej lekcii, Dokončenie knižnice DateUtils v PHP , sme dokončili knižnicu DateUtils, ktorá uľahčuje formátovanie a parsování českého dátumu a času. V dnešnom dieli si naprogramujeme knižnicu StringUtils.

Motivácia

PHP poskytuje bohatú škálu funkcií pre prácu s textovými reťazcami. Niektoré dôležité funkcie tu však úplne chýba a my ich preto musíme implementovať sami a stále znovu a znovu.

StringUtils

Do knižnice StringUtils vložíme niekoľko užitočných funkcií, ktoré PHP chýba. Trieda je pomocný charakter, nebude mať žiadny vnútorný stav a jej funkcie budeme opäť používať často a na mnohých miestach našich aplikácií. Preto budú všetky jej metódy statické.

class StringUtils
{

}

Triedu si môžete vložiť do menného priestoru Utility. Hoci je to snáď samozrejmé, radšej pripomeniem, že pre vnútorné implementáciu budeme používať výhradne PHP funkcie s prefixom mb_, ktoré podporujú unicode.

StartsWith () a endsWith ()

Často by sme potrebovali vedieť, či nejaký text začína alebo končí určitým podreťazcom. Napr. dekóduje nejaké položky a práve podľa častí ich názvu sa chceme orientovať. EndsWith () sa hodí najmä pre autoloader, kde podľa koncovky názvu triedy určujeme z akej zložky sa má načítať.

public static function startsWith($haystack, $needle)
{
    return (mb_strpos($haystack, $needle) === 0);
}

public static function endsWith($haystack, $needle)
{
    return ((mb_strlen($haystack) >= mb_strlen($needle)) && ((mb_strpos($haystack, $needle, mb_strlen($haystack) - mb_strlen($needle))) !== false));
}

Metódy berú v prvom parametri prehľadávaný text a v druhom hľadaný podreťazec. V anglickej literatúre sa pri problémoch prehľadávaní používajú označenie kôpka sena (haystack) a ihla (needle). Asi tušíte prečo :)

Na startsWith () nie je nič zložité, len musíme použiť trojrovnítko, pretože mb_strpos () vracia false pri neúspechu a 0 pri nájdení na prvej pozícii.

EndsWith () je už zaujímavejšie. Kupka musí byť dlhšia alebo aspoň rovnako dlhá ako ihla, inak v nej nemá zmysel hľadať. Ďalej necháme funkciu mb_strpos () prehľadať kôpku až od tej pozície, kde by mohla ihla začínať (dĺžka kôpky - dĺžka ihly), predchádzajúce výskyty nás nezaujímajú.

Funkcia vyskúšajme, nezabudnite nastaviť interné kódovanie na UTF-8:

require_once('models/System/Utility/StringUtils.php');
mb_internal_encoding('utf-8');
var_dump(StringUtils::startsWith('Čtvrtletní hodnocení', 'Čtvrtletní'));
var_dump(StringUtils::startsWith('Pololetní hodnocení', 'Čtvrtletní'));
var_dump(StringUtils::startsWith('Pololetní a čtvrtletní hodnocení', 'Čtvrtletní'));
var_dump(StringUtils::endsWith('ArticleController', 'Controller'));
var_dump(StringUtils::endsWith('ArticleHelperController', 'Helper'));

výsledok:

PHP knižnica StringUtils – StartsWith a EndsWith - Knižnice pre PHP

Capitalize () a uncapitalize ()

Vyššie uvedené funkcie prevedú začiatočné písmeno reťazca na veľký alebo na malý tvar. Capitalize () sa nám hodí pri výpise napr. Tabuľkových dát, kde chceme, aby užívateľ videl hodnoty s počiatočným veľkým písmenom, ale vnútorne sa s nimi nejako pracuje a preto sú malými písmenami. Uncapitalize () prvé písmeno naopak zmenší. Obe funkcie budeme využívať ešte pre vnútorné potreby knižnice.

Pozn. uncapitalize je pravdepodobne nasprávný anglický tvar, však mi pripadá zrejmejšie, než napr. lowerFirst alebo niečo podobné.

public static function capitalize($text)
{
    return mb_strtoupper(mb_substr($text, 0, 1)) . mb_substr($text, 1, mb_strlen($text));
}

public static function uncapitalize($text)
{
    return mb_strtolower(mb_substr($text, 0, 1)) . mb_substr($text, 1, mb_strlen($text));
}

Kód je zrejmý, poďme ho teda vyskúšať:

echo(StringUtils::capitalize('žluťoučký kůň') . '<br />');
echo(StringUtils::uncapitalize('Žluťoučký kůň') . '<br />');

výsledok:

PHP knižnica StringUtils – Capitalize a Uncapitalize - Knižnice pre PHP

Skrátenie textu

Často vypisujeme nejaké popisky napr. K položkám v eshope a chceme, aby mal popisok nejaký maximálny počet znakov, pretože dlhší text sa k tovaru v danej šablóne nezmestí. Ak je text dlhší, než určitá maximálna dĺžka, potrebujeme ho skrátiť a pridať na koniec tri bodky, aby bolo jasné, že časť chýba. Ak bol kratší, nepridávame nič. Maximálna dĺžka sa počíta už s prípadnými bodkami.

public static function shorten($text, $length)
{
    if (mb_strlen($text) - 3 > $length)
        $text = mb_substr($text, 0, $length - 3) . '...';
    return $text;
}

Metódu niekedy nájdete vo frameworkoch pod názvom truncate. Môžeme vyskúšať:

echo(StringUtils::shorten('Notebook - Intel Pentium 2020M Ivy Bridge, 15.6" LED 1366x768 lesklý, RAM 4GB, Intel HD Graphics, HDD 500GB 5400 otáček, DVD, WiFi, Bluetooth, Webkamera, USB 3.0, Windows 8 64-bit', 71) . '<br />');
echo(StringUtils::shorten('Notebook - Intel Pentium 2020M', 71) . '<br />');

Výsledok som schválne odťal u znaku s diakritikou, všetko funguje správne:

PHP knižnica StringUtils – Skrátenie textu - Knižnice pre PHP

Odstránenie diakritiky

Dnešný diel zakončíme odstránením diakritiky. To je často potrebné, keď vyrábame napr. Z mena emailovú adresu daného človeka, z názvu článku jeho URL adresu, ak chceme overiť, že používateľ nezadal do hesla diakritiku (heslo musí byť zhodné s heslom bez diakritiky, inak je v ňom diakritika) a podobne.

Priznám sa, že kód metódy som vygooglil, presnejšie ho vygooglil sczdavos :) . Ukážme si ho:

public static function removeAccents($text) {
    $chars = array(
        // Decompositions for Latin-1 Supplement
        chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
        chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
        chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
        chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
        chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
        chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
        chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
        chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
        chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
        chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
        chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
        chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
        chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
        chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
        chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
        chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
        chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
        chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
        chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
        chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
        chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
        chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
        chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
        chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
        chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
        chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
        chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
        chr(195).chr(191) => 'y',
        // Decompositions for Latin Extended-A
        chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
        chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
        chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
        chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
        chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
        chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
        chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
        chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
        chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
        chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
        chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
        chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
        chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
        chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
        chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
        chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
        chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
        chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
        chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
        chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
        chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
        chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
        chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
        chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
        chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
        chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
        chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
        chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
        chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
        chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
        chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
        chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
        chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
        chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
        chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
        chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
        chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
        chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
        chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
        chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
        chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
        chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
        chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
        chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
        chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
        chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
        chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
        chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
        chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
        chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
        chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
        chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
        chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
        chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
        chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
        chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
        chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
        chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
        chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
        chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
        chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
        chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
        chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
        chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
        // Euro Sign
        chr(226).chr(130).chr(172) => 'E',
        // GBP (Pound) Sign
        chr(194).chr(163) => ''
    );
    return strtr($text, $chars);
}

Ide vlastne len o výpočet diakritických znakov, ktoré sú v UTF-8 reprezentované ako niekoľko ASCII znakov za sebou (napr. Háčik ac). Výpočet je zapísaný ako pole, aby pomocou neho mohla následne PHP funkcie strtr () vykonať nahradenie.

Kód je súčasťou metódy nejakého modulu WordPress (konkrétne tu: https://core.trac.wordpress.org/...rmatting.php), kde je výpočet ešte oveľa dlhší, nám však bude tento stačiť.

Metódu vyskúšajme:

echo(StringUtils::removeAccents('Příliš žluťoučký kůň úpěl ďábelské ódy. PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ ÓDY. <br />'));
echo(StringUtils::removeAccents('Příliš žluťoučký kůň úpěl ďábelské ódy. PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ ÓDY. <br />'));

výsledok:

PHP knižnica StringUtils – Odstránenie diakritiky - Knižnice pre PHP

To by bolo pre dnešok všetko. Nabudúce, v lekcii Dokončenie knižnice StringUtils v PHP , StringUtils dokončíme.


 

Predchádzajúci článok
Dokončenie knižnice DateUtils v PHP
Všetky články v sekcii
Knižnice pre PHP
Preskočiť článok
(neodporúčame)
Dokončenie knižnice StringUtils v PHP
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity