У меня есть веб-приложение, написанное на PHP с использованием базы данных MySQL.Этот вопрос может быть так же легко применим к любому языку и приложению, которые пытаются использовать базу данных SQL и конструкцию ООП MVC.
Как ограничить использование кода SQL для Модели?
За этим вопросом стоит довольно длинная история, характерная для моего случая.Как упоминалось ранее, я работаю над сайтом PHP / MySQL / AJAX.Я разработал его, используя принципы проектирования ООП и MVC - с моделью, видом и контроллером.Мне удалось сохранить элементы представления - такие как разметка и стилизация - полностью ограниченными видом и сделать их многоразовое использование довольно легко.Я думал, что сделал то же самое с кодом SQL.Но по мере продвижения работы стало ясно, что Модель нуждается в серьезном рефакторинге.
Я нашел способ сохранить SQL в Модели - заключить в капсулу каждый отдельный запрос SQL в своем собственном объекте Query.И затем, когда мне нужно было вызвать какой-то SQL в View или Controller, я получал доступ к запросу через фабрику.В контроллере или представлении не существует кода SQL.
Но это стало чрезвычайно утомительным.Я не думаю, что на самом деле что-то получаю, делая это, и трачу слишком много времени на создание запросов с именами, такими как «SelectIdsFromTableWhereUser».Фабрика для запросов приближается к тысячам строк.Небольшой поиск в Eclipse показал, что подавляющее большинство этих запросов используется в одном или двух местах и никогда больше.Не хорошо.
Я знаю, что в хорошем MVC вы хотите полностью отделить SQL от контроллера или представления.Но на данный момент мне кажется, что было бы лучше просто разместить SQL, где это было необходимо, в коде, а не пытаться похоронить его и код базы данных вглубь модели.Эти запросы используются только один раз, зачем их инкапсулировать?
Так ли важно отделить SQL от Controller или View?Что получается, делая это?Что теряется, позволяя ему распространяться?Как вы решаете эту проблему?
Редактировать По запросу, здесь немного подробнее о моей модели.
Есть две части.Часть таблиц и часть запросов.Часть Таблицы содержит объекты домена - в основном разработанные как обертки вокруг объектов класса, которые являются точными аналогами таблиц в базе данных.Например, это может быть таблица базы данных Foo
с полями id
, name
и type
.Будет объект Table (class FooTable
), который имеет массив с полями 'id', 'name' и 'type'.Это будет выглядеть так:
class FooTable extends MySQLTable {
private $id;
private $data;
private $statements;
public function __construct($id, $data=NULL, $populate=false) {
// Initialize the table with prepared statements to populate, update and insert. Also,
// initialize it with any data passed in from the $data object.
}
public function get($field) {}
public function set($field, $value) {}
public function populate() {}
public function update() {}
public function insert() {}
}
Если есть таблица базы данных fooBar
, которая имеет отношение один ко многим (один Foo
много Bars
) с полями id
, fooID
,и bar
тогда будет объект FooBar
Table (class FooBarTable
), который будет выглядеть почти так же, как и выше FooTable
.
FooTable
и множество FooBarTable
объектовоба будут содержаться в объекте Foo
.Присвойте фабрике объектов Foo
идентификатор таблицы Foo
, и она заполнится данными Foo
и всеми ее Bar
и их данными.
Объекты Query используются для извлечения идентификаторов Foo
в том порядке, в котором они необходимы.Итак, если я хочу, чтобы объекты Foo
были упорядочены по дате, голосу или имени, мне нужен другой объект запроса, чтобы сделать это.Или если я хочу выбрать все Foo
объекты, которые имеют Bar
в определенном диапазоне.Мне нужен объект запроса.
Большую часть времени я использую объекты Table (обертки, а не базовые таблицы) для взаимодействия с базой данных.Но когда дело доходит до выбора объектов таблицы, вот куда приходят запросы.
Во время оригинального дизайна я не думал, что будет слишком много запросов, и я думал, что это будут вещи, которые увидят повторное использование.Так как может быть несколько мест, где я бы хотел Foo
в порядке дат.Но так не получилось.Их гораздо больше, чем предполагалось, и большинство из них одноразовые, используются один раз в каком-то View или Command, а затем никогда больше.Я также думал, что запросы могут инкапсулировать довольно сложный SQL, и было бы хорошо иметь их в качестве объектов, чтобы я всегда мог предоставить им необходимые данные, и это была бы относительно дезинфицированная среда для тестирования самого запроса SQL,Но опять же, это не сработало.Большинство из них содержат довольно простой SQL.