Как реализовать подключение к БД через синглтон

367
13 ноября 2017, 22:19

Всем привет. Есть модель (если можно так назвать), состоящая из статичных методов. В каждом методе есть подключение к БД. Как это можно преобразовать, поскольку делать запрос каждый раз - не есть хорошо?

/**
 * Класс Category - модель для работы с категориями товаров
 */
class Category
{   

public static function getCategoriesByName($names)
{
    // Соединение с БД
    $db = Db::getConnection();
    // Текст запроса к БД
    $sql = 'SELECT * FROM categories WHERE link IN (?,?)';
    // Используется подготовленный запрос
    $result = $db->prepare($sql);
    $result->bindParam(':link', $link, PDO::PARAM_INT);
    // Указываем, что хотим получить данные в виде массива
    $result->setFetchMode(PDO::FETCH_ASSOC);
    // Выполняем запрос
    $result->execute($names);
    // Возвращаем данные
    return $result->fetchAll();
}
public static function getChildrenCategoriesByParent($id)
{
    // Соединение с БД
    $db = Db::getConnection();
    // Текст запроса к БД
    $sql = 'SELECT cat.id, cat.title, cat.link FROM categories AS cat                
            WHERE cat.parent_id = :id';

    // Используется подготовленный запрос
    $result = $db->prepare($sql);
    $result->bindParam(':id', $id, PDO::PARAM_INT);
    // Указываем, что хотим получить данные в виде массива
    $result->setFetchMode(PDO::FETCH_ASSOC);
    // Выполняем запрос
    $result->execute();
    // Возвращаем данные
    return $result->fetchAll();
}
/**
 * Возвращает текстое пояснение статуса для категории :<br/>
 * <i>0 - Скрыта, 1 - Отображается</i>
 * @param integer $status <p>Статус</p>
 * @return string <p>Текстовое пояснение</p>
 */
public static function getStatusText($status)
{
    switch ($status) {
        case '1':
            return 'Отображается';
            break;
        case '0':
            return 'Скрыта';
            break;
    }
}
/**
 * Добавляет новую категорию
 * @param string $name <p>Название</p>
 * @param integer $sortOrder <p>Порядковый номер</p>
 * @param integer $status <p>Статус <i>(включено "1", выключено "0")</i></p>
 * @return boolean <p>Результат добавления записи в таблицу</p>
 */
public static function createCategory($name, $sortOrder, $status)
{
    // Соединение с БД
    $db = Db::getConnection();
    // Текст запроса к БД
    $sql = 'INSERT INTO category (name, sort_order, status) '
            . 'VALUES (:name, :sort_order, :status)';
    // Получение и возврат результатов. Используется подготовленный запрос
    $result = $db->prepare($sql);
    $result->bindParam(':name', $name, PDO::PARAM_STR);
    $result->bindParam(':sort_order', $sortOrder, PDO::PARAM_INT);
    $result->bindParam(':status', $status, PDO::PARAM_INT);
    return $result->execute();
}
}

Как правильно тут это реализовать?

UPD код Db::getConnection():

{
        $paramsPath = ROOT . '/config/db_params.php';
        $params = include($paramsPath);
        $dsn = "mysql:host={$params['host']};dbname={$params['dbname']}";
        $db = new PDO($dsn, $params['user'], $params['password']);
        $db->exec("set names utf8");
        return $db;
    }
Answer 1

Всё, что Вам нужно - сохранить соединение для дальнейшего переиспользования.

Что-то вроде этого:

class Db {
   private static $connections = [];
   public static function getConnection($id = 'default') {
     if (!empty(self::$connections[$id])) return self::$connections[$id];
     return self::$connections[$id] = get_connection_old_way();
   }
   // Возможно стоит также озаботиться дерегистрацией закрываемых соединений
   public static closeConnection($id = 'default') {
     if (!empty(self::$connections[$id])) {
       // self::$connections[$id]->close();
       unset(self::$connections[$id]);
     }
   }
}
Answer 2

Вот как то так. getInstance() это и есть синглтон. тут можешь хоть PDO хоть mysqli юзать.

Использовать так. Берешь и создаешь ккласс в котором делаешь use DB. И этим классом расширяешь свой класс где будешь делать что то с базой.

trait DB
{
    private static $instance;
    /**
     * @var null|mysqli
     */
    private static $link = null;
    /**
     * Return an object of mysql class to work with database.
     *
     * @return \mysqli|null
     */
    public static function getInstance()
    {
        if (self::$link === null) {
            self::$link = new mysqli(DB_HOST, DB_USER, DB_PASSWORD);
            if (!empty(self::$link->connect_error)) {
                die(self::$link->connect_error);
            }
            if (!self::$link->select_db(DB_NAME)) {
                die(self::$link->error);
            }
            self::$link->query('SET NAMES utf8');
        }
        return self::$link;
    }
    /**
     * Clean a value from space and html tags.
     *
     * @param string $value String value
     *
     * @return string
     */
    public function clean($value)
    {
        return strip_tags(trim($value));
    }
    /**
     * Escape a value.
     *
     * @param string $value String value.
     *
     * @return string
     */
    public function escape($value)
    {
        return self::getInstance()->real_escape_string($value);
    }
    private function __clone()
    {
    }
    private function __wakeup()
    {
    }
}
READ ALSO
Редактирование записей в бд

Редактирование записей в бд

Добрый деньНеобходимо производить редактирование данных в базе данных

172
Laravel api не работает

Laravel api не работает

Добрый день! Подскажите, пожалуйста, не могу разобраться

292
обработка html страницы

обработка html страницы

помогите как из этого:

302