Mass-produce input forms quickly, elegantly, and wildly using fuelphp's fieldset
table of contents
Hello.
I'm Mandai, in charge of Wild on the development team.
At our company, we often use
fuelphp Nowadays, I am very satisfied with the significant reduction in man-hours. This time, I would like to convey the essence of fieldset.
The version of FuelPHP has been confirmed to be 1.7.2.
What is fieldset?
I think that fieldset is the product of fuelphp's high-speed development, but surprisingly there seem to be few Japanese articles that explore it in depth.
There are a lot of articles that say I tried using it for a while.
fieldset is a mechanism that creates a form with a single method based on the information defined in the model, and
if you are using a web application that uses standard Twitter bootstrap, you can
easily output the form part without writing HTML. It's possible.
Once you have carefully drawn the model, you can rely on the momentum of fieldset and create it all at once, so
if you have a lot of input screens and the last train will be fixed for a while, please consider this and enjoy time with your family. I would appreciate it if you could figure it out.
So let's write a model as well.
When using fieldset, all the information necessary for form generation is pushed into $_properties.
Not only the input type but also the validation can be written here to centrally manage form information.
As an example, let's create a Model_Book class using a model that assumes a book registration screen.
The books table has been prepared as follows.
CREATE TABLE `books` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(512) NOT NULL, `author` varchar(256) NOT NULL, `price` int(10) unsigned NOT NULL, ` isbn` varchar(13) DEFAULT '', `released_at` date DEFAULT '0000-00-00', `type` tinyint(2) DEFAULT NULL, `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00: 00', `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Define the model for this books table as follows.
<?php // fuel/app/classes/model/book.php class Model_Book extends \Model\Orm { protected static $_connection = 'default'; protected static $_table_name = 'books'; protected static $_properties = [ 'id', 'title' => [ 'data_type' => 'varchar', 'label' => 'title', 'validation' => [ 'required', 'max_length' => [512], ], 'form' => [ 'type' = > 'text', 'class' => 'form-control', ], ], 'author' => [ 'data_type' => 'varchar', 'label' => 'author', 'validation' => [ 'required', 'max_length' => [512], ], 'form' => [ 'type' => 'text', 'class' => 'form-control', ], ], 'price' => [ 'data_type' => 'int', 'label' => 'price', 'validation' => [ 'required', 'numeric_min' => [0], ], 'form' => [ 'type' = > 'number', 'class' => 'form-control', 'min' => 0, ], ], 'isbn' => [ 'data_type' => 'varchar', 'label' => 'ISBN' , 'validation' => [ 'match_pattern' => ['/^[0-9]{10}([0-9]{3})?$/'], ], 'form' => [ 'type ' => 'text', 'class' => 'form-control', ], ], 'released_at' => [ 'data_type' => 'date', 'label' => 'issue date', 'validation' => [ 'valid_date' => [], ], 'form' => [ 'type' => 'text', 'class' => 'form-control datepicker', ], ], 'type' => [ 'date_type' => 'tinyint', 'label' => 'format', 'validation' => [ 'numeric_min' => [0], ], 'form' => [ 'type' => 'select' , 'class' => 'form-control', 'options' => [ 0 => 'unknown', 1 => 'A4 size', 2 => 'A5 size', 3 => 'A6 size', 4 => 'B4 size', 5 => 'B5 size', 6 => 'B6 size', 7 => 'Small B6 size', 8 => 'Kikube size', 9 => 'International size', 10 => 'AB size', 11 => 'Jubako version', 12 => 'Kikuban', 13 => 'Shiroku size', 14 => 'B40 size', 15 => 'Pocket book version', 16 => '35-size', 17 => '8-fold', 18 => 'HL-size', ], ], ], 'created_at' => [ 'form' => ['type' => false] , ], 'updated_at' => [ 'form' => ['type' => false], ], ]; protected static $_observers = [ 'Orm\Observer_CreatedAt' => [ 'events' => ['before_insert' ], 'mysql_timestamp' => true, ], 'Orm\Observer_UpdatedAt' => [ 'events' => ['before_update'], 'mysql_timestamp' => true, ], ]; }
I have now filled out most of the information I need.
Because the information is very compact and can be written in a structured arrangement, there are fewer mistakes and
it is easy to make corrections later.
The standard validation rules are listed in the Validation - Class - FuelPHP document
Information regarding form creation is provided under the "form" key for each field.
"Type" corresponds to the type attribute of the input tag, and textarea tags can be treated in the same way, including the commonly used text, select, hidden, checkbox, radio, etc.
In the case of type="select", type="checkbox", type="radio", you can define a fixed value by writing the option element as an array under "options".
Also, if it is not a fixed value, data can be set in options from the controller side as shown below.
$form = \Fieldset::forge('default', [ 'form_attributes' => ['class' => 'form-horizontal'] ])->add_model('Model_Book'); $newspaper_types = [ 19 => ' 'Broadsheet', 20 => 'Nordic', 21 => 'Rhenish', 22 => 'Swiss (NZZ)', 23 => 'Berliner', 24 => 'Tabloid Extra' ', 25 => 'Half Swiss', 26 => 'Half Berliner', 27 => 'Half Rhenish', 28 => 'Half Broadsheet', 29 => 'Tabloid', ]; // To add an item $form->field('type')->set_options($newspaper_types); // To replace an item $form->field('type')->set_options($newspaper_types , null, true);
If you set true to the third argument of the set_options method, the array will be overwritten without being merged.
For now, you can easily input only unselected values on the model side, and add values if there are other possible values.
You can directly manipulate form elements with $form->field('type'), so as long as you remember this shape,
you can control it with a controller if you want to change the expression slightly at certain times.
Methods that connect to $form->field('type') and perform various operations are located in fuel/core/classes/fieldset/field.php.
If you look at the methods as well, I think you can find the method that suits your purpose.
Create a form with one method
Once you have defined the model, all you have to do is make some fine adjustments in the controller and generate the HTML.
What I mean by fine-tuning is that if you do nothing, you will end up with a form that does not have a submit button.
Since it's a form, a submit button is required, right? You might think that, but
I think it's unique to fuelphp, which has a different philosophy than cakephp, without taking care of unnecessary things.
$form->add('submit', ' ', ['type'=>'submit', 'class'=>'btn btn-primary submit', 'value' => 'registration']);
However, since this is all there is to it, you can almost do it by copying and pasting.
Finally, we pass the HTML of the form part to the View, but
in the case of a controller that inherits Controller_Template, all you have to do is forge the View and pour in the output of the build method that assembles the form using the steps below.
$this->template->content = View::forge('manager/master/form.php', $this->contents); $this->template->content->set_safe('form', $form- >build());
fuelphp automatically escapes strings passed to views.
However, the set_safe method is used to pass the information in the second argument to the View without escaping it.
For security reasons, it may be better not to use it too much, but I'm doing it this way because there doesn't seem to be any other effective method at the moment.
I want to create a form where bootstrap is applied neatly.
At the beginning, I wrote that you can create a better form if you close your eyes a little,
but it's human nature to still care about the appearance. Right!
In the default state, a form with labels and input elements arranged in a table will be displayed, but
you can control this behavior by manipulating the template.
The default template is fuel/core/config/form.php, so copy this file to app/config/ and modify it.
here is an example of a template config file that has been modified to apply twitter bootstrap's Horizontal form
<?php // fuel/app/config/form.php return [ 'form_template' =>"\n\t\t{open}\n{fields}\n\t\t{close}\n", 'field_template' => "\t\t<div class=\"form-group\"> \n\t\t\t{label}\n\t\t\t<div class=\"col-xs-3 {error_class}\"> {field} <span>{description}</span> {error_msg}</div> \n\t\t</div> \n", 'multi_field_template' => "\t\t<div class=\"form-group\"> \n\t\t\t <label class=\"col-xs-2 control-label\">{group_label}{required}</label> \n\t\t\t<div class=\"col-xs-3 {error_class}\"> {fields}\n\t\t\t\t<div> {field} {label}</div> {fields} <span>{description}</span> \t\t\t{error_msg}\n\t\t\t</div> \n\t\t</div> \n", 'label_class' => 'col-xs-2 control-label', 'group_label' => '{label}', ];
The format is difficult to grasp because it contains characters such as \t and \n, but it has nothing to do with screen display, so there is no problem if you omit it. It just makes the HTML source a little harder to read.
Also, there are some items that are listed in the default core/config/form.php but not in app/config/form.php, but this is not a problem because they will be merged and the default settings will be used.
You can also use AdminLTE , which is derived from twitter bootstrap,
How much man-hour can actually be reduced?
First of all, it is clear that the DB design must be completed (to some extent) as a prerequisite, even from the point of view of concentrating information in the model.
When creating screens using fieldset, it is impossible to proceed with the implementation in parallel with the DB design, so you should focus on finalizing the DB design first.
Also, if you proceed while researching the fieldset mechanism and best practices, it will cost you money in the beginning, but as you think more deeply, the speed in the second half, as you get used to it, will dramatically increase to a level that can be called sensual. I think it ended quickly.
In fact, I've left a lot of the man-hours I had planned and am using the extra time to write this blog.
If you have never experienced it, why not try it out and experience its convenience?
That's it.