Атрибут типа "Дата" организованный 3-dropDownList

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
slips
Сообщения: 106
Зарегистрирован: 2011.02.24, 16:04
Откуда: Россия, Москва
Контактная информация:

Атрибут типа "Дата" организованный 3-dropDownList

Сообщение slips »

Добрый вечер, хочу поделиться своими наработками(не без участия rak и mc-bear, может кому и пригодиться.
Задача: В таблице есть поле типа "Дата", сделать приложение в котором это поле можно было бы заполнять с помощью трёх dropDownList.
1. Модуль (выполняем следующие шаги)
1.1. Объявляем переменную

Код: Выделить всё

public $DateArr; 
1.2. Назначаем правила валидации:

Код: Выделить всё

  public function rules(){
    return array(
    array('DateArr', 'required'),
    array('Dateofbirth','type','type'=>'date','dateFormat'=>'yyyy-M-d','allowEmpty'=>true,
              'message'=>'Некорректно указана дата.'),
        );
    }
 
1.3. Переопределяем метод (beforeValidate())

Код: Выделить всё

  public function beforeValidate(){
    foreach($this->attributeNames() as $name):
      if (strcmp($this->tableSchema->getColumn($name)->dbType,'date')==0):
        $temp=$this->DateArr[$name];
        $this->$name=(empty($temp['year']) && empty($temp['month']) && empty($temp['day'])) ?
          NULL : $temp['year'].'-'.$temp['month'].'-'.$temp['day'];
      endif;
    endforeach;
     return parent::beforeValidate();
   }
  
1.4. Переопределяем метод (afterFind())

Код: Выделить всё

 public function afterFind(){
     foreach($this->attributeNames() as $name) :
       if (strcmp($this->tableSchema->getColumn($name)->dbType,'date')==0) :
        $bd = array();
        list($bd['year'],$bd['month'],$bd['day'])=(!is_NULL($this->$name)) ?
            explode('-', $this->$name) : array(0,0,0);
        foreach($bd as $key => $val)
          $this->DateArr[$name][$key]=(int)$val;
       endif;
     endforeach;
     parent::afterFind();
    }
 
1.5. Создаём метод заполнения(Его можно вынести в родительский ActiveRecord)

Код: Выделить всё

public static function getRange($start, $end){
     $range = array();
     for ($i=$start; $i<=$end; $i++) $range[$i]=$i;
   return $range;
   }
 
2. Во вью :
2.1.

Код: Выделить всё

<?php echo $form->dropDownList($model,'DateArr[Dateofbirth][day]',$model->getRange(1,31),array('empty' => 'День')); ?>
<?php echo $form->dropDownList($model,'DateArr[Dateofbirth][month]',$model->getRange(1,12),array('empty' => 'Месяц')); ?>
<?php echo $form->dropDownList($model,'DateArr[Dateofbirth][year]',$model->getRange(1940,2011),array('empty' => 'Год')); ?>


Вот собственно и всё.
Если в таблице есть несколько полей то например ещё поле с названием "Data2"
то измениться всего несколько строк в модели, а именно в:

Код: Выделить всё

array('Dateofbirth,Data2','type','type'=>'date','dateFormat'=>'yyyy-M-d','allowEmpty'=>true,
              'message'=>'Некорректно указана дата.'),
        );
 
А во вью соответственно добавиться ещё кусок кода:

Код: Выделить всё

<?php echo $form->dropDownList($model,'DateArr[date2][day]',$model->getRange(1,31),array('empty' => 'День')); ?>
<?php echo $form->dropDownList($model,'DateArr[date2][month]',$model->getRange(1,12),array('empty' => 'Месяц')); ?>
<?php echo $form->dropDownList($model,'DateArr[date2][year]',$model->getRange(1940,2011),array('empty' => 'Год')); ?>
Аватара пользователя
mitaichik
Сообщения: 512
Зарегистрирован: 2010.09.24, 21:18
Откуда: Россия, Санкт-Петербург

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение mitaichik »

Молодец! Но лучше все это оформить в виде виджета, или еще вынести куда-нить. ИМХО, слишком много кода в моделе для простого поля даты ) Лично я бы сделал так: написал виджет, который берет из поля дату, разбивает ее, генерирует dropDown'ы (причем dropDown с именами типа Model_datafield_day, Model_datafield_year...) и т.д. В этом виджете было бы скрытое поле Model_datafield (собственно, которое и будет присваиваться аттрибуту). А при изменении какого-либо dropDown'a, записывает в это скрытое поле кооректное Data значение, которое потом уже на сервере и валидируется, и атрибуту присваивается.

Плюсы - абсолютно все располагается в виджете (кроме правила валидации). И подключается одной строчкой.

Минус - не работает с откл. JavaScript
Последний раз редактировалось mitaichik 2011.03.10, 00:53, всего редактировалось 1 раз.
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение slavcodev »

Лучше всего это в поведение модели засунуть. И цикл чтения всех атрибутов лишний, можно указывать нужные поля при подключении поведения.
Жду Yii 3!
rak
Сообщения: 2181
Зарегистрирован: 2010.11.02, 23:40
Контактная информация:

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение rak »

плюсом в виджете ещё может быть подключение js с валидатором, чтобы не оказалось 31 февраля итп...
slips
Сообщения: 106
Зарегистрирован: 2011.02.24, 16:04
Откуда: Россия, Москва
Контактная информация:

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение slips »

mitaichik писал(а):лучше все это оформить в виде виджета, или еще вынести куда-нить.
Плюсы - абсолютно все располагается в виджете (кроме правила валидации). И подключается одной строчкой.
Минус - не работает с откл. JavaScript
Думаю стоит подумать над тем что вы говорите, но самой первой причиной по которой я отказался от виджетов так это то что они очень грамоздки, да согласен огромный плюс что нужно написать всего одну строчку и забыть. Всё остальное сделает виджет. По-этому пока трудно оценить ситуацию, попробую сделать виджет и посмотреть что будет из этого.
Очередной велосипед или же что-то интересное.
mc-bear писал(а): Лучше всего это в поведение модели засунуть. И цикл чтения всех атрибутов лишний, можно указывать нужные поля при подключении поведения.
ну опять таки будет дополнительное поведение. (Конечно перебор в цикле мне сразу показалось весьма не правильным, учитывая что к примеру будет 10-15 полей из которых всего одна дата. Уже окончательно отбрасывает перебор).
rak писал(а): плюсом в виджете ещё может быть подключение js с валидатором, чтобы не оказалось 31 февраля итп...
Ну сейчас тоже происходит валидация и 31 число не попадёт в БД как бы этого не хотелось.
Не пускает правило валидации или я не прав? По-крайней мере у меня пускает только "Правильную дату" и пустоту

Код: Выделить всё

array('Dateofbirth','type','type'=>'date','dateFormat'=>'yyyy-M-d','allowEmpty'=>true,
              'message'=>'Некорректно указана дата.'),
        );
 
rak
Сообщения: 2181
Зарегистрирован: 2010.11.02, 23:40
Контактная информация:

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение rak »

slips писал(а):
rak писал(а): плюсом в виджете ещё может быть подключение js с валидатором, чтобы не оказалось 31 февраля итп...
Ну сейчас тоже происходит валидация и 31 число не попадёт в БД как бы этого не хотелось.
Не пускает правило валидации или я не прав? По-крайней мере у меня пускает только "Правильную дату" и пустоту
Валидация то не проходит, но выбрать неправильную дату в селектах можно.
slips
Сообщения: 106
Зарегистрирован: 2011.02.24, 16:04
Откуда: Россия, Москва
Контактная информация:

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение slips »

rak писал(а): Валидация то не проходит, но выбрать неправильную дату в селектах можно.
Извиняюсь не так понял. Полностью с вами согласен. Но тогда придётся писать правила валидации ещё и на клиенте.
Аватара пользователя
vitaxa_prog
Сообщения: 306
Зарегистрирован: 2011.06.06, 22:44
Откуда: Волноваха

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение vitaxa_prog »

Уважаемые форумчане, прошу прощения, что снова подымаю эту тему, но...
Попытался реализовать этот пример, но не происходит присваивания атрибутов в контроллере при сохранении. Я совсем не много еще изучаю Yii. Я чувствую, что я что то упустил, но не могу понять, что.
Если не затруднит, ткните пожалуйста носом.
Спасибо.
В принципе ничего нет невозможного.
— Вы думаете?
— Для человека. С интеллектом.
Аватара пользователя
anton44eg
Сообщения: 2716
Зарегистрирован: 2012.01.25, 13:37
Откуда: Киев

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение anton44eg »

аттрибуты в rules прописаны?
Аватара пользователя
vitaxa_prog
Сообщения: 306
Зарегистрирован: 2011.06.06, 22:44
Откуда: Волноваха

Re: Атрибут типа "Дата" организованный 3-dropDownList

Сообщение vitaxa_prog »

Да, атрибуты прописаны. Спасибо за ответ. Просидел ночь, разобрался. Может конечно не правильно. Но работает.
Исправил вот здесь

Код: Выделить всё

public function beforeValidate()
    {

        foreach($this->attributeNames() as $name)
        {

            if (strcmp($this->tableSchema->getColumn($name)->dbType,'date')==0)
            {

                $temp = $this->DateArr[$name];
                //Здесь все время приходил NULL, не зависмо от того есть данные в массиве или нет
                //$this->$name=(empty($temp['year']) && empty($temp['month']) && empty($temp['day'])) ?
                    //NULL : $temp['year'].'-'.$temp['month'].'-'.$temp['day'];
                $this->$name = $temp['year'].'-'.$temp['month'].'-'.$temp['day'];
            }

        }

        return parent::beforeValidate();
    } 
И в правилах указал правило валидации для своего поля даты

Код: Выделить всё

array('birthday','type','type'=>'date','dateFormat'=>'yyyy-m-d','allowEmpty'=>false,
                'message'=>'Incorrectly listed the date of.'), 
Теперь работает. Не проверил конечно всесторонне, насколько правильно работает. Но пока хоть так.
В принципе ничего нет невозможного.
— Вы думаете?
— Для человека. С интеллектом.
Ответить