Кросспост моего хабратопика.
Коль скоро у вас в проекте используется база данных, то вам рано или поздно потребуются справочные таблицы. Такие таблицы я бы условно разбил на три категории:
- Небольшие справочники, до 10, реже 20 записей. Например – таблица статусов чего-нибудь (active|inactive|deleted как минимум).
- Средние справочники – от 20 до нескольких сотен записей. Например, таблица типов или категорий чего-либо.
- Большие справочники – от нескольких сотен до сотен тысяч записей. Например список городов и улиц России.
Справочники, как правило, заполняются разово при создании и крайне редко пополняются. Но тем не менее, пополнение возможно и наиболее вероятно для третьего типа, менее для второго и редко для первого.
Собственно зачем я это пишу:
Раз у вас есть таблица, то есть и классы модели для нее. Все хорошо, пока вам в коде не приходится сослаться на какое-то значение из справочника. Например есть таблица Status
:
| id | name | ---------------------------- | 1 | active | | 2 | inactive | | 3 | deleted |
В связанных таблицах мы имеем HasOne: Status
, и foreign key на status.id
.
И вот нам понадобилось выбрать все активные записи. Не долго думая мы пишем:
$query = Doctrine_Query::create() ->select() ->from( "Product p, p.Status s" ) ->where( "s.name = 'active'" ) //...
Oops. Джойн хорош, но нам постоянно добавлять его к любому запросу неинтересно. “Рефакторим”:
$query = Doctrine_Query::create() ->select() ->from( "Product p" ) ->where( "p.status_id = 1" ) //...
OOOOOooops. По проекту плодятся магические числа:
status_id = 2 type_id = 36 city_id = 1234
Стоп.
а) мы не хотим в каждый запрос, который требует связки со справочником пихать join (да и name=”active” тоже магическая константа по сути, но вербально понятная).
б) мы не хотим плодить магические числа.
И какой же выход?
Честно говоря, красивого выхода я не вижу. Для справочников типа 1 я применяю следующий подход:
// Status class StatusTable extends Doctrine_Table { const STATUS_ACTIVE = 1; const STATUS_INACTIVE = 2; const STATUS_DELETED = 3; ... } // Product class ProductTable extends Doctrine_Table { public function getActive() { ... ->addWhere( "p.status_id = ?", self::STATUS_ACTIVE ) // ну или как-то так :) } ... }
Этот подход более-менее работает только со справочниками типа 1 (при этом, при добавлении нового статуса попробуй еще вспомнить, что надо добавить еще одну константу, благо это не часто требуется).
Со справочниками типов 2 и 3 вообще не знаю что делать.
А как вы работаете со справочниками?
P.S. не факт что со справочниками типа 3 приходится работать “точечно”, поэтому для них может это и не актуально.