Poznajemy wzorzec projektowy singleton. Uczymy się zamieniać istniejącą już klasę na ten wzorzec. Do dzieła.

Oto nasza klasa:

<?php 

class App {
public function run(){
    $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
    $method = $_SERVER['REQUEST_METHOD'];

   echo "Path: $path, Method: $method";
  }
}

$app = new App();
$app->run();

Singleton oznacza, że może być tylko jedna instancja (obiekt) danej klasy. To piszemy:

<?php 

class App {

    private static $instance = null;

    private function __construct(public $app_name)
    {}

    public static function getInstance(){
        if (self::$instance == null){
                self::$instance = new App("MY_APP");
            }
        return self::$instance;
    }

    public function run(){
    $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
    $method = $_SERVER['REQUEST_METHOD'];

   echo "Path: $path, Method: $method";
  }
}

$app = App::getInstance();
$app->run();

Konstruktor prywatny, instancja jako pole statyczne. Zawsze będzie tylko jeden obiekt. Pytanie co z argumentami do konstruktora. Jeżeli są zaciągane np. z jakiegoś pliku konfiguracyjnego – nie ma problemu.

Jeżeli chcemy dać użytkownikowi możliwość ustawiania ich samemu należy olać konstruktor i napisać odpowiedni getter/setter:

class App {

    private static $instance = null;
    private $app_name;

    private function __construct()
    {}

    public static function getInstance(){
        if (self::$instance == null){
                self::$instance = new App();
            }
        return self::$instance;
    }

    public function getName(){
        return $this->app_name;
    }

    public function setName($name){
        $this->app_name = $name;
    }

    public function run(){
    $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
    $method = $_SERVER['REQUEST_METHOD'];

   echo "Path: $path, Method: $method";
  }
}

$app = App::getInstance();
$app->run();
$app->setName("my_app");
echo $app->getName();
//my_app

$app2 = App::getInstance();
echo $app2->getName();
//my_app

var_dump($app === $app2);
//true

Jak widać cały czas mamy do czynienia z jedną instancją, choć dwie zmienne mają referencję do niej.