15. díl - Tvorba knihoven v PHP

PHP Základní konstrukce Tvorba knihoven v PHP American English version English version

V minulém dílu seriálu tutoriálů se základy PHP jsme se naučili deklarovat vlastní funkce. V dnešním dílu se je naučíme logicky seskupovat do knihoven a vše si prakticky vyzkoušíme na jednoduché aplikaci.

Tvorba knihoven

Funkce obvykle nezapisujeme jen tak někam do stránky, ale vkládáme je do knihoven. Knihovna není nic jiného, než soubor s příponou .php, ve kterém na začátku otevřeme PHP sekvenci a poté do něj pod sebe vložíme několik funkcí. Knihovna by samozřejmě měla obsahovat jen ty funkce, které souvisí s jejím zaměřením. Pro každé zaměření si vytvoříme jinou knihovnu (např. emaily.php, matematika.php, databaze.php...) a vyvarujeme se tvoření "božských knihoven" všeho v jednom souboru.

Vytvořme si knihovnu k posílání emailů. Bude zatím obsahovat jen jednu funkci a tou bude ta z minulého dílu. Obsah knihovny emaily.php bude následující:

<?php

/*
 * Knihovna pro práci s emaily
 */

function odesliEmail($adresa, $predmet, $odesilatel, $zprava)
{
        $hlavicka = 'From:' . $odesilatel;
        $hlavicka .= "\nMIME-Version: 1.0\n";
        $hlavicka .= "Content-Type: text/html; charset=\"utf-8\"\n";
        $predmet = 'Nová zpráva z mailformu';
        $uspech = mb_send_mail($adresa, $predmet, $zprava, $hlavicka);
        return $uspech;
}

Funkcí můžeme do knihovny vložit samozřejmě kolik chceme, mohla by zde být např. ještě funkce, co kontroluje správnost zadané emailové adresy. Všimněte si, že na konci souboru chybí uzavření PHP sekvence. Je to z toho důvodu, že v knihovně je jen PHP kód, direktiva se sama uzavře, až se PHP dostane na konec souboru. Jedná se také o doporučení, protože pár bílých znaků za uzavřením PHP sekvence by mohlo v určitých případech vyvolat nepříjemné chyby.

Jakmile máme knihovnu hotovou, jednoduše ji uložíme do složky s webem a v souborech, ve kterých ji budeme chtít použít, ji načteme. Asi vás nepřekvapí, že načtení knihovny provedeme pomocí funkce require(). O té víme, že do souboru vloží obsah jiného souboru a to tak, že vykoná případné vložené skripty. V našem případě tedy deklaruje funkce, které knihovna obsahuje. Abychom se vyvarovali toho, že knihovnu omylem někde načteme i tehdy, když už je načtená, použijeme variantu require_once(). Ta nic neudělá v případě, že knihovna již byla načtena. Samozřejmě platí, že pokud zobrazujeme celý web pomocí index.php, stačí knihovnu načíst jen jednou zde. Pokud máme však oddělené stránky, musíme ji načíst na začátku každé stránky, ve které chceem funkce z knihovny používat.

require_once('emaily.php');
odesliEmail('vas@email.cz', 'Test emailu', 'odesilatel@seznam.cz', 'Text zprávy');

Funkce je deklarována v knihovně a nám stačí již jen knihovnu načíst a začít funkci používat. Pokud budete tento princip využívat, budou vaše aplikace velmi přehledné. Pojďme si procvičit práci s textovými řetězci a za tímto účelem si vytvořme vlastní knihovnu.

Analyzátor vět

Naprogramujme si jednoduchý analyzátor vět, kterému zadáme větu a on vypíše počet znaků ve větě, dále počet samohlásek, počet souhlásek a počet ostatních znaků.

Knihovna

Začneme knihovnou. Víme, že pro počet znaků máme funkci mb_strlen(). Zjištění počtu samohlásek a souhlásek za nás však již PHP neudělá a proto si na to založíme knihovnu. Pojmenujeme ji analyzaVet.php. Její obsah bude následující:

<?php

/**
 * Knihovna pro analýzu vět
 */

function pocetSamohlasek($text)
{
    $text = mb_strtoupper($text);
    $delka = mb_strlen($text);
    $samohlasky = array('A', 'E', 'I', 'O', 'U', 'Y');
    $pocet = 0;
    for ($i = 0; $i < $delka; $i++)
    {
        $znak = mb_substr($text, $i, 1);
        if (in_array($znak, $samohlasky))
            $pocet++;
    }
    return $pocet;
}

function pocetSouhlasek($text)
{
    $text = mb_strtoupper($text);
    $delka = mb_strlen($text);
    $souhlasky = array('B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Z');
    $pocet = 0;
    for ($i = 0; $i < $delka; $i++)
    {
        $znak = mb_substr($text, $i, 1);
        if (in_array($znak, $souhlasky))
            $pocet++;
    }
    return $pocet;
}

Každá funkce si nejprve definuje proměnné $text a $delka, kde je délka textu ve znacích. Do pole $samohlasky (resp. $souhlasky) si uloží znaky, jejichž počet nás zajímá. Dále si vytvoří proměnnou $pocet, do které dá počáteční hodnotu 0. Potom cyklem for projede všechny znaky a aktuální znak vždy uloží do proměnné $znak. Pomocí funkce in_array() zjistí, zda pole obsahuje daný znak. Pokud ano, započítá ho. Dále nezbývá nic jiného, než výslednou hodnotu vrátit.

Jistě jste si všimli, že se obě funkce liší jen obsahem pole. Můžeme kód výrazně optimalizovat tím, že vytvoříme univerzální funkci, která bere na vstupu řetězec a znaky, které nás zajímají. Tuto funkci budeme poté volat ve funkcích pocetSamohlasek() a pocetSouhlasek().

Obsah souboru s identickou funkcionalistou by mohl vypadat takto:

<?php

/**
 * Knihovna pro analýzu vět
 */

function pocetZnaku($text, $znaky)
{
    $text = mb_strtoupper($text);
    $delka = mb_strlen($text);

    $pocet = 0;
    for ($i = 0; $i < $delka; $i++)
    {
        $znak = mb_substr($text, $i, 1);
        if (in_array($znak, $znaky))
            $pocet++;
    }
    return $pocet;
}

function pocetSamohlasek($text)
{
    $samohlasky = array('A', 'E', 'I', 'O', 'U', 'Y');
    return pocetZnaku($text, $samohlasky);
}

function pocetSouhlasek($text)
{
    $souhlasky = array('B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Z');
    return pocetZnaku($text, $souhlasky);
}

Poměrně zajímavou úlohu jsme rozdělili do 3 funkcí. Vidíme, že funkce jsou našimi spojenci a dokáží nám zjednodušit život. Stačí totiž jen zavolat tu samou funkci s jinými parametry místo toho, abychom kopírovali celý kód znovu.

Nyní si vytvoříme soubor analyza.php, kam vložíme formulář na zadání věty, načteme knihovnu a pomocí ní zjistíme dané počty:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Analyzátor vět</title>
    </head>
    <body>
        <h1>Analyzátor vět</h1>

        <?php
            require_once('analyzaVet.php');

            if ($_POST)
            {
                if (isset($_POST['zprava']))
                {
                    $zprava = $_POST['zprava'];
                    $znaku = mb_strlen($zprava);
                    $samohlasek = pocetSamohlasek($zprava);
                    $souhlasek = pocetSouhlasek($zprava);
                    echo('<h2>Výsledek analýzy:</h2>');
                    echo('<table>');
                    echo('<tr><td>Znaků</td><td>' . htmlspecialchars($znaku) . '</td></tr>');
                    echo('<tr><td>Samohlásek</td><td>' . htmlspecialchars($samohlasek) . '</td></tr>');
                    echo('<tr><td>Souhlásek</td><td>' . htmlspecialchars($souhlasek) . '</td></tr>');
                    echo('</table>');
                }
            }

        ?>

        <p>Zadejte větu k analýze</p>
        <form method="post">
            <textarea name="zprava"></textarea><br />
            <input type="submit" value="Analyzovat" />
        </form>
    </body>
</html>

Výsledek:

Analyzátor vět v PHP

Zkuste se zamyslet nad tím, jak by vypadal zdrojový kód bez použití funkcí (nebyl by vůbec hezký). Diakritiku jsem neřešil, můžete si ji do polí přidat. Na knihovny se obvykle také vytváří nějaká složka, když je jich více.

Obecně je snaha co nejvíce logiky přesunou do knihoven (později objektů) a v souborech s HTML stránkou mít opravdu jen to nejnutnější. Toto je úplný základ oddělení logiky a výstupu. Časem se dostaneme např. k MVC architektuře, kde je tento princip doveden do dokonalosti. Knihovny a funkce si bohatě procvičíme v dalším seriálu o práci s databázemi.

Kam dál?

Náš arzenál znalostí je nyní připraven k tomu, abychom se pustili do databází. Pokračování seriálu naleznete v sekci Databáze v PHP pro začátečníky.


 

Stáhnout

Staženo 358x (1.31 kB)
Aplikace je včetně zdrojových kódů v jazyce php

 

  Aktivity (2)

Č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 (7 hlasů) :
55555


 


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

 

 

Komentáře
Zobrazit starší komentáře (10)

Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

Nechce se mi číst ten román, ale už první věta je špatně - "Ošetrovať stačí vždy iba tie vstupy, ktoré si získal priamo od používateľa". Ty nikdy nevíš která proměnná to je, protože ošetřuješ při výpisu, ne při zápisu. Když ti uživatel něco pošle, tak v tom může být XSS. Ale ty tu hodnotu uložíš do databáze (neošetřenou, protože do DB se ukládají surová data) a až při načtení z DB a při výpisu ji budeš ošetřovat a tam to už nepoznáš odkud byla.

Editováno 21.3.2014 16:36
Odpovědět 21.3.2014 16:36
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

Díky, opraveno.

Odpovědět 21.3.2014 16:41
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Mazwor
Člen
Avatar
Mazwor:

Ahoj,
děkuju za skvělé tutoriály, moc mi pomohly. Zatím jsem neměl s ničím problém, jen tentokrát jsem narazil na nesrovnalost.
Pochopil jsem správně podle 13. kapitoly ("S textovými řetězci lze v novějších verzích PHP pracovat jako s polem"), že tedy např. text 'ahoj' lze považovat za pole, kde znak a má index 0, znak h má index 1 a tak dále?
Snažil jsem se totiž u funkce vypisující počet samohlásek použít cyklus foreach následovně:

foreach ($text as $i) {
         if (in_array($i, $samohlasky)) {
             $pocet++;
         }
}

Doufal jsem, že nebude nutné použít funkci mb_substr(), ale při zadání prostého textu (např. $text = 'ahoj') na mě vyskočila chyba. Když jsem pak zkusil do vstupu jako proměnnou $text zadat pole (např. $text = array('a', 'h', 'o', 'j')), vše běželo v pořádku a výstup mi vypsal číslo 2 (dvě samohlásky).
Dělám někde chybu nebo pouze příkaz foreach nedokáže samostatný text zpracovávat jako pole?

Předem moc díky za odpověď, snad jsem vše popsal srozumitelně, teprve s programováním začínám, tak doufám, že jsem nenapsal úplnou hloupost :D.

Editováno 18.7.2014 1:14
Odpovědět 18.7.2014 1:12
Pořádek je pro blbce, inteligent ovládá chaos. :D
Avatar
Odpovídá na Mazwor
Martin Konečný (pavelco1998):

Foreach požaduje jako parametr pole, řetězec nebere. Můžeš si ten text do pole nacpat pomocí funkce str_split(). Ta ale neumí pracovat s UTF-8 řetězci.
Možná k tomu pomůže článek na stackoverflow.com:

http://stackoverflow.com/…ray-of-chars

 
Odpovědět 18.7.2014 1:26
Avatar
Mazwor
Člen
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Mazwor:

Super, moc díky za rychlou odpověď! :)
Tak nějak jsem předpokládal, že problém bude v tom, že si foreach řetězec nedokáže přebrat jako pole, jen mě zmátla ta poznámka z předešlých kapitol, kde bylo řečeno, že lze string za pole považovat (a bylo tak s ním i částečně nakládáno). Je to tedy nejspíš tak, že se sice textový řetězec za určitých podmínek jako pole chová, ale je nutné to brát s rezervou (?). Teď už je mi vše jasné, díky.

Odpovědět 18.7.2014 1:48
Pořádek je pro blbce, inteligent ovládá chaos. :D
Avatar
Odpovídá na Mazwor
Martin Konečný (pavelco1998):

Popravdě to neznám tak detailně, takže ti neřeknu, jak přesně se to chová na úrovni bitů, ale co znám, tak řetězec sám o sobě polem není, jen můžeš přistoupit k jeho bytům pomocí indexu (jako u pole). Tzn. že třeba u:

$string = "ahoj";
echo $string[0];

ti to vypíše první byte toho stringu (čili 'a').

 
Odpovědět 18.7.2014 11:46
Avatar
filiploja
Člen
Avatar
filiploja:

Fakt veľmi dobrý tutorál. Chcel by som sa ale opýtať, snažil som sa to naprogramovať použitím foreach ale funguje mi to len s písmenami bez diakritiky, ako náhle zadám á é č tak tie písmená nezapočíta aj keď som ich do pola prial. V čom môže byť chyba?

function pocet($text)
      {$text=mb_strtoupper($text);
       $pole=array('Á','A', 'É', 'Í','Č');
       $dlzka=mb_strlen($text);
       $pocet=0;

       for ($i=0;$i<$dlzka;$i++)
         foreach ($pole as $index => $hodnota)
           if ($text[$i]===$hodnota)
             $pocet++;

       return $pocet;}
 
Odpovědět 31.3.2015 16:17
Avatar
MArtin
Člen
Avatar
MArtin:

Ja by som sa chcel opytat, ze ked chcem prerobit projekt do OOP a mam kniznicu s jednoduchymi funkciami, ktore spolu nesuvisia a mozu byt pouzite na viacerych miestach vramci projeku, je v poriadku nacitat takuto kniznicu s funkciammi rovno niekde na zaciatku alebo je lepsie vytvorit nejaky class kontainer a pristupovat k nim staticky? Alebo existuje ina metoda?

 
Odpovědět 30.10.2015 15:55
Avatar
Odpovídá na filiploja
Martin Konečný (pavelco1998):

Chyba je v tom, že se to nebere po znacích, ale po bytech. Písmena jako ěšč atd. mají byty dva (aspon myslim), proto ti to vypíše nějakou blbost.

 
Odpovědět  +1 30.10.2015 17:32
Avatar
Filip Šohajek
Redaktor
Avatar
Odpovídá na filiploja
Filip Šohajek:

Jak říká Martin Konečný (pavelco1998).
Změň

$text=mb_strtoupper($text);

na

$text=preg_split("//u", mb_strtoupper($text));
 
Odpovědět 30.10.2015 18:23
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 10 zpráv z 20. Zobrazit vše