Должен был спросить кого-то это давным-давно.
Каков наилучший способ использования других классов в другом классе?
Например, скажем, у меня есть класс приложения:
class Application { public function displayVar() { echo 'hello world'; } }
и класс базы данных
class Database { // connects to db on construct public function query() { // queries db } }
теперь я хочу добавить функцию в свой класс приложения, который использует функцию из класса db
class Application { public function displayVar() { echo 'hello world'; } public function getVar() { global $db; $sql = foo; $db->query($sql); } }
так что у меня есть
$db = new Database(); $app = new Application(); $app->getVar('var');
Есть ли лучший способ сделать это? Действительно, то, что я ищу, это стандартный способ сделать это, а не другой способ подделать его.
Есть несколько способов сделать это. Глобальные переменные, безусловно, являются одним из способов, и большинство из них тоже смотрели сверху вниз. Вы можете создать Singleton, и все остальные классы, которым нужен доступ к базе данных, будут ссылаться на этот синглтон.
final class Database { private static $connection; public static function getInstance() { if(self::$connection == NULL) { self::$connection = // init your database connection } return self::$connection; } }
И используйте этот объект подключения к базе данных в любом классе.
class Application { public function displayVar() { echo 'hello world'; } public function getVar() { $db = Database::getInstance(); $sql = foo; $db->query($sql); } }
Все это хорошо для начала и отличный шаг за пределами использования глобальных переменных, но вы можете сделать лучше с Injection Dependency . Dependency Injection – простая концепция: если класс имеет какие-либо внешние зависимости, например соединение с базой данных в вашем примере, вы явно передаете их нуждающемуся классу в его конструкторе или методе. Таким образом, новый код будет выглядеть как решение Джонатана. Основным преимуществом использования инъекции зависимостей является модульное тестирование, где вы можете легко заменить этот фактический объект базы данных макетным объектом и передать его тому, кто в нем нуждается.
class Application { private $db; public function __construct(Database $db) { $this->db = $db; } public function displayVar() { echo 'hello world'; } public function getVar() { $sql = foo; $this->db->query($sql); } }
Для небольших проектов вы можете легко сделать это сами. Для крупных проектов существуют различные рамки DI для PHP
$db
может быть свойством вашего класса Application
. Любая ссылка на него из экземпляра Application
будет выполнена через $this
– $this->db
class Application { private $db = null; public function setDB($name) { $this->db = new Database($name); } }
Включите файл класса (или настройте autoinclude) в каждый файл PHP, который нуждается в соответствующем классе. Затем создайте экземпляр при необходимости.
Если вам нужно иметь «общий» экземпляр объекта, вы можете посмотреть шаблоны Singleton и Factory:
Шаблон фабрики Pattern Singleton