Статьи

Простое создание форм с помощью FuelPHP

Благодаря классу полей FuelPHP , работа с формами не может быть проще. С помощью нескольких строк кода вы можете легко создавать и проверять форму. Сегодня мы узнаем, как это сделать!


Класс Fieldset используется для создания формы и обработки ее валидации объектно-ориентированным способом. Используются классы Form и Validation . Этот класс сам по себе предназначен только для моделирования набора полей и его полей, тогда как два других класса выполняют основную работу.


Нам нужна установка FuelPHP с включенным пакетом RM. Я собираюсь использовать базу данных MySQL с образцом таблицы. Хотя класс Fieldset можно настроить на использование нормальной модели, использование ORM сэкономит нам некоторое время.

Если вы еще не просмотрели первые несколько частей серии FuelPHP здесь, на Nettuts +, то сейчас самое время проверить первую и вторую части Фила Стерджена.

Установите соединение с базой данных в fuel/app/config/development/db.php .

1
2
3
4
5
6
7
8
9
return array(
  ‘default’ => array(
     ‘connection’ => array(
         ‘dsn’ => ‘mysql:host=localhost;dbname=blog’,
         ‘username’ => ‘root’,
         ‘password’ => ‘root’,
     ),
  ),
);

Включить пакет ORM через fuel/app/config.php

1
2
3
‘packages’ => array(
    ‘orm’,
),

И, наконец, вот SQL для таблицы, которую я использую для этого урока.

1
2
3
4
5
6
7
8
9
CREATE TABLE `blog`.`posts` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`post_title` VARCHAR( 100 ) NOT NULL ,
`post_content` TEXT NOT NULL ,
`author_name` VARCHAR( 65 ) NOT NULL ,
`author_email` VARCHAR( 80 ) NOT NULL ,
`author_website` VARCHAR( 60 ) NULL,
`post_status` TINYINT NULL
) ENGINE = INNODB;

Нам нужна модель для взаимодействия нашего контроллера с таблицей сообщений. Продолжайте и создайте post.php внутри app/classes/model/ . Создайте класс Model_Post и убедитесь, что он расширяет \Orm\Model . ORM будет автоматически использовать таблицу posts в нашей базе данных, поскольку мы использовали единственное число «сообщений». Если вы хотите установить другую таблицу, установите статическое свойство с именем $_table_name .

1
2
3
4
class Model_Post extends \Orm\Model
{
    protected static $_table_name = ‘posts’;
}

Мы должны указать столбцы нашей таблицы сообщений в нашей модели. В то же время мы также можем настроить метки, правила проверки формы для использования с нашим классом fieldset для генерации формы. Все они идут в связанном массиве, который называется $_properies . Когда все готово, наша окончательная модель должна выглядеть так:

01
02
03
04
05
06
07
08
09
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
class Model_Post extends \Orm\Model
{
    protected static $_table_name = ‘posts’;
 
    protected static $_properties = array(
        ‘id’,
        ‘post_title’ => array( //column name
            ‘data_type’ => ‘string’,
            ‘label’ => ‘Post Title’, //label for the input field
            ‘validation’ => array(‘required’, ‘max_length’=>array(100), ‘min_length’=>array(10)) //validation rules
        ),
        ‘post_content’ => array(
            ‘data_type’ => ‘string’,
            ‘label’ => ‘Post Content’,
            ‘validation’ => array(‘required’)
        ),
        ‘author_name’ => array(
            ‘data_type’ => ‘string’,
            ‘label’ => ‘Author Name’,
            ‘validation’ => array(‘required’, ‘max_length’=>array(65), ‘min_length’=>array(2))
        ),
        ‘author_email’ => array(
            ‘data_type’ => ‘string’,
            ‘label’ => ‘Author Email’,
            ‘validation’ => array(‘required’, ‘valid_email’)
        ),
        ‘author_website’ => array(
            ‘data_type’ => ‘string’,
            ‘label’ => ‘Author Website’,
            ‘validation’ => array(‘required’, ‘valid_url’, ‘max_length’=>array(60))
        ),
        ‘post_status’ => array(
            ‘data_type’ => ‘string’,
            ‘label’ => ‘Post Status’,
            ‘validation’ => array(‘required’),
            ‘form’ => array(‘type’ => ‘select’, ‘options’ => array(1=>’Published’, 2=>’Draft’)),
        )
 
 
    );
}

Давайте рассмотрим, какие варианты мы можем использовать. data_type просто содержит тип полей. Это может быть либо строка, целое число, либо mysql_date. Значение свойства label будет отображаться как метка поля после создания формы. validation принимает массив правил валидации. По умолчанию эти поля будут полями ввода текста. Используя form , вы можете сделать выбор или texarea.

ORM обрабатывает столбец с именем id как основной и не будет отображаться при создании формы. Если столбец первичного ключа вашей таблицы отличается, используйте свойство $_primary_key чтобы указать его.

1
2
3
4
5
6
7
8
9
/**
 * Post Model
 */
class Model_Post extends \Orm\Model
{
    protected static $_table_name = ‘posts’;
 
    protected static $_primary_key = array(‘id’);
}

Теперь, когда модель готова, давайте создадим контроллер. Контроллеры должны быть помещены в fuel/app/classes/controller/ . Я создал контроллер с именем Controller_Posts (posts.php) и расширил его из Controller_Template .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * Post Controller fuel/app/classes/controller/posts.php
 */
class Controller_Posts extends \Controller_Template
{
    //list posts
    function action_index()
    {
 
    }
 
    //add new one
    function action_add()
    {
 
    }
 
    //edit
    function action_edit($id)
    {
 
    }
}

Пользователи смогут просматривать список сообщений, добавлять новые или редактировать существующие. Поскольку я использую контроллер шаблона, я могу использовать базовый файл шаблона для работы. Шаблоны идут в fuel/app/views/template.php

01
02
03
04
05
06
07
08
09
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
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv=»Content-type» content=»text/html; charset=utf-8″ />
    <?php echo Asset::css(‘bootstrap.css’);
</head>
 
<body>
 
    <div id=»content»>
 
        <p>
            <?php
                echo \Html::anchor(‘posts/index’, ‘Listing’), ‘&nbsp;’, \Html::anchor(‘posts/add’, ‘Add’);
            ?>
        </p>
 
        <?php if(isset($messages) and count($messages)>0): ?>
        <div class=»message»>
            <ul>
            <?php
                foreach($messages as $message)
                {
                    echo ‘<li>’, $message,'</li>’;
                }
            ?>
            </ul>
        </div>
        <?php endif;
 
        <?php echo $content;
    </div>
 
</body>
</html>

Это просто стандартная разметка HTML с помощью начальной загрузки Twitter. Переменная $content будет содержать содержимое. Мы можем установить массив сообщений, и если мы это сделаем, он будет напечатан как неупорядоченный список.


Здесь начинается самое интересное. Мы собираемся создать форму для добавления новых сообщений. Как вы уже догадались, мы будем работать с action_add() . Давайте сгенерируем форму и передадим ее нашему шаблону.

1
2
3
4
5
6
7
8
//add new one
function action_add()
{
    $fieldset = Fieldset::forge()->add_model(‘Model_Post’);
    $form = $fieldset->form();
 
    $this->template->set(‘content’, $form->build(), false);
}

Fieldset::forge() вернет новый экземпляр класса fieldset. Это то же самое, что делать new Fieldset . Однако, используя метод forge , мы можем назвать наши экземпляры. Если мы дважды вызываем экземпляр с одним и тем же именем, будет возвращен существующий экземпляр, если он доступен [шаблон Factory]. Чтобы назвать свой экземпляр, передайте имя методу forge . Fieldset::forge('new_post')

Используя метод add_model , мы передаем модель, из которой мы хотим генерировать формы. Fieldset будет извлекать данные из $_properties для генерации формы. Вызов метода form() из объекта fieldset вернет экземпляр из класса Form , и, вызвав метод build() , мы можем получить html (string) вывод формы.

1
$this->template->set(‘content’, $form, false);

Наконец, мы передаем шаблон $form в качестве содержимого. Другой метод передачи переменных в шаблон — это $this->template->content = $form .

http://path_to_site/index.php/posts/add браузер и перейдите по http://path_to_site/index.php/posts/add . Вы должны увидеть форму, идентичную этой.

Нет кнопки отправки? Давайте это исправим. Нам нужно добавить новое поле в наш объект формы.

1
$form->add(‘submit’, », array(‘type’ => ‘submit’, ‘value’ => ‘Add’, ‘class’ => ‘btn medium primary’));

Используя метод add мы можем добавить дополнительные поля в нашу форму. Первый параметр — это имя нашего нового поля, второй — для метки, для третьего параметра мы передаем массив атрибутов.

После добавления этого наша action_add() будет выглядеть следующим образом.

1
2
3
4
5
6
7
8
function action_add()
{
    $fieldset = Fieldset::forge()->add_model(‘Model_Post’);
    $form = $fieldset->form();
    $form->add(‘submit’, », array(‘type’ => ‘submit’, ‘value’ => ‘Add’, ‘class’ => ‘btn medium primary’));
 
    $this->template->set(‘content’, $form->build(), false);
}

И наша форма ..


Теперь, когда у нас есть хорошая форма, давайте проверим ее и сохраним в базе данных. Объект fieldset включает в себя экземпляр класса валидации FuelPHP. Все правила были применены и готовы к работе.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function action_add()
{
    $fieldset = Fieldset::forge()->add_model(‘Model_Post’);
    $form = $fieldset->form();
    $form->add(‘submit’, », array(‘type’ => ‘submit’, ‘value’ => ‘Add’, ‘class’ => ‘btn medium primary’));
 
    if($fieldset->validation()->run() == true)
    {
        $fields = $fieldset->validated();
 
        $post = new Model_Post;
        $post->post_title = $fields[‘post_title’];
        $post->post_content = $fields[‘post_content’];
        $post->author_name = $fields[‘author_name’];
        $post->author_email = $fields[‘author_email’];
        $post->author_website = $fields[‘author_website’];
        $post->post_status = $fields[‘post_status’];
 
        if($post->save())
        {
            \Response::redirect(‘posts/edit/’.$post->id);
        }
    }
    else
    {
        $this->template->messages = $fieldset->validation()->errors();
    }
 
    $this->template->set(‘content’, $form->build(), false);
}

$fieldset->validation() возвращает экземпляр класса валидации и, обращаясь к его методу run() мы можем проверить, прошла ли валидация. Если это так, мы добавляем новый пост в нашу базу данных. $fieldset->validated() вернет массив проверенных полей. Если проверка пройдена и сообщение сохранено, пользователь будет перенаправлен на страницу редактирования, в противном случае передайте ошибки проверки нашему шаблону в качестве переменной сообщения.

Если вы попытаетесь отправить некоторые недопустимые данные, вы получите такой вывод:

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

1
$fieldset = Fieldset::forge()->add_model(‘Model_Post’)->repopulate();

Круто, да? Добавьте некоторые допустимые данные, и он будет перенаправлен в метод action_edit() , который еще не готов.


Редактирование раздела почти такое же, как в разделе добавления постов. За исключением того, что нам нужно заполнить данные существующим постом. Я собираюсь продублировать код action_add .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function action_edit($id)
{
    $post = \Model_Post::find($id);
 
    $fieldset = Fieldset::forge()->add_model(‘Model_Post’)->populate($post);
    $form = $fieldset->form();
    $form->add(‘submit’, », array(‘type’ => ‘submit’, ‘value’ => ‘Save’, ‘class’ => ‘btn medium primary’));
 
    if($fieldset->validation()->run() == true)
    {
        $fields = $fieldset->validated();
 
        //$post = new Model_Post;
        $post->post_title = $fields[‘post_title’];
        $post->post_content = $fields[‘post_content’];
        $post->author_name = $fields[‘author_name’];
        $post->author_email = $fields[‘author_email’];
        $post->author_website = $fields[‘author_website’];
        $post->post_status = $fields[‘post_status’];
 
        if($post->save())
        {
            \Response::redirect(‘posts/edit/’.$id);
        }
    }
    else
    {
        $this->template->messages = $fieldset->validation()->errors();
    }
 
    $this->template->set(‘content’, $form->build(), false);
}

С некоторыми небольшими изменениями в нашем action_add() у нас есть метод edit. метод repopulate() был заменен методом populate() . Используя метод populate , мы можем заполнить форму существующими данными поста.

В этом случае мы извлекаем сообщение из нашей базы данных с помощью параметра $id , а затем передаем его нужному методу. Нам не нужно $post = new Model_Post; больше, потому что мы ничего не добавляем в базу данных. Объект $post мы создаем в начале, используется для назначения новых значений. После редактирования он будет перенаправлен обратно на экран редактирования. Были сделаны! Добавьте несколько постов и попробуйте их отредактировать.


Давайте создадим раздел листинга, чтобы пользователи могли видеть все сообщения в одном месте.

Листинг обрабатывается методом action_index()

01
02
03
04
05
06
07
08
09
10
//list posts
function action_index()
{
    $posts = \Model_Post::find(‘all’);
 
    $view = \View::forge(‘listing’);
    $view->set(‘posts’, $posts, false);
 
    $this->template->content = $view;
}

Model_Post::find('all') вернет массив объектов записей для всех наших сообщений. Используя View::forge() , создается новый объект вида. Параметр для View::forge() — это имя для нашего конкретного представления. Он находится в app/views/listing.php . Массив объекта posts ( $posts ) затем передается нашему представлению. Представление Listing позаботится о листинге, и, наконец, мы назначим представление $this->template->content .

По нашему мнению, мы перебираем $posts и генерируем список.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
/**
 * Listing view, views/listing.php
 */
if($posts):
    foreach($posts as $post):
?>
 
<div class=»post»>
    <h2><?php echo $post->post_title;
    <p><?php echo $post->post_content;
    <p>
        <small>By <?php echo $post->author_name;
        <small><?php echo $post->author_email;
        <small><?php echo $post->author_website;
    </p>
</div>
 
<?php
    endforeach;
endif;
?>

Если у вас есть какие-либо сообщения в базе данных, это будет выглядеть примерно так.


Кажется, все работает правильно; Тем не менее, есть некоторые незначительные проблемы. Сгенерированная форма имеет текстовое поле для содержимого публикации, которое лучше использовать как текстовую область.

1
2
3
4
5
6
7
//Model_Post
‘post_content’ => array(
    ‘data_type’ => ‘string’,
    ‘label’ => ‘Post Content’,
    ‘validation’ => array(‘required’),
    ‘form’ => array(‘type’ => ‘textarea’) //will give us a textarea
),

Вы можете передать все типы полей: текст, текстовое поле, выбор, радио и т. Д. Для элементов выбора или радио вы можете установить параметры. Настройка параметров для выбора с использованием другой таблицы также возможна. Если вы хотите изменить макет по умолчанию, поместите файл конфигурации формы в fuel/app/config/form.php Если вы не уверены в том, что туда поместить, скопируйте fuel/core/config/form.php из fuel/core/config/form.php Fuel использует этот файл для генерации форм.


Я надеюсь, что теперь у вас есть четкое понимание класса fieldset . Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать в комментариях ниже. Большое спасибо за чтение!