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í.

Lekce 5 - První objektová komponenta v PHP - Galerie obrázků

Na dnešek si vytvoříme galerii obrázků.

Motivace

Často chceme na našich stránkách zobrazit nějakou galerii obrázků, ať již se jedná o fotky z dovolené nebo o screenshoty našeho programu. Psát ručně HTML tabulku s obrázky je poněkud pracné, hlavně když jich je v dané složce hodně. Budeme tedy chtít zautomatizovat výpis obrázků z nějaké složky do přehledné tabulky a nejlépe pomocí objektové komponenty, kterou budeme moci používat vícekrát a třeba i na více webech.

Založení struktury projektu

Vytvoříme si novou složku pro projekt, já jsem ji pojmenoval galerie/. V ní vytvoříme soubor index.php a složku tridy/, ve které vytvoříme soubor Galerie.php. Nakonec vytvoříme složku s obrázky, tu jsem pojmenoval jednoduše obrazky/. Do ní si připravíme několik obrázků, já jsem použil ty výchozí "Ukázky obrázků" z operačního systému Windows. Ke každému obrázku je nutné vytvořit ještě jeho miniaturu (třeba v grafickým nástroji GIMP). Mohlo by to za nás dělat PHP při nahrávání obrázků, ale nahrávání již není předmětem tohoto tutoriálu a můžeme ho dodělat někdy jindy. Zvolil jsem si, že miniatura bude široká 160px a její název bude vždy končit na _nahled. Vaše složka by mohla vypadat třeba nějak takto:

Složka s obrázky pro PHP Galerii - Objektově orientované programování (OOP) v PHP

Galerie

Máme připravená data a strukturu, pusťme se do programování. Začneme samozřejmě třídou Galerie, jejíž instance bude reprezentovat galerii obrázků. Pojďme si promyslet, jaké atributy bude třída mít.

Atributy

Budeme chtít určit kolik náhledů se má zobrazit v jednom řádku, tedy kolik sloupců bude mít tabulka s obrázky. Dále budeme chtít samozřejmě uchovávat cestu ke složce s obrázky. Ani jeden atribut není důvod zpřístupňovat zvenčí, stačí, když si je necháme zadat v konstruktoru.

Kód třídy s těmito atributy a konstruktorem bude vypadat následovně:

class Galerie
{

    public function __construct(private string $slozka, private int $sloupcu) {}

}

Metody

Přejděme k metodám. Jednu ve třídě již samozřejmě máme (konstruktor), přidáme tam 2 další.

nacti()

Metoda nacti() prohledá složku a uloží si do paměti náhledy obrázků. K prohledání složky nám PHP nabízí třídu Directory. Vzpomínáte si, jak jsme si říkali, že se v PHP začínají objevovat objekty? Directory je jedním z nich. Bohužel lze instanci vytvořit jen pomocí funkce dir(), no, nic není dokonalé. Na instanci nás zajímají 2 metody:

  • read() - Načte obsah dalšího souboru nebo složky ve složce a vrátí ho jako textový řetězec
  • close() - Ukončí čtení složky

Naše metoda nacti() by mohla vypadat prozatím takto:

public function nacti(): void
{
    $slozka = dir($this->slozka);

    while ($polozka = $slozka->read()) {
        // TODO
    }
    $slozka->close();
}

Vytvoříme si instanci Directory a pomocí metody read() čteme postupně složky a soubory v této složce. Metoda vrátí hodnotu false v případě, že jsme se prokousali až na "konec" složky (za poslední soubor nebo složku). Díky tomu můžeme dát načítání názvu souboru do while cyklu, který skončí ve chvíli, kdy načteme poslední. Název budeme mít uvnitř cyklu dostupný v proměnné $polozka. Možná je trochu nezvyklé, že v podmínce while cyklu provádíme rovnou i přiřazení do proměnné, ale dělá se to tak velmi často.

Každý soubor nyní načítáme 2× (miniatura + originál) a k tomu nám funkce ještě vrátí vždy 2 složky navíc. Jsou to složky s názvem . a .., které označují současnou a nadřazenou složku. My budeme chtít zobrazovat jen miniatury, proto do cyklu umístíme podmínku, že nás zajímají pouze soubory, obsahující v názvu _nahled.. Tyto soubory si uložíme do pole. Jelikož chceme, aby bylo toto pole přístupné pro metodu vypis(), musíme ho přidat třídě jako privátní atribut:

private array $soubory = array();

Nyní se přesuňme do těla cyklu while a přidejme název souboru do našeho pole pokaždé, když se jedná o náhled. Použijeme k tomu funkci strpos(), která vrací pozici podřetězce v řetězci. Pokud se v názvu položky vyskytuje od druhého znaku někde text _nahled., bude položka přidána do našeho pole. Pokud ne, funkce vrátí hodnotu false. Pro jistotu ještě přidáme podmínku kontrolující, zda je daná položka skutečně souborem a ne adresářem. K tomu nám poslouží funkce is_file(), která přijímá jako argument cestu k položce a vrací hodnotu true, jedná-li se o soubor:

if (strpos($polozka, '_nahled.') && is_file($this->slozka . '/' . $polozka)) {
    $this->soubory[] = $polozka;
}

Funkce strpos() vrátí hodnotu 0 v případě, že řetězec podřetězcem začíná (protože 0 označuje první pozici). V našem případě by se hodnota 0 vyhodnotila jako nepravda a podmínka by neplatila. To je správně, soubor _nahled.jpg by se vázal k obrázku bez názvu a není tedy platný. Pokud bychom však chtěli opodmínkovat kompletně výskyt podřetězce, třeba v jiné aplikaci, používá se k odlišení 0 a hodnoty false operátor !== takto:

if (strpos($polozka, '_nahled.') !== false) {
    $this->soubory[] = $polozka;
}

Nyní podmínka neprojde pouze s hodnotou false a projde s hodnotou 0. V našem případě se nám však spíše hodí první varianta.

vypis()

Tu složitější část máme za sebou, přesuňme se nyní k výpisu HTML tabulky, tedy k metodě vypis(). I když by načtení i výpis mohly být v jedné metodě, jedná se o 2 logické úlohy a proto je lepší je rozdělit do 2 metod. Metoda by měla dělat vždy jednu věc a měli bychom ji být schopni popsat bez spojky a. Tedy "Metoda zobraz() zobrazí HTML tabulku s náhledy", nikoli "Metoda zobraz() načte a zobrazí galerii".

Metoda vypis() vyechuje začátek tabulky. Dále proiterujeme cyklem foreach miniatury a ty vyechujeme do buňky tabulky jako tag <img>. Kolem tagu <img> samozřejmě uděláme odkaz na originální obrázek. Ten získáme velmi jednoduše, stačí v názvu miniatury nahradit _nahled. za .. Nahrazení provedeme funkcí str_replace(). Aby nebyla celá tabulka v jednom řádku, budeme si počítat kolikátý sloupec vypisujeme. Jakmile dosáhneme hodnoty nastavené v atributu $sloupcu, uzavřeme řádek, začneme nový a vynulujeme počítadlo sloupců.

Kód metody vypis() by mohl vypadat nějak takto:

public function vypis(): void
{
    echo('<table id="galerie"><tr>');
    $sloupec = 0;
    foreach ($this->soubory as $soubor) {
        $nahled = $this->slozka . '/' . $soubor;
        $obrazek = $this->slozka . '/' . str_replace('_nahled.', '.', $soubor);
        echo('<td><a href="' . htmlspecialchars($obrazek) . '"><img src="' . htmlspecialchars($nahled) . '" alt=""></a></td>');
        $sloupec++;
        if ($sloupec >= $this->sloupcu) {
            echo('</tr><tr>');
            $sloupec = 0;
        }
    }
    echo('</tr></table>');
}

Použití

Přesuneme se do index.php, vložíme sem základní HTML strukturu a vytvoříme instanci galerie. Do konstruktoru předáme složku a počet sloupců. Následně zavoláme nacti() a vypis().

<!DOCTYPE html>
<html lang="cs-cz">
<head>
    <meta charset="utf-8" />
    <title>Galerie obrázků</title>
</head>

<body>
    <h1>Galerie obrázků</h1>
    <?php
    require_once('tridy/Galerie.php');

    $galerie = new Galerie('obrazky', 5);
    $galerie->nacti();
    $galerie->vypis();

    ?>
</body>
</html>

Máme hotovo.

Když přidáme minimum CSS, může vaše aplikace vypadat třeba takto (zdrojový kód jako vždy níže ke stažení, k zobrazování originální obrázků jsem ještě přidal javascriptový plugin LightBox):

Objektová galerie obrázků v PHP - Objektově orientované programování (OOP) v PHP

Po kliknutí na obrázek se aktivuje lightbox:

Objektová galerie obrázků v PHP – LightBox - Objektově orientované programování (OOP) v PHP

Možná vylepšení

Metoda vypis() není úplně ideální, jelikož se HTML kód echuje a proto je práce s ním poněkud nepřehledná. Dalším, již zmíněným vylepšením, by mohl být nahrávač obrázků, který nám na FTP nahraje obrázky do galerie a sám vytvoří miniatury. Pro naše účely je však aplikace dostačující a myslím, že má i tak praktické využití.

Naprogramovali jsme objektovou komponentu, kterou můžeme používat na různých webech, pro různé složky a na různě široké tabulky.

V příští lekci, Referenční a primitivní datové typy v PHP, si vysvětlíme referenční datové typy v PHP.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 3369x (5.78 MB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
Kvíz - Úvod, třídy a zapouzdření v PHP OOP
Všechny články v sekci
Objektově orientované programování (OOP) v PHP
Přeskočit článek
(nedoporučujeme)
Referenční a primitivní datové typy v PHP
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
184 hlasů
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 se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity