Rozbudowa kontrolera. Użyjemy sztuczki zwanej late static binding aby móc lepiej obsługiwać nieistniejące metody kontrolera. Do dzieła.
Ostatnim razem dodaliśmy sobie coś takiego:
//(...)
$router->add("/products", ["controller" => "product", "action" => "list123"]);
$router->add("/product/list", ["controller" => "product", "action" => "list"]);
//(...)
Oczywiście kontroler Product nie posiada metody list123. Ona była po to, aby pokazać, że metoda __call() działa:
<?php
abstract class Controller {
public function __call($name, $arguments)
{
die("404 NOT FOUND");
}
}
Co jednak, gdyby nie tworzyć takiej metody (list123), ale utworzyć plik product_list123.php?
<?php
echo "hello from product_list123.php!";
Można by taki plik dołączyć. Pytanie, jak to zrobić. Potrzebujemy nazwę klasy i nazwę metody:
<?php
abstract class Controller {
public function __call($name, $arguments)
{
echo __CLASS__ . " " . $name;
die("");
}
}
//Controller list123
Tu pojawia się problem – o ile nazwa metody wyświetla się dobrze, o tyle __CLASS__ daje nam „Controller” zamiast konkretną w danym przypadku klasę pochodną (Product).
Można to obejść poprzez tzw. late static binding:
<?php
abstract class Controller {
public function __call($name, $arguments)
{
echo get_class(new static) . " " . $name;
die("");
}
}
//Product list123
Teraz, skoro wyświetla się poprawnie, możemy sprawdzić, czy taki plik „product_list123.php” istnieje i go dołączyć. Jeżeli nie – błąd:
<?php
abstract class Controller {
public function __call($name, $arguments)
{
$cls = strtolower(get_class(new static));
$action = $name;
$path = __DIR__ . "/{$cls}_{$action}.php";
if(file_exists($path)){
require $path;
} else {
die("404 NOT FOUND");
}
}
}
//hello from product_list123.php!
Działa. Teraz możemy usunąć plik „product_list123.php” – wtedy dostaniemy błąd, czyli też działa, jak należy.