cult3

Creating forms in Laravel 4

Aug 19, 2013

Table of contents:

  1. Creating forms for Cribbb
  2. Methods
  3. Routes and Methods
  4. Params
  5. Files
  6. CSRF
  7. Form Model binding
  8. Labels
  9. Text, Text Area, Password, Hidden and Form Fields
  10. Checkboxes and Radio Buttons
  11. Drop Down Lists
  12. Buttons
  13. Conclusion

One of the very basic requirements of all online applications is that the user should be able to enter data. Web forms are the most commonly used methods for entering data into an application and so they are a fundamental thing that you need to get right.

Laravel is a framework that aims to make developing and maintaining web applications as easy as possible. One of the ways this is achieved is by having an excellent Form class that makes creating and interacting with forms extremely easy.

A lot of other frameworks seem to make working with forms much harder then they need to be. In my experience they are either too rigid or not comprehensive enough! If you are coming at this from a non-framework perspective, using a form builder might seem a little bit strange, but hopefully by the end of this tutorial you will be able to see the benefits.

So let’s look at building Laravel forms!

Creating forms for Cribbb

If you remember back to when we were building out the Controller methods of the User resource, the create and edit methods are used to display a form so the user can create or edit a record in the system.

Both of these methods simply return a View to the browser. Open those two views up now so we can create the forms to allow new records to be created and existing records to be edited.

In order to create a form in your view, you can simply use the open and close tags of the Form class:

{{ Form::open(array('url' => 'users')) }}

{{ Form::close() }}

This will create the following HTML output:

<form method="POST" action="https://localhost:8000/users" accept-charset="UTF-8">
  <input
    name="_token"
    type="hidden"
    value="1gDaHZGie4TwE47wIT7T7uUU5hQOKu8hfFHG6Dwj"
  />
</form>

Notice how the Form tags are wrapped in Blade curly braces!

Methods

As you can see, the open method accepts an array of arguments. In this case I have specified an action URL, /users.

By default the form will automatically set the method to POST. As you might already know, HTML forms only accepts POST or GET methods. However, our Controller will also be listening out for PUT or DELETE methods. If you specify that this is a PUT or DELETE request, Laravel will add a hidden parameter to your form.

To set the method to PUT, simply add it to the array of arguments:

{{ Form::open(array('url' => 'users', 'method' => 'put')) }}

This will add the following hidden parameter to your form:

<input name="_method" type="hidden" value="PUT" />

Laravel will understand that you want to update this resource rather than attempt to create a new one and so the update method of the Controller will be used, instead of the store method.

Routes and Methods

If you have ever worked on a big website in the past, you will understand the pain of having to change URL routes. For whatever reason you need to change URLs and so you have to find every instance of that route in your code in order to make the transition.

Laravel 4 makes this problem go away by allowing you to use named routes or set the controller method directly in the form. This means if the URL changes, your code won’t know the difference!

To use a named route, just add a route key value pair to your arguments list:

{{ Form::open(array('route' => 'route.name')) }}

To specify a Controller method, simply add an action key value pair instead:

{{ Form::open(array('action' => 'Controller@method')) }}

Params

When you are updating a record, you need to pass the id of the record that you want to update. To do that, you simply need to set the action to an array and pass the param as the second value:

{{ Form::open(array('action' => array('Controller@method', $user->id))) }}

Files

If you want to use the form to upload files to the server, simply specify this as another argument:

{{ Form::open(array('action' => array('Controller@method', $user->id), 'files' => true)) }}

This will add the following to the form HTML output:

<form enctype="multipart/form-data"></form>

HTML forms provide two methods of encoding. The default is application/x-www-form-urlencoded, which is more or less the same as a query string on the end of the URL. The other, multipart/form-data, is a more complicated encoding but one that allows entire files to be included in the data.

CSRF

In the first example of the HTML output of the form, you might be thinking, what is the _token?

<input
  name="_token"
  type="hidden"
  value="1gDaHZGie4TwE47wIT7T7uUU5hQOKu8hfFHG6Dwj"
/>

Laravel 4 will automatically set this token in your session and include it in your forms. The token is to prevent CSRF (Cross-Site Request Forgery).

If you use the Form class you don’t have to even think about protecting against CSRF as Laravel will automatically include the token for you. However, if you don’t want to use the form builder, you can manually generate it using the token() method:

Form::token();

To prevent CSRF attacks, you can attach Laravel’s CSRF filter to your routes like this:

Route::post("users", [
    "before" => "csrf",
    function () {
        //
    },
]);

Form Model binding

For the majority of the time when you are working with forms, you will want to bind the input to a model. So for instance, if you are updating a user’s record, you will want the form to bind to the User model. By binding the form to the model, you can automatically populate it so when you generate the form the fields will automatically be set with the user’s data.

To bind a form to a model, use the model() method, like this:

{{ Form::model($user, array('route' => array('user.update', $user->id))) }}

{{ Form::close() }}

Now if you were to go to /users/1/edit the form will automatically be populated with the data of user 1 without you having to actually do anything!

If, for example, your user tries to update their details with data that does not pass your validation rules, the edit form will be regenerated but the incorrect data will appear in the updated fields rather than the model data. This means that your form will not only auto populate from the model, but it will also intuitively re-populate if their was a validation error, allowing the user to correct their mistakes.

Laravel’s order of preference flows like this:

  1. Session Flash Data (Old Input)
  2. Explicitly Passed Value
  3. Model Attribute Data

So the model attribute data will be set as default, but if the user has entered data that does not pass the validation, that data will take preference to enable the user to quickly correct their mistake.

Pretty cool huh?

Labels

No form would be complete without Labels and so Laravel makes it incredibly easy to generate them:

{{ Form::label('email', 'E-Mail Address') }}

If you want to specify a class for your label, simply add a third parameter:

{{ Form::label('email', 'E-Mail Address', array('class' => 'awesome')) }}

Text, Text Area, Password, Hidden and Form Fields

Generating Text fields, Text areas, Password, Hidden and Form fields are about as easy and intuitive as you would expect from Laravel:

Text field:

// Regular text field
{{ Form::text('username') }}

// Text field with a default value
{{ Form::text('email', 'Your email') }}

Text area:

// Regular text area
{{ Form::textarea('description') }}

// Text area with a default value
{{ Form::textarea('description', 'Description...') }}

Password field:

// Regular password field
{{ Form::password('password') }}

// Password field with a default value
{{ Form::text('password', 'Password') }}

Hidden field:

// Regular hidden field
{{ Form::hidden('secret_code') }}

// Hidden field with a default value
{{ Form::hidden('secret_code', 'shhhh') }}

File:

{{ Form::file('image') }}

Checkboxes and Radio Buttons

Checkboxes and Radio buttons also have a very simple syntax. Like the previous fields, the first argument allows to you set a name for the field, the second argument allows you to set a value, and for checkboxes and radio buttons the third optional argument allows you to specify whether this field should be automatically be set to checked:

{{ Form::checkbox('admin', 'yes', true) }}

{{ Form::radio('gender', 'female', true) }}

With drop down lists, you simply need to pass a name for the element, an array of options and an optional default value.

Simple drop down list:

{{ Form::select('Network', array(
    'facebook' => 'Facebook',
    'twitter' => 'Twitter',
    'cribbb' => 'Cribbb'
)) }}

With a selected default:

{{ Form::select('Network', array(
    'facebook' => 'Facebook',
    'twitter' => 'Twitter',
    'cribbb' => 'Cribbb'), 'cribbb') }}

You can also pass a multidimensional array to create a grouped drop down list:

{{ Form::select('cribbbs', array(
    'laraval' => array("design", "development"),
    'startups' => array("advice", "strategy"),
    'business' => array("marketing", "sales")
)) }}

Buttons

And finally creating submit button or a button element is as easy as this:

// Submit button
{{ Form::submit('Register') }}

// Button element
{{ Form::button('Find out more') }}

Conclusion

And there you have it, everything a sane person would ever want to know about creating forms in Laravel 4. Forms are pretty much essential to all web applications, and so Laravel makes it incredibly easy to generate them with a clean and simple syntax.

I also really like how Laravel can generate CSRF tokens and allow you to use PUT and DELETE methods without you having to do anything complicated. Imagine if you had to try and build that functionality yourself?!

This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.