Введение в тему использования HTML::FormFu под Catalyst. Очень простые примеры, комментарии. Руководство для начинающих. Как создавать и обрабатывать формы.
Изначально, статья была написана специально для журнала "Pragmatic Perl" (см. оригинал). Для блога разделила публикацию на две части.
Все примеры были выполнены специально для публикации, в windows-среде, под Strawberry Perl.
Создаем интерфейс администратора с помощью HTML::FormFu и Catalyst
Панель администратора - это скрытый от обычных посетителей блок сайта, который позволяет владельцу осуществлять управление контентом сайта и принципами его отображения. Например, настроить список используемых виджетов, добавить новые публикации, разместить баннеры и т.п.
Почти вся админка - это бесконечное число разнообразных форм. Использование менеджера форм тут более чем оправдано.
Поэтому, в качестве простого примера, создадим примитивный интерфейс администратора:
- главную страницу панели администратора
- страницу со списком публикаций на сайте
- страницу для редактирования статей (на основе HTML::FormFu)
- страницу для создания новой публикации (на основе HTML::FormFu)
Кроме того, позволим пользователю удалять статьи.
Дамп БД
Для начала, нам потребуется база данных. Ниже - дамп БД, которая использовалась для приведенных примеров. Установить БД, если ее у вас нет, лучше еще до начала установки Catalyst с его модулями для создания моделей.
Теперь просто создаем таблицу и следим за кодировками, дабы избежать проблем в будущем. Как современные люди, мы выбираем utf-8.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
-- -------------------------------------------------------- -- Host: 127.0.0.1 -- Server version: 5.6.14 - MySQL Community Server (GPL) -- Server OS: Win32 -- HeidiSQL version: 7.0.0.4053 -- Date/time: 2013-10-07 20:42:30 -- -------------------------------------------------------- /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET NAMES utf8 */; /*!40014 SET FOREIGN_KEY_CHECKS=0 */; -- Dumping database structure for test CREATE DATABASE IF NOT EXISTS `test` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `test`; -- Dumping structure for table test.articles CREATE TABLE IF NOT EXISTS `articles` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `full` text, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- Dumping data for table test.articles: ~2 rows (approximately) /*!40000 ALTER TABLE `articles` DISABLE KEYS */; INSERT INTO `articles` (`id`, `name`, `full`) VALUES (1, 'name', 'text'), (2, 'name2', 'текст'); /*!40000 ALTER TABLE `articles` ENABLE KEYS */; /*!40014 SET FOREIGN_KEY_CHECKS=1 */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; |
Главная страница панели администратора
Для максимально удобной работы с HTML::FormFu в Catalyst, существует модуль Catalyst::Controller::HTML::FormFu . Если планируем в создаваемом контроллере использовать менеджер форм, подключаем Catalyst::Controller::HTML::FormFu с помощью extends.
Создать форму можно, либо определив ее параметры в непосредственно в коде, либо - по конфигурационному файлу. Конфигурационный файл предпочтительней. Во-первых, это все-таки элементы html-кода, и уже давно стало хорошим правилом отделять разметку от кода. Во-вторых, при создании панели администратора в боевых условиях, форм будет очень много, и удобнее хранить их отдельно.
Чтобы создать форму, нужно задать в атрибутах Catalyst action - :FormConfig(). Если не указать путь к форме в атрибуте :FormConfig, система решит, что в качестве имени формы следует использовать имя action. Поиск файла будет осуществляться примерно по такому пути: root/forms/controller_name/action_name.yml
Наличие атрибута :FormConfig говорит системе, что требуется создать объект формы и разместить его
в хранилище Catalyst - $c->stash->{form} . Чтобы вывести форму на html-странице, достаточно добавить в шаблон инструкцию: [% form %] . form - это полностью готовый блок html-кода формы.
Проверить, была ли отправлена форма и корректны ли ее данные, можно с помощью метода $form->submitted_and_valid.
Другой метод, позволит получить данные из полей формы: $form->param_value('field_name') . Кроме того, можно получить значения полей формы с помощью $c->req->param('field_name').
Модуль /lib/MyApp/Controller/Admin.pm
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package MyApp::Controller::Admin; use Moose; use namespace::autoclean; BEGIN { extends 'Catalyst::Controller'; } sub index :Path :Args(0) { my ( $self, $c ) = @_; $c->stash->{template} = 'admin/index.tt'; $c->forward('View::TT'); } __PACKAGE__->meta->make_immutable; 1; |
Шаблон /root/src/admin/index.tt
Переходим в директорию root. Создаем в ней каталог src. В каталоге src создаем каталог admin.
Не забываем, что все шаблоны должны быть в кодировке UTF-8 .
|
1 2 3 4 |
<h1>Панель администратора</h1> <ul> <li><a href="[% c.uri_for( 'articles' ).path_query %]">Список публикаций</a></li> </ul> |
Для наглядности, tt-шаблоны не содержат никакого html-кода, кроме самого необходимого.
Работа с публикациями
Модуль /lib/MyApp/Controller/Admin/Articles.pm
Один модуль будет отвечать и за отображение списка публикаций, и за создание новых, редактирование старых, и за удаление статей.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
package MyApp::Controller::Admin::Articles; use Moose; use namespace::autoclean; BEGIN { extends qw/ Catalyst::Controller::HTML::FormFu / } =head2 index Отображение страницы со списком статей =cut sub index :Chained('') :Path :Args(0) { my ( $self, $c ) = @_; $c->stash->{articles_list} = [$c->model('DB::Article')->search( {} )->all]; $c->stash->{template} = 'admin/articles.tt'; $c->forward('View::TT'); } =head2 remove Удаление статьи по ее идентификатору с БД =cut sub remove :Chained('') :Path('remove') :Args(1) { my ( $self, $c, $id ) = @_; $c->model('DB::Article')->find({ id => $id})->delete; $c->res->redirect($c->uri_for('/admin/articles')); } =head2 update Данный блок кода отвечает за отображение страницы для редактирования статьи, и за обновление статьи в БД. =cut sub update :Chained('') :Path('update') :Args(1) :FormConfig('article/update.yml') { my ( $self, $c, $id ) = @_; my $form = $c->stash->{form}; if ($form->submitted_and_valid) { eval { my $obj = $c->model('DB::Article')->update_or_create({ id => $form->param_value('id'), name => $form->param_value('name') || undef, full => $form->param_value('full') || undef }); }; $c->warn('Duplicate notice task error') if $@; } else { my $article = $c->model('DB::Article')->search( { id => $id, } )->first; $c->stash->{form}->default_values({ 'name' => $article->name, 'full' => $article->full, 'id' => $article->id }); } $c->stash->{template} = 'admin/article/update.tt'; $c->forward('View::TT'); } =head2 create Страница для создания новой статьи. Если пользователь нажал кнопку "Сохранить", статья отправляется в БД, затем клиента перенаправляют на страницу со списком статей. =cut sub create :Chained('') :Path('create') :Args(0) :FormConfig('article/create.yml') { my ( $self, $c, $id ) = @_; my $form = $c->stash->{form}; if ($form->submitted_and_valid) { eval { my $obj = $c->model('DB::Article')->create({ name => $form->param_value('name') || undef, full => $form->param_value('full') || undef }); }; $c->warn('Duplicate notice task error') if $@; $c->res->redirect($c->uri_for('/admin/articles')); } else { $c->stash->{template} = 'admin/article/create.tt'; $c->forward('View::TT'); } } __PACKAGE__->meta->make_immutable; 1; |
Метод default_values() - позволяет задать значения "по-умолчанию" полям формы, то, что увидит пользователь, если откроет страницу с формой.
Можно использльзовать метод $form->submitted , чтобы понять - была форма отправлена или нет. Форма может быть отправлена, но не пройти валидацию. Метод $form->submitted_and_valid учитывает и отправку, и благополучное прохождение валидации.
Шаблон /root/src/admin/articles.tt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Формочка</title> <link rel="stylesheet" type="text/css" href="/static/style.css" /> </head> <body> <table cellspacing="0" id="result_list"> [% FOREACH article = articles_list %] <tr> <td> <a href="[% c.uri_for( 'update', article.id ).path_query %]"> [% article.name %]</a> <a href="[% c.uri_for( 'remove', article.id ).path_query %]">Удалить</a> </td> </tr> [% END %] </table> <a href="[% c.uri_for( 'create' ).path_query %]">Добавить новую статью</a> </body> </html> |
Шаблон /root/src/admin/article/update.tt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Формочка</title> <link rel="stylesheet" type="text/css" href="/static/style.css" /> </head> <body> Update article [% form %] </body> </html> |
Шаблон /root/src/admin/article/create.tt
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Формочка</title> <link rel="stylesheet" type="text/css" href="/static/style.css" /> </head> <body> Create new article [% form %] </body> </html> |
CSS-стили для формы /root/static/style.css
Добавим совсем простую css-таблицу, которая позволяет аккуратно вывести элементы формы. В дальнейшем, css можно усложнить, создавая с его помощью профессиональное оформление всей панели администратора.
|
1 2 3 4 5 6 7 8 9 10 11 |
form { width: 40em; } .submit { display: block; } label { display: block; } |
YML-конфиг для формы /root/forms/article/update.yml
По-умолчанию, catalyst-приложение будет искать формы в директории root/forms . Для работы с конфигурационными файлами, Catalyst::Controller::HTML::FormFu использует Config::Any. Соответственно, хранить конфигурационную информацию о формах кроме yml-формата, можно в XML, JSON, конфигах в стиле Apache, perl-коде и т.п.
Переходим в директорию root. Создаем в ней каталог forms. В каталоге forms создаем каталог article и файл update.yml.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
--- attributes: id: element-form auto_fieldset: attributes: class: module aligned --- elements: - type: Hidden name: id - type: Text name: name label: Название статьи - type: Textarea name: full label: Текст статьи - type: Submit name: submit value: Сохранить |
YML-конфиг для формы /root/forms/article/create.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
--- attributes: id: element-form auto_fieldset: attributes: class: module aligned --- elements: - type: Text name: name label: Название статьи - type: Textarea name: full label: Текст статьи - type: Submit name: submit value: Сохранить |
Вот и все. Простой прототип панели администратора с использованием HTML::FormFu готов. Теперь, на основе полученных результатов, можно пробовать усложнять формы, вводить в работу сложные поля и правила валидации, добавлять JS для работы со сложными элементами, CSS для создания современного интерфейса.
Похожие публикации на блоге программиста
Как создать Catalyst-приложение с нуля
Полезные ссылки по теме Catalyst и HTML::FormFu
Catalyst::Controller::HTML::FormFu
Dynamic forms with HTML::FormFu
HTML::FormFu. How FormFu works
Handles forms, so you don't have to
девушка, в ваших статьях ничего нет об model('DB::Article')
откуда должны взяться методы для их самому создавать или както можно сгенерировать?
Пример создания модели был в предыдущей заметке: https://dev-lab.info/2013/11/%D0%BA%D0%B0%D0%BA-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C-catalyst-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81-%D0%BD%D1%83%D0%BB%D1%8F/
А это дополнительные материалы: http://search.cpan.org/~gbjk/Catalyst-Model-DBIC-Schema-0.65/lib/Catalyst/Model/DBIC/Schema.pm
В данной заметке примеры кода сильно урезаны, чтобы выделить только самое главное.