Введение
Я давно работаю с yii framework. И пока это единственный framework в мире php. Из минусов для меня то, что он слишком низкоуровневый, отсутствует много плюшек, которые я с успехом возмещаю разумным использованием Zend компонент. Как набор компонент Zend хорош, чего не скажешь о его framework'е.
Ну так вот, возвращаясь к низкоуровневому yii. Его CRUD хорош, хорош для прототипирования, но плодит кучу файлов. Многие из которых со временем вырезаются и сильно модифицируются. Моим кошмаром была работа на небольшим по объему backend проектом. Где вся работа сводилась к администрированию кучи таблиц с текстовыми и буленовскими полями. При помощи CRUD все было сделано быстро, но большую часть времени я потратил на украшение админки, checkboxes вместо input, фильтры вида true|false вместо 0,1 и тому подобной ерунды. Таблиц было много, view еще больше. Я с нежностью вспоминал django и жалел что проект на PHP.
Прошло время, и вот во время работы над очередным проектом выдалась несколько часов, в результате которых было рождено небольшое расширение над CRUD.
Краткая суть. CRUD очень похожи, и их можно объединить. Второй задачей является способ указания системе типов данных в моделях, для того чтобы CRUD мог на основе этих типов создавать фильтры, приводить к строковому виду автоматически.
Что получилось? Получился модуль который позволяет не запуская CRUD получить CRUD странички над любой моделью при условии что она отнаследована от особого ActiveRecord + в ней определен один единственный метод. В качестве небольшого бонуса есть простая возможность слегка менять список полей и их порядок на полученных страницах.
Ниже небольшой туториал как заставить это работать. Текста много, но он расчитан на новичка в yii. Если вы накоротке с yii можете сразу читать с установки модуля.
Инициализация yii проекта
Можно пропустить, если хотите воспользоваться существующим.
Описание как создать yii проект с нуля. Для того чтобы потом использовать модуль.
Создание директории проекта.
Я буду использовать локальный вебсервер, с дефолтными настройками. Проект создам в папке AdminTest внутри моего document root /var/www/
claymore:$ mkdir /var/www/AdminTest
claymore:$ cd /var/www/AdminTest/
claymore:$
Папка создана, скачиваем yii-framework
Среда 2011-03-30 11:03 box:/var/www/AdminTest
claymore:$ wget http://yii.googlecode.com/files/yii-1.1.7.r3135.tar.gz
--2011-03-30 11:12:58-- http://yii.googlecode.com/files/yii-1.1.7.r3135.tar.gz
Преобразование адреса yii.googlecode.com... 74.125.87.82
Устанавливается соединение с yii.googlecode.com|74.125.87.82|:80... соединились.
Запрос HTTP послан, ожидание ответа... 200 OK
Длина: 2550331 (2,4M) [application/x-gzip]
Saving to: «yii-1.1.7.r3135.tar.gz»
100%[=============================================================================================================================>] 2 550 331 780K/s в 3,2s
2011-03-30 11:13:01 (780 KB/s) - «yii-1.1.7.r3135.tar.gz» saved [2550331/2550331]
Распаковываем
claymore:$ tar xf yii-1.1.7.r3135.tar.gz
Переименовываем, или делаем символическую ссылку( кому как удобнее), я переименовываю, т.к. работаю в рамках демонстрации
claymore:$ mv yii-1.1.7.r3135 yii
Удаляю скаченный архив
claymore:$ rm yii-1.1.7.r3135.tar.gz
Проверяем что у нас есть распаковааная папка с yii framework
claymore:$ ls
yii
Переходим в папку со скриптами yii framework
claymore:$ cd yii/framework/
Запускаем скрипт создания проекта
claymore:$ ./yiic webapp /var/www/AdminTest/
Create a Web application under '/var/www/AdminTest'? [Yes|No] Yes
mkdir /var/www/AdminTest/css
generate css/form.css
generate css/main.css
generate css/bg.gif
generate css/ie.css
generate css/screen.css
generate css/print.css
mkdir /var/www/AdminTest/assets
mkdir /var/www/AdminTest/images
generate index.php
generate index-test.php
mkdir /var/www/AdminTest/themes
mkdir /var/www/AdminTest/themes/classic
mkdir /var/www/AdminTest/themes/classic/views
mkdir /var/www/AdminTest/themes/classic/views/site
mkdir /var/www/AdminTest/themes/classic/views/layouts
generate themes/classic/views/.htaccess
mkdir /var/www/AdminTest/themes/classic/views/system
mkdir /var/www/AdminTest/protected
mkdir /var/www/AdminTest/protected/data
generate protected/data/schema.sqlite.sql
generate protected/data/testdrive.db
generate protected/data/schema.mysql.sql
generate protected/yiic
mkdir /var/www/AdminTest/protected/messages
mkdir /var/www/AdminTest/protected/tests
mkdir /var/www/AdminTest/protected/tests/unit
mkdir /var/www/AdminTest/protected/tests/functional
generate protected/tests/functional/SiteTest.php
generate protected/tests/phpunit.xml
generate protected/tests/bootstrap.php
generate protected/tests/WebTestCase.php
mkdir /var/www/AdminTest/protected/tests/fixtures
mkdir /var/www/AdminTest/protected/tests/report
mkdir /var/www/AdminTest/protected/views
mkdir /var/www/AdminTest/protected/views/site
mkdir /var/www/AdminTest/protected/views/site/pages
generate protected/views/site/pages/about.php
generate protected/views/site/login.php
generate protected/views/site/index.php
generate protected/views/site/contact.php
generate protected/views/site/error.php
mkdir /var/www/AdminTest/protected/views/layouts
generate protected/views/layouts/column1.php
generate protected/views/layouts/column2.php
generate protected/views/layouts/main.php
mkdir /var/www/AdminTest/protected/runtime
generate protected/.htaccess
mkdir /var/www/AdminTest/protected/components
generate protected/components/Controller.php
generate protected/components/UserIdentity.php
mkdir /var/www/AdminTest/protected/config
generate protected/config/main.php
generate protected/config/test.php
generate protected/config/console.php
mkdir /var/www/AdminTest/protected/commands
mkdir /var/www/AdminTest/protected/commands/shell
mkdir /var/www/AdminTest/protected/controllers
generate protected/controllers/SiteController.php
mkdir /var/www/AdminTest/protected/models
generate protected/models/ContactForm.php
generate protected/models/LoginForm.php
mkdir /var/www/AdminTest/protected/extensions
generate protected/yiic.bat
generate protected/yiic.php
mkdir /var/www/AdminTest/protected/migrations
Your application has been created successfully under /var/www/AdminTest.
Среда 2011-03-30 11:03 box:/var/www/AdminTest/yii/framework
claymore:$
Проверяем
claymore:$ wget http://127.0.0.1/AdminTest/index.php -q -O - | grep Yii
....
Congratulations! You have successfully created your Yii application.
...
Создаем базу данных admintest. При помощи вашего любимого средства.
mysql> create database admintest;
Query OK, 1 row affected (0.02 sec)
Прописываем настройки базы данных в protected/config/main.php
Теперь у нас есть болванка для веб сайта на основе шаблона yii.
Установка модуля.
Переходим в директорию расширений. (Если пропустили первый шаг, замените /var/www/AdminTest/ на путь до папки вашего проекта, содержащей protected)
claymore:$ cd /var/www/AdminTest/protected/extensions/
Скачиваем расширение.
claymore:$ hg clone -q https://yii-rextensions.googlecode.com/hg/ YiisyCrudAdmin -r YiisyCrudAdmin
[Опционально] удаляем информацию о репозитории, особенно ваш проект уже под системой контроля версий.
claymore:$ rm -rf YiisyCrudAdmin/.hg
Среда 2011-03-30 11:03 box:/var/www/AdminTest/protected/extensions
Модуль установлен.
Пример создания crud административной страницы.
Для примера нам понадобится любая модель.
Создаем таблицу в созданной базе данных.
mysql> create table example(id int primary key auto_increment, name char(20), is_good_record tinyint(1) default 0 , long_description text);
Query OK, 0 rows affected (0.08 sec)
Переходим в папку protected
claymore:$ cd /var/www/AdminTest/protected
Создаем модель.
claymore:$ ./yiic shell config/main.php
Yii Interactive Tool v1.1 (based on Yii v1.1.7)
Please type 'help' for help. Type 'exit' to quit.
>> model Example example
generate models/Example.php
generate fixtures/example.php
generate unit/ExampleTest.php
The following model classes are successfully generated:
Example
If you have a 'db' database connection, you can test these models now with:
$model=Example::model()->find();
print_r($model);
>>
Модифицируем модель.
Цель. Отнаследоваться от расширения CActiveRecord объявленному в YiisyCrudAdmin.RActiveRecord. И реализовать абстрактный метод getFieldsDescription
Открываем /var/www/AdminTest/protected/models/Example.php в любимом редакторе
Yii::import("ext.YiisyCrudAdmin.RActiveRecord"); //Добавляем эту строчку импорта в верх файла.
В модель Example добавляем новый метод
Yii::import("ext.YiisyCrudAdmin.RActiveRecord");
class Example extends RActiveRecord
{
//...
// в последней версии данный метод не требуется в модели, может создаваться по желанию в классе ExampleAdmin
public function getFieldsDescription()
{
return array(
'is_good_record' => 'RDbBoolean',
'long_description' => 'RDbText',
);
}
//...
}
Этот метод предоствляет расширенную информацию о полях модели. На данный момент реализованы пока Bool и Text.
Т.к. метод абстрактный ( чтобы про него не забывали), реализация обязательна, метод может возвращать пустой массив если нет желания заморачиваться.
Создаем в вашем любимом редакторе controllers/ExampleController.php
Yii::import('ext.YiisyCrudAdmin.RController');
class ExampleController extends RController
{
protected $_modelName = 'Example';
}
Тестируем
Открываем в браузере http://127.0.0.1/AdminTest/index.php?r=example/admin
Получаем типичный yii crud с небольшими улучшениями.
- Поля, отмеченные как boolean, отображаются в виде чекбоксов при редактировании. Также в наличии встроенный фильтр для этих полей на странице actionAdmin.
- Текстовые поля при редактировании редактируются в textarea. При просмотре в griidview обрезаются. (Пока и в view обрезаются, но это уже решаемый вопрос :) )
Из плюсов такого подхода, все сделано стандартными средствами yii. Т.е. после этапа прототипирования, вы уже можете использовать существующую базу кода, достаточно заглянуть в RController
Гибкость, например в методе getFieldsDescription модели, элеметом массива может быть массив, формирующий CGridColumn, в этом случае все обрабатывается в обычном для yii ключе.
Улучшаем внешний вид
Как поменять порядок полей в actionAdmin ?
Прямо в файле модели создаем класс
Yii::import('ext.YiisyCrudAdmin.RModelAdmin');
class ExampleAdmin extends RModelAdmin
{
public function getAdminFields()
{
return array(
'name', 'long_description', 'is_good_record', 'id'
);
}
}
После этого в actionAdmin наблюдаем поля в указанном порядке
.
Как исключить поле из отображения в actionAdmin ?
Yii::import('ext.YiisyCrudAdmin.RModelAdmin');
class ExampleAdmin extends RModelAdmin
{
public function getAdminExcludedFields()
{
return array(
'id',
);
}
}
И это все. Оба метода можно комбинировать.
Ну и вот интерфейс RModelAdmin, отвечающий за порядок и отображаемые поля
public function getViewExcludedFields();// список полей для исключения в actionView
public function getAdminExcludedFields();//список полей для исключения в actionAdmin
public function getViewFields();// список полей для отображения в actionView
public function getSearchFields();//список полей для отображения в расширенной форме поиска actionAdmin
public function getAdminFields();// список полей для отображения в actionAdmin
public function getFormFields();// список полей для создания/редактирования.
Почему методы а не массивы? Например для динамической генерации в зависимости от условий.
UPDATED:
В последней версии метод getFieldsDescription перенесен из модели в ModelAdmin класс.
6 comments:
Доброе время суток!
Очень понравился ваш подход:). А вы забросили проект? Или есть какие-то новые версии, которые вы просто не выкладывали?
Ну есть более новая версия, там чуть другой подход, в плане еще меньше кода писать :)
Но я не люблю делать вещи ради вещей, а т.к. в последнее время нет проектов где требуется админка, то он не развивается. :)
Как появится такой проект, кстати возможно в одном из своих понадобится. То буду развивать дальше.
Понятно:). Не поделитесь?:)
Чего вот сейчас у вас не хватает, так это работы с MANY_MANY. Я, вообще, с Yii не работал практически, пару дней только копаю:), но мне кажется вполне это можно допилить, смотрел одним глазком код, который генерирует giix, вроде там всё просто. Попробую это сделать, если хватит умения разобраться:).
Так я на данный момент не готов, давайте на выходных меня поймаете? В гугле толке? zadoev gmail.com. Я посмотрю где чего лежит, и в контекст въеду, как раз над своим проектом надо поработать, а там админка нужна.
В любом разе, быстро не обещаю. Но могу повспоминать, дать доступ к репозиторию и рекомендации, ну и помочь при необходимости.
Хорошо, попробую вас поймать на выходных:)
Post a Comment