5. díl - První objektová komponenta v PHP - Galerie obrázků

PHP Objektově orientované programování První objektová komponenta v PHP - Galerie obrázků American English version English version

V minulém dílu našeho seriálu tutoriálů o objektově orientovaném programování v PHP jsme si vysvětlili zapouzdření. Na dnešek jsem slíbil, že si vytvoříme něco reálně použitelného. Půjde o 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 GIMPu). 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

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
{

        private $slozka;
        private $sloupcu;

        public function __construct($slozka, $sloupcu)
        {
                $this->slozka = $slozka;
                $this->sloupcu = $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()
{
        $slozka = dir($this->slozka);

        while ($polozka = $slozka->read())
        {

        }
        $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í 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 2x (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 $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 řětě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í false.

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

*Funkce strpos() vrátí 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()
{
        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

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.

Příště budeme pokračovat s našimi lidmi, kterých se ještě jen tak nepustíme. Vysvětlíme si jak PHP pracuje s referenčními datovými typy.


 

Stáhnout

Staženo 1762x (6.54 MB)
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 (26 hlasů) :
55555


 



 

 

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

Avatar
Danny
Člen
Avatar
Danny:

Jj díky, přesně to jsem myslel :)

 
Odpovědět 17. ledna 23:19
Avatar
Crrack
Člen
Avatar
Crrack:

Ahoj nevíte jak udělat, aby se soubory řadily podle datumu uprav na souborech ?

 
Odpovědět 16. dubna 14:18
Avatar
Michal Vlasák:

Nevím, jestli to vysvětlím dobře, ale mate mě toto:

public function __construct($slozka, $sloupcu)
        {
                $this->slozka = $slozka;
                $this->sloupcu = $sloupcu;
        }

a toto,

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

protože, když vytvořím instanci $galerie, tak v konstruktoru předávám do $this->slozka hodnotu proměné $slozka a ta se rovná 'obrazky'. Takže ve zkratce řečeno $slozka má hodnotu 'obrazky' a tu jsme předali do $this->slozka.

V dalších krocích pak vidím $slozka = dir($this->slozka). To tím pádem tu původní proměnou složka nahrazuju a mohl bych tam mít i jinou proměnnou a nebo je důležité, aby tam bylo právě $slozka = ?

Děkuju

Odpovědět 10. května 11:09
"It doesn't work! I hate programming!" - One hour later: "It works! I love programming!"
Avatar
kivdul
Člen
Avatar
kivdul:

Ahoj lidi,

23.08.2013 v 1:28 vložil KIT svůj kod, ve kterém ke konci použil zkratku EOT, a nepodařilo se mi dohledat její význam :-(

Věděl by náhodou někdo z Vás, co znamená a napsal sem stručně její použití?

děkuji Ludvík

 
Odpovědět 21. června 14:44
Avatar
Adam Ježek
Tým ITnetwork
Avatar
Odpovědět 21. června 15:04
Programátor dělá co může. Počítač co chce. | Pokud mi dáš mínus, tak prosim, napiš proč!
Avatar
kivdul
Člen
Avatar
Avatar
Odpovídá na Michal Vlasák
Pavel Habžanský:

$this -> slozka je něco jiného než $slozka... $this-> promenna ti říká, že pracuješ přímo s atributem třídy, $slozka je pak už samostatná proměnná

Odpovědět 21. června 17:33
Čím větší výzva, tím větší zkušenost
Avatar
Andreas
Člen
Avatar
Andreas:

Viete niekdo ako spraviť aby keď na obrázok kliknem tak sa mi zobrazí a vistupi dopredu?

 
Odpovědět 9. září 7:46
Avatar
Martin Procházka:

Ahoj mě zajímá trafic a možná jsem už moc old, ale miniatura se tvoří automaticky to je v pohodě, jdem mi o abych člověka nenutil natahovat obrazky v plné velikosti, aby se to transformovalo na miniaturu. někde přece ten trafic být musí a moc se mi nezdá že by tuto hodnotu převzal hosting.

Odpovědět 27. listopadu 7:10
... učit se, učit se, učit se ...
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 62. Zobrazit vše