Какой-то глобальный тип (будь то глобальные переменные, синглтон или какой-то другой вариант) является улучшением по сравнению с вашим предыдущим подходом, и поэтому вы на правильном пути. Вообще говоря, вы должны попытаться минимизировать объем состояния программы (по ряду причин, которые я не буду здесь рассматривать). Наличие глобальной переменной противоречит этому принципу. Есть разные решения этой проблемы, но самый мощный и часто упускаемый из виду подход заключается в использовании инверсии управления; Вместо того, чтобы получить зависимость, ваш класс должен получить ее. Например, скажем, у вас есть этот
class EditUserController {
function saveUser() {
$db = Database::GetInstance();
$db->execute("update users set ...", ...);
}
}
Вы можете изменить это на:
class EditUserController {
function saveUser($db) {
$db->execute("update users set ...", ...);
}
}
Передача зависимостей на уровне функциональных параметров может быть немного громоздкой, поэтому можно пойти на компромисс, чтобы передать ее на уровне объекта:
class EditUserController {
protected $db;
function __construct($db) {
$this->db = $db;
}
function saveUser() {
$this->db->execute("update users set ...", ...);
}
}
Это довольно распространенный паттерн в ОО-программировании. В дополнение к тому, что он более практичен, чем передача параметров функции, он обладает дополнительным преимуществом разделения конструкции (где совместно используемые зависимости связаны друг с другом) и среды выполнения (где они используются). Это упрощает многие вещи.