Всем привет!
Наверняка многим приходилось иметь дело с атрибутами, заначения которых задаются фиксированным списком. Т.е. напр Commerce::name, возможные значения array(‘Офис’, ‘Магазин’)
Как поступал обычно:
/*
пример использования echo $form->dropDownList($model, 'name', Realty::listName());
*/
class Realty exctends CActiveRecord
{
public static function listName()
{
return array('Офис', 'Магазин');
}
}
При необходимости значения в наследниках можно перекрыть. Но при увеличении кол-ва таких полей класс модели превращается в бардак. Что было сделано:
class ActiveRecord extends CActiveRecord
{
public function lookupList($attribute)
{
$class = get_class($this);
$parents = array($class.'_'.$attribute);
$reflection = new ReflectionClass(get_class($this));
while ($parent = $reflection->getParentClass())
{
$parents[] = $parent->getName().'_'.$attribute;
$reflection = $parent;
}
$parents[] = $attribute;
$rows = Yii::app()->db->createCommand()
->select('name, text')
->from('lookup')
->where(array('in', 'name', $parents))
->queryAll();
$data = array();
foreach($rows as $row)
{
$data[ $row['name'] ] = $row['text'];
}
$list = array();
foreach($parents as $name)
{
if(isset($data[$name]))
{
$list = self::parseLookup($data[$name]);
}
}
return $list;
}
public static function parseLookup($text)
{
$list = array();
if(!empty($text))
{
$data = explode("\n", $text);
if($n = count($data))
{
foreach($data as $i=>$line)
{
$line = explode('|', $line);
$key = trim($line[0]);
if($key !== '')
{
$list[$key] = isset($line[1]) ? trim($line[1]) : $key;
break;
}
}
}
}
return $list;
}
}
Структура таблицы lookup:
CREATE TABLE IF NOT EXISTS `lookup` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`text` text,
PRIMARY KEY (`id`),
UNIQUE KEY `IDX_NAME` (`name`)
)
Далее запоолняем таблицу:
INSERT INTO `lookup` (`name`, `text`) VALUES
('operation', '1|Продажа\r\n2|Аренда'),
('Commerce_name', 'Офис\r\nМагазин'),
('Residential_name', 'Квартира\r\nКомната');
или тоже самое делаем сгенерировав модель и crud для lookup.
Теперь наследуем все модели от ActiveRecord и пользуемся
class Realty extends AcriveRecord {...}
class Commerce extends Realty {...}
class Residential extends Realty {...}
...
echo $form->dropDownList($model, 'name', $model->lookupList('name'));
echo $form->dropDownList($model, 'operation', $model->lookupList('operation'));
На первый взгляд все красиво и удобно. Да и в случае наследования удобно переопределять набор значений. Как считаете нормальное решение?