Že v PHP do jedné proměnné lze ukládat různé datové typy v průběhu programu ví každý PHP programátor. Je to výsada snad všech skriptovacích jazyků a určitě všech dynamicky typovaných. Proto bude lepší si ukázat trochu pokročilejší možnosti jazyka PHP.
Volání podle názvu uloženého jako string
Většina moderních programovacích jazyků nabízí možnosti reflexe. Pomocí reflexe lze zjistit vlastnosti tříd a metod za běhu programu a poté je vytvořit či zavolat, i když jméno je uloženo jako string. PHP to samozřejmě umí také, ale mnohem jednodušeji.
Volání funkce
PHP dokáže zjistit, jestli funkce existuje a poté ji i zavolat, pokud je její název uložen jako string. Zde je i první ukázka, jaké výhody má povinnost pojmenovávat proměnné dolarem. Poslední možnost volání by v jiném jazyce moc nešla.
$funcName = "printName";
if (function_exists($funcName)) {
// Všechny parametry se specifikují zvlášť
echo call_user_func($funcName, "Pavel", "Kutac");
// Všechny parametry se předávají jako 1 pole
echo call_user_func_array($funcName, ["Pavel", "Kutac"]);
// Zavolání funkce přímo pomocí
echo $funcName("Pavel", "Kutac");
}
Vytvoření instance a zavolání metody
Když se dá zavolat funkce pomocí jejího jména v proměnné, asi nikoho nepřekvapí, že to samé lze s třídami a metodami.
$className = "Database";
$methodName = "connect";
if (class_exists($className)){
$inst = new $className;
if (method_exists($inst, $methodName)) {
// Stejně jako výše je možné použít i call_user_func_array
call_user_func([$inst, $methodName], "localhost", "root", "root");
// Nebo opět využít přímo proměnné, { } se mohou vynechat
$inst->{$methodName}("localhost", "root", "root");
// Pokud je metoda statická, můžeme udělat toto:
// Lze až od PHP verze 5.2.3
call_user_func($className."::".$methodName, "localhost", "root", "root");
}
}
Využití
Obě metody jsou hojně využívány především v různých frameworcích. Volání funkce pomocí proměnné s názvem funkce je využíváno ve WordPressu. Vytváření instancí třídy a volání jejich metod asi v každém frameworku, kde se takto mapuje controller na "routy".
// Přidávání "háčků" ve WordPressu
add_action('init', 'register_my_menu');
function register_my_menu() {
...
}
// Definování controlleru na routy v Laravelu
Route::get('/', 'FrontendController@hello');
Zdvojený dolar, ztrojený dolar, ...
Nutnost proměnné pojmenovávat dolarem má i další výhody. Lze vytvořit proměnnou se jménem, který je uložený jako string. Takto to lze skládat i dále, přímo v dokumentaci k PHP je ale doporučeno používat maximálně zdvojený dolar.
$name = "firstLevel";
$$name = "secondLevel";
$$$name = "Hello...";
echo $name; // Vypíše "firstLevel"
echo $firstLevel; // Vypíše "secondLevel"
echo $secondLevel; // Vypíše "Hello..."
Využití
I tato technika má využití, a to nejčastěji v šablonovacích systémech... Pro ukázku může sloužit tato velmi jednoduchá třída Template a její použití.
// Soubor: Template.php
class Template{
private $vars;
public function addVar($name, $value)
{
$this->vars[$name] = $value;
}
public function render($file)
{
foreach ($this->vars as $key => $value) {
// { } jsou zde pro vyšší přehlednost, lze je vynechat
${$key} = $value;
}
include $file;
}
}
// Soubor: home.php
echo "Welcome to ".$siteName;
// Soubor: index.php
$tpl = new Template();
$tpl->addVar("siteName", "My Blog");
$tpl->render("home.php"); // Vypíše "Welcome to My Blog"
Magické metody v PHP
Magická metoda vždy začíná __. Nejznámější je __construct() a možná i __destruct(), případně z jiných jazyků __toString(). Je jich ale mnohem více. Nejlepší bude opět příklad
class MyMagicTest{
public $normalProperty = "Hello...";
public function normalMethod(){
echo "Normal method";
}
public function __set($name, $value){
echo "Trying to write {$value} to property {$name}";
}
public function __get($name){
echo "Trying to read property {$name}";
}
public function __isset($name){
echo "Checking if property {$name} is set";
}
public function __unset($name){
echo "Removing property {$name}";
}
public function __call($funcName, $params){
echo "Calling method {$funcName} with params: ".implode(", ", $params);
}
}
Pomocí magických metod se dá přistupovat k vlastnostem objektu které neexistují, stejně tak volat metody které nejsou definovány. Pokud se přistupuje k existujícím vlastnostem nebo metodám, magické metody se samozřejmě nevolají.
Reflexe
Pokud je to opravdu nutné, lze použít reflexi jaká je v jiných programovacích jazycích. Lze získat signatury metod, konstanty a vlastně zjistit cokoli o třídě. Reflexe samotná by byla na jeden článek, takže to teď vynechám a jen dám odkaz http://php.net/manual/en/book.reflection.php.
Znáte v PHP jiné možnosti, o kterých jsem se nezmínil? Podělte se v komentářích
K tomuto článku již není možné přidávat další komentáře