Kromě mechanismu tříd nabízí PHP ještě několik funkcí, které vám práci s objekty mohou zpříjemnit. Všechny jsou popsány v manuálu k PHP, proto zde jen v rychlosti:
Funkce Návratová hodnota Popis
get_class($objekt) řetězec Funkce vrací název třídy, jejíž instancí je objekt $objekt.
get_parent_class($objekt) řetězec Funkce vrací název předka (parent class) třídy, jejíž instancí je objekt $objekt.
get_class_methods($nazev_tridy) pole řetězců Funkce vrací pole názvů metod třídy, jejíž název je předán v řetězcovém argumentu $nazev_tridy. Pole obsahuje názvy všech dostupných metod, tedy i metod zděděných.
get_class_vars($nazev_tridy) pole řetězců Funkce vrací pole názvů deklarovaných atributů třídy, jejíž název je předán v řetězcovém argumentu $nazev_tridy. Pole obsahuje názvy všech atributů deklarovaných pomocí var (i zděděných).
get_object_vars($objekt) asociativní pole Funkce vrací asociativní pole atributů objektu $objekt. (Klíč = název atributu)
is_subclass_of($objekt, $rodicovska_trida) bool Funkce vrací true, jestliže objekt $objekt je instancí třídy, která je podtřídou třídy specifikované řetězcem $rodicovska_trida. Jinak vrátí false (i tehdy, je-li $objekt instancí třídy $rodicovska_trida!).
class_exists($nazev_tridy) bool Funkce vrátí true, jestliže třída daná řetězcem $nazev_tridy existuje. Jinak vrátí false.
method_exists($objekt, $nazev_metody) bool Funkce vrátí true, jestliže objekt $objekt disponuje metodou s názvem $nazev_metody. Jinak vrátí false.
get_declared_classes() pole řetězců Funkce vrátí pole názvů deklarovaných tříd. V některých verzích PHP může vracet i názvy některých speciálních tříd -- viz manuál k PHP.
call_user_method($nazev_metody, $objekt, $parametry...) různé Funkce zavolá na objekt $objekt metodu s názvem $nazev_metody a předá jí případné $parametry.... Vrací hodnotu získanou z výsledku volání dané metody.
Názvy tříd a metod vracené těmito funkcemi jsou vždy automaticky převedeny na malá písmena abecedy.
Dobré mravy
Chcete-li v PHP psát objektově, musíte více než kde jinde pamatovat na dobré mravy a nutit se psát čitelně. PHP, narozdíl od C++ či Javy, neprovádí žádné kontroly typů a chybu v syntaxi rozezná, až když na ni při zpracování narazí. To je zdrojem mnoha nepříjemných chyb, které se špatně hledají, a části z nich se vyvarujete, budete-li důsledně dodržovat jisté konvence a úmluvy.
Zcela byste se měli vyvarovat statických volání metod tříd uvnitř jiné třídy za jiným účelem, než je volání předefinované funkce – ve 4. části jste mohli vidět, jaké psí kusy to dělá s proměnnou $this
.
Všechny atributy, které chcete používat, byste měli důsledně deklarovat v sekci var
definice třídy a nespoléhat se na skutečnost, že v případě neexistence třídního atributu vytvoří PHP atribut objektu.
Také byste si měli vytvořit nějaké konvence pojmenovávání. Proč si neodskočit do Javy:
- názvy tříd – psát dohromady, každé slovo názvu začíná velkým písmenem (např.
MujUkazkovyNazevTridy
) - názvy metod – psát dohromady, první písmeno každého slova kromě prvního velké (např.
nejakaMetoda()
) - názvy atributů – psát malými písmeny, slova oddělovat podtržítkem (např.
$nejaky_atribut
)
Váš kód se tak stane čitelnějším a přehlednějším.
PHP neumožňuje skrývání (pomocí konstrukcí private
jako v C++ či Javě), a to přináší další nepříjemnosti. Dobrým zvykem proto může být předsazování podtržítka '_'
před atributy a metody, které nejsou určeny k použití z vnějšku. Lehce tak dáte uživateli vašich tříd (nebo sami sobě) najevo, které metody se mohou používat přímo a které ne.
Někteří programátoři si zvykli na pravidlo nepřistupovat z vnějšku k atributům objektů přímo, ale vytvářet speciální metody k tomu určené:
/*
implementace jednoducheho seznamu zbozi ve
virtualnim obchode
*/
class SeznamZbozi {
var $_nazev_seznamu; # nazev seznamu zboží
var $_pocet; # pocet položek, jen ke čtení!
var $_polozky; # pole položek
# metody pro práci s názvem seznamu
function vlozNazev($novy_nazev) {
$this->_nazev_seznamu = $novy_nazev;
}
function vratNazev() {
return $this->_nazev_seznamu;
}
# metoda pro práci s atributem $pocet
function vratPocet() {
return $this->_pocet;
}
# ...další metody
}
Ke každému atributu definujte dvojici metod vloz...
a vrat...
(nebo anglicky set...
a get...
) a k atribitu přistupujte vyhradně jejich prostřednictvím. Má to hned dvě výhody. Za prvé, položkám, které chcete mít z vnějšku nepřístupné nebo jen ke čtení, uvedené metody nenapíšete nebo napíšete jenom verzi vrat
– a tak ihned vidíte, co si ke kterému atributu můžete dovolit. Druhou výhodou je možnost přidat později k ukládání nebo čtení hodnoty atributu nejaké akce navíc.
Například chcete pro ladicí účely vědět o každém zápisu hodnoty do atributu $_nazev_seznamu
. Jednoduše upravíte metodu vlozNazev()
:
function vlozNazev($novy_nazev) {
print 'Pozor! Změna názvu seznamu!';
print ' Stará hodnota: ' . $this->_nazev_seznamu;
print ' Nová hodnota: ' . $novy_nazev;
$this->_nazev_seznamu = $novy_nazev;
}
Nebo po čase zjistíte, že atribut $pocet
naší třídy SeznamZbozi
je zbytečný, tak ho odstraníte a metodu vratPocet()
přepíšete:
function vratPocet() {
return count($this->_polozky);
}
Vše bez nebezpečí, že vám zbytek kódu, který třídu SeznamZbozi
používá, přestane fungovat.
Závěr
Jak sami vidíte, programovat objektově v PHP lze. Otázkou však zůstává, nakolik je to příjemné a výhodné. Dostanete do rukou silné nástroje jako dědičnost a polymorfizmus, ale na druhou stranu špatným stylem programování si zavlečete do kódu mnoho nepříjemných chyb. Absence jakýchkoliv kontrol typů je zde citelnou nevýhodou. Pro někoho nezvyklé vlastnosti operátoru přiřazení stejně jako nulová podpora pro abstraktní třídy a nezabezpečené volání předefinovaných metod, to všechno je matoucí a bývá zdrojem chyb. A tak odpověď na otázku, zda PHP s OOP ano, či ne, zůstává jako vždy jen a jen na vás.