Данные в любом приложении являются ключевым фактором простоты их понимания. Со временем вырабатывается определенный подход к их выборке, обработке и обновлению. Если обрабатывая данные вы все еще задумываетесь над тем в какой форме хранить ваши данные, как из списка выбрать то что нужно — возможно данный подход упростит вашу жизнь. Основные требования к хранению данных могли бы звучать как то так:
Структура максимально близкая к реляционной. Подобная форма хранения данных завоевала популярность у разработчиков и мы не будем от нее отказываться.
Данные должны обеспечивать простоту доступа к основному элементу по идентификатору. Взаимосвязи со смежными элементами строятся на основе использования вторичного ключа в качестве указателя на основной элемент. Быстрый доступ будет плюсом.
Повторное использование списка данных. Единожды получив срез данных должна оставаться возможность, обращение к любому из элементов по его основному ключу или совпадению со значением одного или нескольких атрибутов а также построение списков из выборки.
Дополнительным бонусом будет использование «налету» что позволит обращаться к объектам через несколько уровней.
Однозначная поддержка перехода по любым из возможных связей: один ко многим, много к одному и много ко многим. Возможность быстрой модификации логики связей при дальнейших изменениях структуры данных.
После многочисленных проб и ошибок нашел форму, которая меня устроила чуть меньше чем полностью. Условно давайте назовем ее «Основной формой». Наглядно данные основной формы можно представить массивом ключи которого будут значения автоинкрементного поля таблицы, а значения — список полей записи выбранной таблицы. Для выборки подобной структуры из базы данных будем использовать функцию условно названную rebuild (пересборка) rb():
pre(rb(«marks»));
Array(
[1] => Array([id] => 1, [name] => Вольво)
[2] => Array([id] => 2, [name] => Мерседес)
[4] => Array([id] => 4, [name] => Ситроен)
)
Уникальные автоинкрементные поля гарантируют нам конфликты имен записей данных. Они же в дальнейшем помогут в формировании динамических фильтров, поэтому их использование в дальнейшем также обосновано.
Связанная таблица моделей могла бы выглядеть следующим образом:
pre(rb(«models»));
Array(
[1] => Array([id] => 1, [marks_id] => 1, [name] => Volvo S60, [price] => 1644000)
[2] => Array([id] => 2, [marks_id] => 1, [name] => Volvo V40, [price] => 1309000)
[3] => Array([id] => 3, [marks_id] => 2, [name] => CLS Shooting Brake, [price] => 3520000)
)
Дальнейшая идея использования подобных конструкций сводится к последовательному казанию полей по которым мы выбираем и значений для выборки. Полем считается текстовое поле, ключи массива или числово считются значением для выборки. При этом выборка всех нужных нам значений может происходит без вынесения кода в контролер а может быть сделана прямо в шаблоне.
Отобразить список моделей в которых есть хотя бы одна марка и список этих марок.
<? foreach(rb("marks", "id", "id", rb("models", "marks_id")) as $marks): ?>
<h1><?=$marks['name']?></h1>
<? foreach(rb("models", "marks_id", "id", $marks['id']) as $models): ?>
<div><?=$models['name']?></div>
<? endforeach; ?>
<? endforeach; ?>
Подобный подход позволяет реализовать простую линейную логику практически без зависимостей и быстро модифицируемый. Набор ключей в параметрах функции пересборки легкость восприятия фукнционала и его модификации.
При этом все модели Вольво выбираются следующим образом, где идентификатор марки получаем из ГЕТ запроса страницы:
<? pre(rb(«models», «marks_id», «id», $_GET['marks_id'])) ?>
Array
(
[1] => Array([id] => 1, [marks_id] => 1, [name] => Volvo S60, [price] => 1644000)
[2] => Array([id] => 2, [marks_id] => 1, [name] => Volvo V40, [price] => 1309000)
)
Подобным образом можно выбирать и под другим полям. Выборка модели по ее id выглядит следующим образом:
<? pre(rb(«models», «id», $_GET['id'])) ?> где $_GET['id'] = 2;
Array
(
[2] => Array([id] => 2, [marks_id] => 1, [name] => Volvo V40, [price] => 1309000)
)
Выбрать по одной подели каждой марки:
<? pre(rb(«models», «marks_id»)) ?>
Array
(
[1] => Array([id] => 2, [marks_id] => 1, [name] => Volvo V40, [price] => 1309000)
[2] => Array([id] => 3, [marks_id] => 2, [name] => CLS Shooting Brake, [price] => 3520000)
)
Подобным образом происходит обращение от модели к марке машины.
<? if($models = rb("models", "id", $_GET['id'])): ?>
<? pre(rb("marks", "id", $models['marks_id'])); ?>
<? else: pre("Модель не найдена"); endif; ?>
Array(
[1] => Array([id] => 1, [name] => Вольво)
)
Несмотря на некоторые недостатки, подобный подход позволяет на 90% закрыть запросы к данным используя стандартную первую форму.
Надеюсь данный подход кому нибудь помог сделать жизнь проще, а данные понятнее. Упрощает жизнь то, что вы получаете всегда форму аналогичную той, которую получили бы без параметров. Логика приложения становится значительно предсказуемой.
Ну и собственно реализация данной функции.
Автор: mpakep