Атрибуты модели со списком значений

Всем привет!

Наверняка многим приходилось иметь дело с атрибутами, заначения которых задаются фиксированным списком. Т.е. напр 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'));



На первый взгляд все красиво и удобно. Да и в случае наследования удобно переопределять набор значений. Как считаете нормальное решение?

Может я неправильно понял, но почему бы не сделать просто отдельную таблицу commerce_name и отдельную модель для нее. После чего связать две модели.

В выше приведенном решении:

[list=1]

[*]получиться всего одна таблица на все такие поля

[*]списки можно задавать как в виде простого списка, так и ассоциативного массива

[*]Просто переопределять наборы значений при наследовании

[/list]

А если захочется сделать поиск по этому атрибуту? Например найти все коммерческие объекты с атрибутом Офис?

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

просто:

$criteria = new CDbCriteria(‘condition’ => ‘name = :name’, ‘params’ => array(‘name’ => ‘офис’));

а вот напр если по операции, то в форме поиска имеем:

echo $form->dropDownList($model, ‘operation’, Commerce::model()->lookupList(‘operation’));

и далее как обычно

Потому как часто приходится с этим сталкиваться, хочется все-таки более универсальное решение иметь.