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

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

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

#1 User is offline   puritania 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 14-August 09
  • Location:Russia, Chelyabinsk

Posted 10 February 2012 - 01:53 AM

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


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

#2 User is offline   j0ker_ 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 35
  • Joined: 22-December 10
  • Location:Russia, Yaroslavl

Posted 10 February 2012 - 02:21 AM

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

#3 User is offline   puritania 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 14-August 09
  • Location:Russia, Chelyabinsk

Posted 10 February 2012 - 02:42 AM

View Postj0ker_, on 10 February 2012 - 02:21 AM, said:

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


В выше приведенном решении:
  • получиться всего одна таблица на все такие поля
  • списки можно задавать как в виде простого списка, так и ассоциативного массива
  • Просто переопределять наборы значений при наследовании

0

#4 User is offline   j0ker_ 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 35
  • Joined: 22-December 10
  • Location:Russia, Yaroslavl

Posted 10 February 2012 - 02:56 AM

View Postpuritania, on 10 February 2012 - 02:42 AM, said:

В выше приведенном решении:
  • получиться всего одна таблица на все такие поля
  • списки можно задавать как в виде простого списка, так и ассоциативного массива
  • Просто переопределять наборы значений при наследовании


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

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

#5 User is offline   puritania 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 14-August 09
  • Location:Russia, Chelyabinsk

Posted 10 February 2012 - 03:33 AM

View Postj0ker_, on 10 February 2012 - 02:56 AM, said:

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

просто:
$criteria = new CDbCriteria('condition' => 'name = :name', 'params' => array('name' => 'офис'));
а вот напр если по операции, то в форме поиска имеем:
echo $form->dropDownList($model, 'operation', Commerce::model()->lookupList('operation'));
и далее как обычно

View Postj0ker_, on 10 February 2012 - 02:56 AM, said:

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

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

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users