Задать вопрос
@Anywake
сисадмин

Подключние к базе данных из класса — насколько правильно?

Добрый день!
у меня есть подключение к базе данных

try{ 
	$sql_connect = new PDO("mysql:host=". DB_HOST .";dbname=". DB_NAME. ";charset=utf8mb4", "". DB_USER ."", "". DB_PASS ."", $pdo_options);
}  
catch(PDOException $sql_connect_e)
{  
    echo ("Ошибка подключения к базе данных. SQL erorr: ". $sql_connect_e->getMessage() ."");
    die();
};


Данное подключение ($sql_connect ) я вызываю в классах через конструктор:

$Data = new Data($sql_connect);

В классе выглядит так:
class Data
{
	//получаем данные для подключения
	public function __construct($sql_connect)
	{ 
		$this->connection_db = $sql_connect;
	}
	...

}


насколько правильный такой подход или не правильный и почему?

Можно изменить подход так, что бы не использовать конструктор или наследование от класса работы с базой данных (через создание отдельно класса подключение к базе данных)?

Если использоваться отдельный класс работы с базой данных, как его вызывать внутри других классов для работы с бд:

$query = $this->connection_db->query("SELECT * FROM table");
$query->execute();
  • Вопрос задан
  • 391 просмотр
Подписаться 2 Средний 1 комментарий
Решения вопроса 1
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
С ответами выше полностью согласен, DI через конструктор, авто-резолв зависимостей, возможно даже сервис контейнер с биндингами - это правильно, явное лучше не явного и тд.

Но я предлагаю не мучаться, а просто сделать singleton-обертку над PDO
И вызывать её там где нужно нафигачить запросы к БД

class DB
<?php
class DB
{
    private static $instance = null;
    private $pdo;

    private function __construct()
    {
        $host = 'localhost';
        $dbname = 'your_database';
        $username = 'your_username';
        $password = 'your_password';
        $charset = 'utf8mb4';

        $dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
        $options = [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ];

        $this->pdo = new PDO($dsn, $username, $password, $options);
    }

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

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


class Data 
{
    public function __construct($param1, $param2)
    {
         // Получаем PDO напрямую
        $this->db = DB::getInstance();
    }

    public function example()
    {
        // $query = $this->db->query("SELECT * FROM table");
        // $query->execute();

        // $stmt = $this->db->prepare("...");
    }
}


Вариант пробросить PDO через конструктор всё ещё останется, если поймете что оно вам нужно
А так просто получаем глобальный доступ к инстансу PDO из любого места в коде
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
меня есть подключение к базе данных

и уже неправильное

Учим основы:
- на локальном сервере это вот try catch echo является бессмысленным: если убрать всю эту нелепую копипасту, РНР и сам выведет то же самое.
- на боевом сервере этот код является вредным: внутренние ошибки РНР мы никогда не светим наружу. Пользователь их не поймёт, а для хакера они бесценны.
Поэтому убираем бессмысленное try catch и оставляем только соединение
$sql_connect = new PDO("mysql:host=". DB_HOST .";dbname=". DB_NAME. ";charset=utf8mb4", DB_USER, DB_PASS, $pdo_options);

Опять же убрав из него нелепые кавычечьки.

насколько правильный такой подход

Этот подход практически идеальный

Можно изменить подход так, что бы не использовать конструктор

Можно, но не нужно.
Сейчас всё чётко видно, откуда берётся соединение с БД, и где оно нужно. Одна переменная в конструкторе - это не то место, где надо лениться и изобретать способы её не писать. В будущем, когда освоите автоматический вызов классов - тогда оно будет подставляться само. Но всё равно через конструктор.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы