Amitav Roy

Blog on web and travel

Laravel 4 forms, retain data, default and custom validations

Posted on July 2019

Laravel

Working with forms in Laravel 4 is really fun and there is hardly any PHP application which doesn’t have a form. So, in this tutorial, I will demonstrate how to create a simple registration form using the Laravel’s form library. Then we will validate the data when the form is submitted. We will use the validation library which comes with Laravel 4 out of the box and also our custom validation rule.

The starting point

For this tutorial, I will create a simple registration form. It will have an email address, first name, last name and the password field. Then we will post the data and first run the Laravel 4’s Validator to check the post data. If the data is wrong then the form will re-populate with the old data and also with error messages that we want to show the end user. And if the validation is successful, then we will save the data. But I will only show a success message and not save anything.

To do this, we need to do the following things:

  • Create the view with the form
  • Controller with two functions – the form page and the post page
  • Create our own Validation class
  • Register the validation class and its function

The view

@layout('html')
  
@section('pageHeadSection')
@parent
<title>Welcome to Learning Laravel 4 - Registration page</title>
@stop
  
@section('content')
<div class="row">
  <div class="col-md-12">
    <h1>Registration form</h1>
  </div>
</div>
<div class="row">
  <div class="col-md-12">
    {{ Form::open(array('url' => 'registration/save')) }}
    <div class="form-group">
      {{ Form::label('email', 'E-Mail Address') }}
      {{ Form::email('email', Input::old('email'), array('class' => 'form-control', 'placeholder' => 'Enter your email address')) }}
      <span class="error-display">{{$errors->first('email')}}</span>
    </div>
    <div class="form-group">
      {{ Form::label('firstname', 'First name') }}
      {{ Form::text('firstname', Input::old('firstname'), array('class' => 'form-control', 'placeholder' => 'Enter your First name')) }}
      <span class="error-display">{{$errors->first('firstname')}}</span>
    </div>
    <div class="form-group">
      {{ Form::label('lastname', 'Last name') }}
      {{ Form::text('lastname', Input::old('lastname'), array('class' => 'form-control', 'placeholder' => 'Enter your Last name')) }}
      <span class="error-display">{{$errors->first('lastname')}}</span>
    </div>
    <div class="form-group">
      {{ Form::label('password', 'Password') }}
      {{ Form::password('password', array('class' => 'form-control', 'placeholder' => 'Enter your password, min 6 characters')) }}
      <span class="error-display">{{$errors->first('password')}}</span>
    </div>
    <div class="form-group">
      {{ Form::label('cpassword', 'Confirm Password') }}
      {{ Form::password('cpassword', array('class' => 'form-control', 'placeholder' => 'Confirm your password')) }}
      <span class="error-display">{{$errors->first('cpassword')}}</span>
    </div>
  
    <input type="submit" name="save" value="Save" class="btn btn-success">
    {{ Form::token() }}
    {{ Form::close() }}
  </div>
</div>
@stop

The Controller

The controller has two functions. You can check the routes.php file to know the URLs and also the reference to the controller and their respective function. The first one is just returning the view file which has the form, nothing more than that.

The second function is the function which is handling the post data, the validation and then doing the save. As it’s just a tutorial, I will not write the save part but I am sure that’s not a big deal.

public function registerFormPage()
{
  $this->layout->content = View::make('form.register');
}
  
public function saveRegistration()
{
  // getting all of the post data
  $postData = Input::all();
  
  // setting up custom error messages for the field validation
  $messages = array(
    'email.required' => 'We need to know your email address',
    'firstname.required' => 'Please enter your full first name',
    'lastname.required' => 'Please enter your full last name',
    'password.required' => 'You have to set a password',
    'cpassword.required' => 'Write is again so that you are sure about your password',
    'cpassword.matchpass' => 'The two passwords does not match', // this is for the custom validatio that we have written
  );
  
  $rules = array(
    'email' => 'required|email',
    'firstname' => 'required|min:3',
    'lastname' => 'required',
    'password' => 'required',
    'cpassword' => 'required|Matchpass:' . $postData["password"],
  );
  
  // doing the validation, passing post data, rules and the messages
  $validator = Validator::make($postData, $rules, $messages);
  
  
  if ($validator->fails())
  {
    // send back to the page with the input data and errors
    GlobalHelper::setMessage('Fix the errors.', 'warning'); // settig the error message
    return Redirect::to('register')->withInput()->withErrors($validator);
  }
  else
  {
    // send back to the page with success message
    GlobalHelper::setMessage('Registration data saved.', 'success');
    return Redirect::to('register');
  }
}

After getting all post variable inside $postData, I have created an array $messages which contains the entire custom message for each field’s validation. The format is simple; the key should have the field name then a dot and then the validation. And if you have two validation rule running on one field like the cpassword (confirm password) field, then you need to should add two entries. You can check line number 17,18 in the code above.

Then I created another array with the rules. Each key here represents the field and the value is the validation rules. If there are multiple, then you can separate them using “|”.

Then we send the post data, rule and the message array to the Validator’s make function and if the validation fails then we redirect the user to the form again with the old inputs and the error messages. Also I am using a custom helper function GlobalHelper::setMessage where I am using the session to set messages to user and display them. When the validation fails, I am sending a warning message. And when the validation is passed, I send a save and success message to the user.

The Custom validation rule

If you check the rules array inside the controller (line number 26) you will see that I have used a custom validation rule “Matchpass”. Basically, this is checking if the password field and the confirm password field are the same. I am sending the password data to the validation function as an attribute. I have created a class for validation inside helpers function. Now for Laravel 4 to know that the class is inside the helper folder, we need to make a few changes. First, we add an entry in the composer.json file. You can check mine at line number 19. I have added “app/helpers” folder there. This helpers Laravel know that the folder contains class files.

Then I wrote the custom validation class, here is the code:

class CustomValidation extends Illuminate\Validation\Validator {
  
  public function validateMatchpass($attribute, $value, $parameters)
  {
    $cPassword = $parameters[0];
    if ($cPassword == $value)
      return $value == $cPassword;
  }
}

Inside this, I am getting the confirm password as $value and the password field data is coming as a parameter. I check here if the two are same and return if true. Once this is done, we tell Laravel about the new rule by adding this piece of code in global.php.

Validator::resolver(function($translator, $data, $rules, $message){
  return new CustomValidation($translator, $data, $rules, $message);
});

This is how my form looks with the error messages:

Laravel app