Yii - Магазин 3.1: допиливаем Book

09.05.2012

Понял, что не хватает пары вещей:

  1. Добавим в модель Book поле image, в нем будим хранить название изображение;
  2. Поработаем с представлением admin — посмотрим анонимные функции в действии.

Git Rep - https://github.com/neo-classic/YiiShop

Дамп базы находится там же - /protected/data/

Дорабатываем модель Book

Добавляем поле image (varchar(255)) в таблицу tbl_book.

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

Итак, добавляем поле image в правила валидации модели(rules()):

array('image', 'unsafe'),

И не забываем добавить какой-нить лейбл для поля.

Второе — добавим поле в форму:

echo $form->labelEx($model,'image');
echo $form->fileField($model, 'image');
echo $form->error($model,'image');
if(!$model->isNewRecord) {
    echo CHtml::image(Yii::app()->baseUrl.'/images/books/' .$model->id . $model->image, $model->title, array('height'=>100));
}

Видим что здесь также есть проверка — если мы обновляем запись, то покажем миниатюру изображения рядом с полем ввода.

И не забываем указать enctype для формы:

$form=$this->beginWidget('CActiveForm', array(
    'id'=>'book-form',
    'enableAjaxValidation'=>false,
    'method' => 'post',
    'htmlOptions'=>array('enctype'=>'multipart/form-data'),
)); 

Также нужно поправить контроллер:

public function actionCreate() {
    $model=new Book;
    if(isset($_POST['Book'])) {
        $model->attributes=$_POST['Book'];
        $file_image = CUploadedFile::getInstance($model, 'image');
        if(is_object($file_image) && get_class($file_image) === 'CUploadedFile')
            $model->image = $file_image;
        if($model->save()) {
            if(is_object($file_image)) {
                $model->image->saveAs($_SERVER['DOCUMENT_ROOT'] . '/images/books/' .$model->id . $model->image);
            }
            $this->redirect(array('admin'));
        }
    }
    $this->render('create',array(
        'model'=>$model,
    ));
}

public function actionUpdate() {
    $model=$this->loadModel();
    if(isset($_POST['Book'])) {
        $model->attributes=$_POST['Book'];
        $file_image = CUploadedFile::getInstance($model, 'image');
        if(is_object($file_image) && get_class($file_image) === 'CUploadedFile')
            $model->image = $file_image;
        if($model->save()) {
            if(is_object($file_image)) {
                $model->image->saveAs($_SERVER['DOCUMENT_ROOT'] . '/images/books/' .$model->id . $model->image);
            }
            $this->redirect(array('admin'));
        }
    }
    $this->render('update',array(
        'model'=>$model,
    ));
}

Обратите внимание на переменную $file_image и манипуляции с ней! Кроме этого создаем папку images/books — доступную для записи сервером.

Здесь есть пару нюансов, которые можно доработать:

  1. После сохранения изображения, можно отдельно сохранить миниатюру, меньшего размера — я делал это при помощи расширения — http://yiiext.github.com/extensions/image-component/index.html. Дальше в статьях напишу об этом.
  2. Можно объединить действия create и update в одно. Дорабатывайте!)
  3. Как видно файл сохраняется как id+Имя_Файла. Ну это вроде как уменьшает вероятность названия одинаковых файлом...тут тоже можно подумать.

Вот что в итоге у нас получилось:

Форма добавление продукта

Оставим всё как есть и пойдем дальше!

Посмотрим как сейчас выглядит представление admin

Default admin

Пара проблем:

  1. Столбец Категория — отображает id категории;
  2. Убрать описание книги — зачем нам оно в админской части?;
  3. Добавим столбец для отображения Изображения книги — используем http://yiiext.github.com/extensions/zii-image-column/readme.ru.html .

Недавно, на работе просматривай код, написанный Костей Перминовым (devkp.ru) — он во всю уже начал использовать анонимные функции, давайте тоже так и сделаем. Итак — правим представление admin для отображения названия категории:

array(
    'name' => 'book_type',
    'filter' => BookType::model()->getAllTypes(),
    'value' => function($data) {
        return $data->category->title;
    }
),

Обратите внимание на свойство 'value'. В PHP до 5.3 нужно было писать так:

'value' => '$data->category->title',

Конечно можно и так, но анонимные функции добавляют гибкости к приложению.
Идем дальше — давайте подключим расширение image-column для CgridView. Для этого — распаковываем его в директорию extensioins и добавляем в конфиг в раздел import:

'ext.imageColumn.EImageColumn',

Последний этап — добавляем саму колонку для изображений в наш грид:

array(
    'class' => 'EImageColumn',
    'imagePathExpression' => 'Yii::app()->baseUrl."/images/books/".$data->id.$data->image',
    'emptyText' => '—',
    'imageOptions' => array(
        'height' => 100,
    ),
),

Вот что у нас в итоге получилось:

Готовая форма администрирования

На этом всё! Думаю нам ещё придется вернуться к админскому представлению когда будим строить модуль admin, но правок будет не так много!

 

Пишим магазин на Yii (Часть 1Часть 2, Часть 3).

blog comments powered by Disqus
Наверх