Отделение кода от функциональности БД - PullRequest
8 голосов
/ 13 ноября 2008

Я сейчас разрабатываю объектно-ориентированный сайт PHP и пытаюсь определить лучший способ абстрагировать функциональность базы данных от остальной системы. Прямо сейчас у меня есть класс DB, который управляет всеми соединениями и запросами, которые использует система (это в значительной степени интерфейс к MDB2). Однако, используя эту систему, я осознал, что у меня в коде много строк SQL-запросов. Например, в моем классе User у меня есть что-то вроде этого:

function checkLogin($email,$password,$remember=false){
    $password = $this->__encrypt($password);
    $query = "SELECT uid FROM Users WHERE email=? AND pw=?";

    $result = $this->db->q($query,array($email,$password));

    if(sizeof($result) == 1){
       $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
       $uid = $row['uid'];
    }else{
       return false;
    }

    /* Rest of the login script */
}

Что я хотел бы сделать, так это найти лучший метод для сокращения количества встроенного SQL. Я понимаю, что одним из способов сделать это было бы написание функций внутри пользователя для каждого из запросов, которые использует пользователь (что-то вроде следующего), но это может привести к довольно большому количеству функций.

function checkLogin($email,$password,$remember=false){
    $password = $this->__encrypt($password);
    $uid = $this->do_verify_login_query($email,$password);

    /* Rest of the login script */
}

function do_verify_login_query($email,$encpw){
    $query = "SELECT uid FROM Users WHERE email=? AND pw=?";
    $result = $this->$db->q($query,array($email,$encpw));

    if(sizeof($result) == 1){
       $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
       return $row['uid'];
    }else{
       return false;
    }
}

Итак ... мой вопрос. Каков наилучший метод управления большим количеством запросов, который будет использоваться типичным приложением базы данных? Будет ли способ, который я описал, быть правильным способом справиться с этой ситуацией? Или как насчет регистрации списка запросов в классе DB и связывания с каждым уникальным идентификатором (таким как USER_CHECKLOGIN), который передается в функцию запроса DB? Этот метод также может помочь с безопасностью, так как он будет ограничивать запросы, которые могут быть выполнены, только теми, которые зарегистрированы в этом списке, но это еще одна вещь, которую следует помнить при написании всех функций класса. Мысли?

Ответы [ 5 ]

7 голосов
/ 13 ноября 2008

Вытаскивание SQL в отдельные функции - неплохое начало. Некоторые другие вещи, которые вы можете сделать:

  • Создание отдельных классов для кода доступа к базе данных. Это поможет убедиться, что у вас нет функций SQL, разбросанных по всем вашим файлам PHP.
  • Загрузить SQL из внешних файлов. Это полностью разделяет ваш код SQL и код PHP, делая их более удобными в обслуживании.
  • Используйте хранимые процедуры, когда можете. Это полностью удаляет SQL из вашего PHP-кода и помогает повысить безопасность вашей базы данных за счет снижения риска выполнения внешнего SQL.
4 голосов
/ 13 ноября 2008

Другим вариантом может быть использование ORM, для PHP наиболее мощными являются:

Оба позволяют вам получить доступ к вашей базе данных, используя набор объектов, предоставляя простой API для хранения и запроса данных, оба имеют свой собственный язык запросов, который внутренне конвертируется в целевой SQL СУБД, что облегчит миграцию одна СУБД к другой с простыми изменениями конфигурации. Мне также нравится тот факт, что вы можете инкапсулировать логику модели данных для добавления проверки, например, только путем расширения классов вашей модели.

4 голосов
/ 13 ноября 2008

Возможно, вы захотите изучить реализацию ActiveRecord Pattern . Использование такого шаблона проектирования обеспечивает некоторую согласованность в работе с данными из ваших таблиц. Такие подходы могут иметь некоторые недостатки, в основном производительность для определенных типов запросов, но это можно обойти.

3 голосов
/ 13 ноября 2008

Поскольку вы говорите, что делаете это как OO PHP, то почему у вас SQL разбросан по всем методам в первую очередь? Более распространенные модели будут:

  1. Используйте ORM и позвольте ему обрабатывать базу данных.
  2. Предоставьте вашим классам один или несколько методов «загрузки», которые используют один запрос для извлечения всех данных объекта в память, и метод «сохранения», который использует один запрос для обновления всего в базе данных. Все остальные методы должны выполнять только манипуляции в памяти, а взаимодействие с базой данных ограничивается методами загрузки / сохранения.

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

Для вашего примера входа в систему я мог бы просто загрузить пользователя по адресу электронной почты, вызвать $user->check_password($entered_password) и выдать исключение / вернуть false / что угодно, если check_password не удастся. Ни check_password, ни какой-либо из кода обработки входа в систему не нужно заниматься базой данных или даже знать, что база данных - это то место, откуда пользователь загружается.

0 голосов
/ 13 ноября 2008

Другой вариант - думать о запросах как о данных и сохранять их в базе данных. Например, вы можете создать одну таблицу, в которой хранится запрос с именем, и другую таблицу, в которой хранятся параметры этого запроса. Затем создайте в PHP функцию, которая принимает имя запроса и массив параметров и выполняет запрос, возвращая любые результаты. Вы также можете прикрепить другие метаданные к запросам, чтобы ограничить доступ для определенных пользователей, применить пост-функции к результатам и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...