ООП и подключение к БД из класса

vasya.grishin

Новичок
Приветствую!

Проконсультируйте новичка.

У меня есть разные классы, в них разные методы (обычные и статичные), мне во всех методах надо делать выборку из БД, как правильнее сделать подключение к бд, чтобы не дублировать и не делать глупо? Я думаю наследовать через extends это не лучший вариант?

Подключение к БД выполнено через собственный класс.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Код в студию, и в теории этому делать имхо нечего.
 

vasya.grishin

Новичок
Код в студию, и в теории этому делать имхо нечего.
Код тут все запутает. Потому как я пока проектирую приложение.
Ранее оно было на функциональном подходе, бардак надоел и было решено сделать все на ООП (без фреймворков).

Вот есть класс подключения к БД
Еще есть другой класс, где есть разные методы, как из метода обратится к БД чтобы не выполнять повторное подключение к БД, так как объект из другого класса (который подключается к БД) недоступен в этом классе
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Ну это дело вкуса, можешь экземпляр класса-обертки над базой передать через конструктор, внутрь класса, где ты его использовать собрался, или статически его вызвать (DB::instance('тут можно именованное соединение впилить')) или как угодно еще.
 

AnrDaemon

Продвинутый новичок
У тебя классы-сервисы или классы - ValueObject?
Если сервисы, то передавать в конструкторе или фабрике.
Если VO, то фабрикой.
IMHO.
 

FSA

Новичок
Я сделал класс DB по шаблону проектирования одиночка (singleton). Вроде это так называется. Получилось что-то вроде такого:
PHP:
class DB {
  private static $pdo = null ;

  private function __construct() {
  }

  private function __clone() {
  }

  public static function getLink() {
    if (self::$pdo) {
      return self::$pdo;
    }
    self::$pdo=new PDO(PDO_DSN,PDO_USERNAME,PDO_PASSWORD);
    self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    self::$pdo->query('SET TIME_ZONE="'.TIMEZONE.'"');
    return self::$pdo;
  }

# Для тех, кто понимает что делает, код может быть небезопасен, подробности в обсуждении ниже
#  public static function insertValues($params) {
#    return "(`".implode("`, `", array_keys($params))."`) VALUES :)".implode(", :", array_keys($params)).")";
#  }

  public static function __callStatic ($name,$args) {
    $callback=array(self::getPDO(),$name);
    return call_user_func_array($callback,$args);
  }
}
Чтобы обратиться к базе данных из любого места можно сделать примерно так
PHP:
$q=DB::getLink()->prepare('....');
$q->execute([...]);
DB::insertValues() - это просто для удобства чтобы не плодить кучу текста из плейсхолдеров для простой операции INSERT или UPDATE.
 
Последнее редактирование:

AmdY

Пью пиво
Команда форума
DB::insertValues() - это просто для удобства чтобы не плодить кучу текста из плейсхолдеров для простой операции INSERT или UPDATE.
Ты так и скажи клиенту, когда он потеряет кучу денег благодаря взлому. Зато тебе удобно было, в топку плейсхолдеры.
 

FSA

Новичок
Ты так и скажи клиенту, когда он потеряет кучу денег благодаря взлому. Зато тебе удобно было, в топку плейсхолдеры.
В чём ошибка? Там данные не подставляются. Там на основе ключей формируется строка типа:
PHP:
(name,phone,email) VALUES (:name, :phone,:email)
Данные скармливаются execute(). Смысл руками городить весь этот огород если уже всё в объекте прописано?
 
Последнее редактирование:

FSA

Новичок
Как минимум, не экранируются сами названия полей.
Поясните? Названия полей жёстко фиксированы в классе. Что нужно экранировать? Поля типа order и др. которые пересекаются с SQL? Стараюсь их не использовать, а если и будут такие, но на этапе написания программы выловятся сами собой.
Кстати, этот метод можно выкинуть. Но интересно, вдруг в чём-то ошибаюсь.
 

Вурдалак

Продвинутый новичок
Ты спрашиваешь в чём ошибка. Ты передаёшь имя поля в переменной, ты держишь в уме источник этой переменной, ты вставляешь значение переменной сразу в строку запроса, что делает значение этой переменной кодом, а не данными. Я называю это ошибкой.

Другое дело, что тот же PDO не предусматривает экранирование идентификаторов (имена полей/таблиц/БД).

Если интересно, экранируются идентификаторы с помощью удваивания backtick'а: http://dev.mysql.com/doc/refman/5.7/en/identifiers.html (Cmd + F «quote the identifier»).

Но в целом — забей. Считай, что я придираюсь. Мне не хочется всерьёз рассуждать об этом коде.
 

FSA

Новичок
Ну я туда вставляю не то, чтобы переменную, это обычно свойства объекта, которые жёстко описаны в соответствующем классе специально для этой конкретной таблицы в БД. Изменить array_keys данные пользователя не в состоянии.
Придираешься или не придираешься, это не важно. Я не очень опытный разработчик, я сюда и пришёл чтобы хоть с кем-то общаться, а не в собственном соку вариться. Если я в чём, то ошибаюсь, то хотелось бы разобраться в чём.
 

Фанат

oncle terrible
Команда форума
В общем, Вурдалак уже все сказал.
Ты должен понимать разницу между тем, что ты делаешь, и тем что там себе воображаешь.

Ты выложил код. Тебе говорят, что код небезопасен. Вместо того, чтобы согласиться, ты начинаешь рассказывать, что "вот у меня там".

Пойми, никто не знает, что "у тебя там". И, по большому счету, никого это не интересует. потому что код - это код. Его можно взять и использовать. А твои соображения к делу не подошьешь. Любой, кто будет использовать этот код, подвергает себя очевидной опасности. Будешь спорить?

Хуже того - ты же и сам себя подвергаешь. Код, который рассчитывает на то, чо программист что-то там держит в уме, заведомо уязвим. Сто раз ты напишешь этот код для прописанных в классе переменных, а на сто-первый засунешь напрямую. Или не ты, а человек, который будет поддерживать написанный тобой проект, но не будет знать ни единого слова из того, что ты там "подразумевал".
 
Последнее редактирование:

FSA

Новичок
Закомментировал, дабы не искушать людей и чтобы было понятно о чём мы там говорили в обсуждении.
 

HORO

Новичок
напиши ещё в комментах чтоб в prepare() напрямую переменные не вставляли, а то вдруг кто-то вот так будет делать
PHP:
$pdo->prepare("INSERT INTO t VALUES ($var)")->execute();
:)
 
Сверху