Konštruktor triedy
Predtým, než si vysvetlíme, čo je konštruktor triedy a aký má význam, poďme sa ešte raz pozrieť na kód, ktorý sme vytvorili na poslednej prednáške. Ako sme si povedali, properties sú premenné (atribúty), ktoré popisujú danú triedu a metódy sú funkcie, ktoré s nimi niečo vykonávajú. Obe veci s danou triedou, resp. s jej objektami súvisia. Povedali sme si tiež, že kód napísaný v štýle OOP by mal v podstate obsahovať iba deklarácie triedy a v kóde funkcionality vo väčšine prácu s objektami (s ich properties a metódami).
Keď sa ale pozrieme na kód za vytvorením objektu ($db = new Database();), hneď za ním si vytvárame premennú, ktorá nepatrí k žiadnej triede a do nej si vkladáme výsledok pripojenia. Keď sa nad tým zamyslíme, na čo nám je táto premenná, ktorá nie je priradená k žiadnej triede? Nesúvisí náhodou pripojenie do databázy so samotnou databázou? Odpoveď je áno, súvisí a áno, taká premenná by tam nemala byť len tak pohodená (podľa OOP), mala by sa nachádzať v našej triede. Poďme to teda napraviť, nech náš ukážkový kód vyzerá naozaj ako OOP kód. Skúste sami, či by ste to vedeli napraviť, ak nie, tak by to mohlo vyzerať takto:
index.php (pripojenie do db):
//TRIEDA DATABAZA (pripojenie)
class Database{
public $server_name = 'localhost';
public $login_name = 'root';
public $login_password = 'root';
public $db_name = 'zapr_db_1';
public $connection = null;
function connectToDb(){
$this->connection = mysqli_connect($this->server_name, $this->login_name, $this->login_password, $this->db_name);
if (!$this->connection) {
echo 'Spojenie s databázou sa nepodarilo nadviazať.';
}else{
// echo 'Spojenie s databázou sa podarilo úspešne nadviazať.';
}
}
}
$db = new Database();
$db->connectToDb();
Ako vidíte, do našej triedy sme si pridali novú property s názvom connection, do ktorej vkladáme v metóde pre pripojenie výsledok pripojenia (príkazu mysqli_connect). Priamo v tej istej metóde aj vypisujeme v prípade nepripojenia chybovú hlášku. Tým sme kód funkcionality (mimo deklarácii tried) zredukovali na dva riadky, kde obidva súvisia s triedami, jeden objekt vytvára a druhý volá jeho metódu (čiže tiež pracuje s nejakým objektom). Takto to už vyzerý oveľa lepšie.
Musíme dať ale pozor. Tým, že sme zrušili premennú connection, ktorá sa ako vieme používa v príkazoch na vykonanie query, sme znefunkčnili všetky príkazy na databázu. Aby to bolo ako má, nahradíme všetky výskyty premennej connection za property našej triedy, teda $db->connection, riadky s týmto príkazom by mali vyzerať takto:
$result = mysqli_query($db->connection, $sql_query);
Zamyslime sa nad našou triedou. Ako sme si povedali, mala by nám reprezentovať objekt, ktorý bude slúžiť, resp. bude reprezentovať databázu, s ktorou pracujeme. Kľúčové info pre databázu sú 4 properties, ktoré sme si vytvorili na začiatku. Týmto properties sme natvrdo nadefinovali (rovno priradili) hodnoty hneď na začiatku deklarácie triedy.
Ako sme sa už viackrát naučili, vždy treba byť opatrný, keď niečo definujeme natvrdo, čiže keď priraďujeme rovno niekde konkrétne hodnoty. Treba sa vždy zamyslieť, či tieto hodnoty budú vždy rovnaké. Ako vieme, tieto dáta – hodnoty (napríklad heslo do databázy) sa môžu kedykoľvek zmeniť. Ak by sa tak stalo, museli by sme v kóde priamo v deklarácii triedy tieto hodnoty zmeniť. To by ešte nebol taký problém.
Predstavte si ale, že by sme v našom programe potrebovali pracovať s dvomi rôznymi databázami. V prvej časti programu by sme napríklad pracovali s touto databázou a v druhe by sme pracovali s inou, ktorá by pochopiteľne mala iné údaje, napríklad prihlasovacie meno a heslo. Čo by to pre nás znamenalo? No keby sme to chceli robiť hlava nehlava ako drevorubači, tak by sme skopírovali celú deklaráciu tejto triedy Database a nazvali ju napríklad Database2 a v deklarácii properties by sme iba zmenili rozdielne prihlasovacie údaje. Fungovalo by to, dokonca by to bolo všetko OOP, ale samozrejme, nie je to optimálne riešenie. My chceme predsa množstvo kódu redukovať.
Chcelo by to takú všeobecnú triedu pre databázu (jednu), ktorú by sme mohli použiť pri práci s jednou a aj pri práci s druhou databázou. Musíme teda spraviť to, aby sa hodnoty kľúčových štyroch properties nenastavili hneď pri vytvorení objektu alebo ešte lepšie, nech sa aj vytvoria, ale nie priamo v deklarácii. A presne na toto slúži špeciálna funkcia každej triedy, ktorá má názov konštruktor (constructor). Je to metóda, ktorá sa spúšťa automaticky pri príkaze new. Ak nie je definovaná, tak sa nespustí nič, ak je definovaná, tak sa spúšťa práve v tomto momente.
A presne preto sa nachádzajú za slovom new a názvom triedy, ktorej objekt chceme vytvoriť, okrúhle zátvorky, pretože je to v podstate miesto, do ktorého vkladáme hodnoty parametrov, ktoré chceme preposlať metóde konštruktor. Ako to využijeme na vyriešenie nášho problému? Využijeme to tak, že v deklarácii triedy si vytvoríme properties s prázdnymi hodnotami (tak sa to zvykne robiť) a pomocou konštruktora nastavíme konkrétnemu objektu hodnoty, ktoré chceme do nich nastaviť.
Metóda konštruktor sa definuje väčšinou ako prvá v zozname metód danej triedy. Zadáva sa slovom function, za ktorým nasledujú dva podtržníky (underscore __), za ktorými nasleduje názov metódy – contruct. Tak ako to už vieme, zachytí štyri parametre a v tele konštruktora iba napíšeme priradenie parametrov do našich properties (stále cez this, lebo sme v deklarácii triedy). Malo by to vyzerať teda takto:
index.php:
//TRIEDA DATABAZA (pripojenie)
class Database{
public $server_name = '';
public $login_name = '';
public $login_password = '';
public $db_name = '';
public $connection = null;
function __construct($server_name, $login_name, $login_password, $db_name){
$this->server_name = $server_name;
$this->login_name = $login_name;
$this->login_password = $login_password;
$this->db_name = $db_name;
}
function connectToDb(){
$this->connection = mysqli_connect($this->server_name, $this->login_name, $this->login_password, $this->db_name);
if (!$this->connection) {
echo 'Spojenie s databázou sa nepodarilo nadviazať.';
}else{
// echo 'Spojenie s databázou sa podarilo úspešne nadviazať.';
}
}
}
$db = new Database('localhost', 'root', 'root', 'zapr_db_1');
$db->connectToDb();
Ako vidíte, skutočne to funguje. Síce sa nám zvýšil počet riadkov kódu, ale ak by sme teraz chceli použiť našu triedu pre pripojenie do inej databázy, iba by sme si vytvorili inštanciu s inými hodnotami konštruktora. Šikovné nie? Na záver by som ešte podotkol, aby ste si všimli, ako sme vytvorili prázdne hodnoty. Pre prvé štyri, ktoré očakávame, že budú string, sme priradili prázdny string ('') a v poslednej pre pripojenie, ktoré je objektom, sme nastavili null (prázdny objekt – nič – podobne ako v databázach). Je to v podstate jedno, len aby ste chápali, prečo sme to tak dali.