Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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 3 - Atributy a magické metody v PHP

V minulé lekci, První objektová aplikace v PHP, jsme si vysvětlili, jak OOP funguje a vytvořili jsme si první jednoduchou objektovou aplikaci.

Dnes si vysvětlíme atributy a základní magické metody.

Atributy

Naše třída Clovek má zatím pouze metody (dokonce jen jednu). Přidejme jí nějaké atributy. Každý náš člověk bude mít jméno, příjmení a věk. Atributy třídě přidáme následovně:

<?php

class Clovek
{

    public string $jmeno;
    public string $prijmeni;
    public int $vek;

    . . .

Již víme, že atributy fungují jako proměnné, ale náleží objektu. Modifikátor přístupu public před názvem atributu označuje, že je atribut viditelný zvenčí (stejně jako tomu bylo u metody).

Abychom si atributy vyzkoušeli, upravíme si naši metodu pozdrav(). Budeme chtít, aby pozdravila "Ahoj, já jsem" a k tomu dodala hodnotu z atributu $jmeno. Budeme tedy chtít uvnitř metody použít atribut instance. Zajímavá otázka je, kde tu instanci vezmeme, jelikož třída je vzor společný pro všechny objekty daného typu (pro všechny lidi). Řešení je velmi jednoduché, ve třídě můžeme používat klíčové slovo $this. Pod touto proměnnou se skrývá instance, se kterou zrovna pracujeme a na které je tedy metoda volána. Metoda pozdrav bude nyní vypadat následovně:

public function pozdrav() : void
{
    echo('Ahoj, já jsem ' . $this->jmeno);
}

Přesuňme se nyní do index.php, kde tvoříme instanci. Nyní ji nastavíme atributy, které jsme třídě Clovek dodali:

<?php
require_once('tridy/Clovek.php');

$karel = new Clovek();
$karel->jmeno = 'Karel';
$karel->prijmeni = 'Novák';
$karel->vek = 30;
$karel->pozdrav();
<?php

class Clovek
{

    public string $jmeno;
    public string $prijmeni;
    public int $vek;

    public function pozdrav() : void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

}

Do index.php si dodejme ještě HTML hlavičku, aby nám aplikace uměla česky. Když ji nyní spustíme, vidíme, že metoda opravdu přistoupila k atributu a vypsala jeho hodnotu:

Tvoje stránka
localhost

Abychom si vyzkoušeli, že je třída univerzální, vytvořme si ještě Jana. Celý kód indexu včetně HTML bude vypadat takto:

<!DOCTYPE html>

<html lang="cs-cz">
    <head>
            <meta charset="utf-8" />
            <title>OOP na ITnetwork</title>
    </head>

    <body>
        <?php
        require_once('tridy/Clovek.php');

        $karel = new Clovek();
        $karel->jmeno = 'Karel';
        $karel->prijmeni = 'Novák';
        $karel->vek = 30;

        $jan = new Clovek();
        $jan->jmeno = 'Jan';
        $jan->prijmeni = 'Nový';
        $jan->vek = 24;

        $karel->pozdrav();
        echo('<br />');
        $jan->pozdrav();

        ?>
    </body>
</html>
<?php

class Clovek
{

    public string $jmeno;
    public string $prijmeni;
    public int $vek;

    public function pozdrav() : void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

}

Výstup aplikace vypadá takto:

Tvoje stránka
localhost

Objekty jsou vysoce univerzální komponenty, stačí vytvořit společnou třídu a poté můžeme pracovat s různě nastavenými instancemi různým způsobem. A tím to zdaleka nekončí, uvidíte, že toho umí ještě spoustu.

Magické metody

PHP nám ve třídě umožňuje definovat několik tzv. magických metod. Magických proto, že si je nevoláme my sami (i když samozřejmě také můžeme), ale spouští se v určitých chvílích automaticky. Reagují tedy na určité události. Všechny magické metody začínají na dvě podtržítka. Je jich několik, ale my si zatím zmíníme první 3.

Konstruktor

V našem programu si nejprve vytváříme prázdnou (nenastavenou) instanci člověka a až poté mu nastavujeme jméno, příjmení a věk. To má hned několik nevýhod, zejména:

  1. Lze vytvořit nenastavený objekt a pracovat s ním, což jistě vyvolá chyby, např. při vypsání jména, které není zadané.
  2. Nastavení všech hodnot objektu zabírá zbytečně místo ve zdrojovém kódu.

Tento problém za nás řeší konstruktor. Konstruktor je metoda, která se automaticky spustí při vytvoření instance. Slouží k nastavení vnitřního stavu objektu tak, aby byl připraven k použití. Pokud má naše třída konstruktor, nelze její instanci vytvořit jinak, než právě použitím konstruktoru.

Konstruktor je metoda se jménem __construct() a s libovolným počtem parametrů. Přidejme si ho do naší třídy a jako parametry mu dejme $jmeno, $prijmeni a $vek. Hodnoty z parametrů nastavíme atributům instance:

public function __construct(string $jmeno, string $prijmeni, int $vek)
{
    $this->jmeno = $jmeno;
    $this->prijmeni = $prijmeni;
    $this->vek = $vek;
}

Konstruktor nemá návratový datový typ, to samé platí i pro destruktor.

Konstruktor do třídy vložíme za atributy a před ostatní metody. Když nyní naši aplikaci spustíme, tak nebude fungovat. Je to z toho důvodu, že třída má nyní konstruktor a ten vyžaduje určité parametry, které jsme při vytváření instancí nezadali. Vidíme, že nás PHP nenechá vytvořit objekt jinak, než předepisuje konstruktor.

Přejděme do index.php a modifikujme PHP kód do následující podoby:

<?php

require_once('tridy/Clovek.php');

$karel = new Clovek('Karel', 'Novák', 30);
$jan = new Clovek('Jan', 'Nový', 24);

$karel->pozdrav();
echo('<br />');
$jan->pozdrav();
echo('<br />');
<?php

class Clovek
{
    public string $jmeno;
    public string $prijmeni;
    public int $vek;

    public function __construct(string $jmeno, string $prijmeni, int $vek)
    {
        $this->jmeno = $jmeno;
        $this->prijmeni = $prijmeni;
        $this->vek = $vek;
    }

    public function pozdrav() : void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

}

První dojem je zvýšení přehlednosti kódu. Vidíme, že ona záhadná závorka za třídou při vytváření její instance slouží k předání parametrů konstruktoru. Konstruktor následně tyto parametry uloží do objektu a tím ho připraví k použití. Využití konstruktoru samozřejmě není omezeno jen na nastavování atributů, můžeme v něm udělat cokoli jako v běžné metodě. Konstruktor můžeme definovat i bez parametrů, např. si v něm někam uložíme čas kdy byla instance vytvořena a podobně.

Definice vlastností

V PHP 8 lze konstruktor využít i k přímé deklaraci a definici vlastností objektu. Asi jste si všimli, že v kódu výše jsme napsali jména všech vlastností třikrát:

  1. Při deklaraci vlastností
  2. V parametrech konstruktoru
  3. V těle konstruktoru při definici vlastností

Nyní se můžeme prvního a třetího bodu zbavit, a využít ke všemu parametry konstruktoru:

<?php

require_once('tridy/Clovek.php');

$karel = new Clovek('Karel', 'Novák', 30);
$jan = new Clovek('Jan', 'Nový', 24);

$karel->pozdrav();
echo('<br />');
$jan->pozdrav();
echo('<br />');
<?php

class Clovek
{

    public function __construct(public string $jmeno, public string $prijmeni, public int $vek) {}

    public function pozdrav() : void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

}

Destruktor

Pro úplnost si uveďme i destruktor. Jak vás asi napadlo, destruktor je metoda, která se zavolá ve chvíli, když se objekt odstraňuje z paměti. Můžeme zde provést nějaké úklidové práce, které jsou potřeba k uvolnění zdrojů, které objekt využíval. Jelikož skripty v PHP běží jen chvíli a poté se veškerá paměť, kterou skript využíval, uvolní, nemají destruktory příliš velký význam. Přesto je můžeme využít např. k uložení dat do databáze před zrušením nějakého objektu nebo databáze může před zrušením ukončit databázové spojení a podobně. Vy v současné době destruktor asi nevyužijete, ale patří ke konstruktoru, tak proč si ho nevyzkoušet.

Metoda destruktoru se jmenuje __destruct(). Vypišme v ní hlášku o tom, že se objekt odstranil z paměti:

<?php
public function __destruct()
{
    echo('Byl jsem odstraněn z paměti.');
}
<?php

require_once('tridy/Clovek.php');

$karel = new Clovek('Karel', 'Novák', 30);
$jan = new Clovek('Jan', 'Nový', 24);

$karel->pozdrav();
echo('<br />');
$jan->pozdrav();
echo('<br />');

Když nyní aplikace spustíme, uvidíme, že úplně na konci se vypíše 2x hláška "Byl jsem odstraněn z paměti.":

Tvoje stránka
localhost

Hlášku vypíší před svým zničením $karel a $jan, k jejich odstranění z paměti dojde až při ukončení aplikace nebo přesněji ve chvíli, když je již nemá smysl uchovávat. Předčasně můžeme destruktor spustit zničením objektu pomocí metody unset().

Destruktor můžeme z naší třídy zase odebrat.

ToString

Magická metoda __toString() se spouští ve chvíli, kdy chceme objekt převést na textový řetězec, nejčastěji tedy když ho chceme vypsat. Schválně si zkuste nyní vypsat objekt $karel:

echo($karel);

PHP vám vyhodí chybu, jelikož není definované jakým způsobem se mají lidé vypisovat. Lidé jsou objekty, které mají několik vlastností, PHP jednoduše neví které z nich vypsat. Doplňme tedy do naší třídy Clovek metodu __toString(), která bude vracet atribut jméno:

public function __toString() : string
{
    return $this->jmeno;
}

Pokud se nyní znovu pokusíme Karla nebo Jana vypsat, vypíše se jednoduše jejich jméno.

Konstruktory nám umožňují provádět tzv. zapouzdření - o tom ale jindy :). Dnešní projekt máte jako vždy v příloze spolu se zdrojovými kódy.

V následujícím cvičení, Řešené úlohy k 1.-3. lekci OOP v PHP, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

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 1482x (862 B)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
První objektová aplikace v PHP
Všechny články v sekci
Objektově orientované programování (OOP) v PHP
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 1.-3. lekci OOP v PHP
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
241 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