Kontynuujemy zabawy z MVC i klasami abstrakcyjnymi oraz dziedziczeniem. Tym razem poznamy słówko kluczowe parent i wyjdziemy na wyższy poziom, jeżeli chodzi o obiektówkę. Do dzieła!

Nasz plik helloname.php:

<?php 
echo "<h1>Hello name page</h1>";
echo "<br>";
echo @"Hello $name";

Możemy już „zdjąć” error suppress operator – nie będzie nam potrzebny.

Klasa z poprzedniej lekcji:

<?php 

abstract class InvokableController {
    protected $path;

    public function __construct($path)
    {
        $this->path = $path;
    }
    
    abstract public function __invoke();
    
}

class HomeController extends InvokableController {

    public function __invoke(){
        require __DIR__ . "/$this->path.php";
    }
}

$invokable = new HomeController("helloname");
$invokable();

Tutaj jak widać pola klasy (path) oraz sam konstruktor znajdują się w abstrakcyjnej klasie bazowej, jedynie implementacja abstrakcyjnej metody invoke znajduje się w klasie pochodnej.

Tym razem nieco zamieszamy. Potrzebujemy dwóch dodatkowych pól w klasie pochodnej:

<?php 

abstract class InvokableController {
    protected $path;

    public function __construct($path)
    {
        $this->path = $path;
    }
    
    abstract public function __invoke();
    
}

class HomeController extends InvokableController {

    protected $code;
    protected $data;

    //(...)
}

$invokable = new HomeController("helloname", ['name' => 'John'], 200);
$invokable();

Chcemy, aby działało tak, jak to przedstawiłem w kodzie powyżej. Problem polega na tym, że konstruktor klasy głównej i abstrakcyjnej nie przewiduje takich pól.

Musimy zatem napisać własny, wywołać konstruktor bazowej za pomocą słówka kluczowego parent, następnie dodać nowe pola, których klasa bazowa nie przewiduje:

<?php 

abstract class InvokableController {
    protected $path;

    public function __construct($path)
    {
        $this->path = $path;
    }
    
    abstract public function __invoke();
    
}

class HomeController extends InvokableController {

    protected $code;
    protected $data;

    public function __construct($path, $data, $code=200)
    {
        parent::__construct($path);
        $this->data = $data;
        $this->code = $code;
    }

   //(...)
}

$invokable = new HomeController("helloname", ['name' => 'John'], 200);
$invokable();

Teraz możemy użyć naszego code i data w metodzie invoke:

<?php 

abstract class InvokableController {
    protected $path;

    public function __construct($path)
    {
        $this->path = $path;
    }
    
    abstract public function __invoke();
    
}

class HomeController extends InvokableController {

    protected $code;
    protected $data;

    public function __construct($path, $data, $code=200)
    {
        parent::__construct($path);
        $this->data = $data;
        $this->code = $code;
    }

    public function __invoke(){
        http_response_code($this->code);
        extract($this->data);
        require __DIR__ . "/$this->path.php";
    }
}

$invokable = new HomeController("helloname", ['name' => 'John'], 200);
$invokable();