Singleton в PHP на примере подключения к MySQL

Singleton (синглтон) — один из простейших для понимания шаблонов проектирования в PHP. Это обычный класс в PHP, в логику которого добавлена проверка на единственность создания его экземпляра.

95% процентиль

Как создать синглтон:

  • хранить экземпляр класса в приватной статической переменной
  • инициализировать его через метод getInstance и сохранять в статической переменной, а если она была создана раньше, то вернуть ее
  • определить метод __construct в private и определить в нем логику создания instance
  • определить метод __clone (клонирование объекта) как private
  • определить метод __wakeup (вызывается перед unserialize) как private

Почему стоит использовать синглтон:

  • позволяет иметь общую точку доступа к внешнему ресурсу
  • упрощает инициализацию, проверку состояния, передачу контекста в приложении
  • при грамотном использовании (примеры ниже), упрощает управление приложением

Когда стоит использовать Singleton:

  • подключение к БД
  • класс, инициализирующий настройки приложения, состояние, контекст

Почему не стоит использовать синглтон

  • нарушает принцип единственной ответственности (проверяет на существование, создает экземпляр, отдает результат)
  • затрудняет тестирование, т.е. приносит в приложение глобальное состояние
  • скрытые зависимости

Пример

Рассмотрим использование Singleton на примере создания соединения к базе данных MySQL.

Создадим класс DB. Информацию о соединении будем хранить в статической приватной переменной $_instance. Чтобы получить ее значение будем использовать статический метод getInstance(), в котором будем делать проверку на null переменной $_instance, в случае истины создавать ее через new self, иначе — возвращать ее.

Пример реализации этого класса:

<?php

class DB
{
	private static $_instance = null;
	
	// для безопасности настройки лучше хранить в файле с конфигом
	private static DB_HOST = '';
	private static DB_NAME = '';
	private static DB_USER = '';
	private static DB_PASS = '';

	private function __construct () {
		
		$this->_instance = new PDO(
			'mysql:host=' . self::DB_HOST . ';dbname=' . self::DB_NAME,
	    	self::DB_USER,
	    	self::DB_PASS,
	    	[PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"]
	    );

	}

	private function __clone () {}
	private function __wakeup () {}

	public static function getInstance()
	{
		if (self::$_instance != null) {
			return self::$_instance;
		}

		return new self;
	}
}

Использование:

<?php

$db = DB::getInstance();
$db2 = DB::getInstance();

var_dump($db == $db2); // bool(true) 


Подпишитесь на Хайлоад с помощью Google аккаунта
или закройте эту хрень