Laravel Lesson: Controllers, Requests & Validations

Published May 5, 2020 • 6 mins read

This lesson is the heart of this series. As a Laravel developer, these three components are going to be a routine for you as you build PHP applications with the Laravel framework.

I am not going into the full details of these components because this is a beginners series. Like I said earlier, I will keep it simple and actionable.

Controllers

A Laravel controller is basically where we handle HTTP requests. Instead of messing up our route file, we can keep everything clean and organized inside the controller class.

Laravel controllers are located inside the app/http/controllers directory. Going back to Laravel artisan commands, lets look at the make:controller command. This command is used to scaffold a controller class.

php artisan make:controller EmailController

This command will create an EmailController class inside the default Laravel controller directory. By default this controller extends our base controller class that gives us access to request This controller will take care of returning our application views and execute of our email sending logics.

Updates: Routes

Now lets update our route file to point to our new controller class.

Route::view('/', 'welcome');
Route::get('/email/add', 'EmailController@showAddEmailForm');
Route::post('/email/add', 'EmailController@saveEmail');
Route::get('/email/send', 'EmailController@showSendEmailForm');
Route::post('/email/send', 'EmailController@sendEmail');

We added two additional routes which are HTTP POST requests. These new routes will handle add new email and sending out mails.

Updates: EmailController

Now we have to update our EmailController class with these new methods we are pointing to.

...
public function showAddEmailForm()
{
    return view('add-email');
}
    
public function saveEmail()
{
}

public function showSendEmailForm()
{
    return view('send-email');
}          

public function sendEmail()
{
}

Requests

The message that is sent by a client to a server is what is known as an HTTP request.

There are two ways to get an instance of HTTP request coming into a Laravel controller.

Dependency Injection: This is done by type-hinting Illuminate\Http\Request class to our controller method and Laravel service container will inject the incoming request automatically. Something like this: store(Request $request)

...
use Illuminate\Http\Request;
public function store(Request $request) { 
  $email = $request->input('email'); 
}

Now we can access the request data(POST, GET, PUT etc) sent to a controller method.

Request Helper: This is another way to access request data without type-hinting anything on the controller method. The request() helper function returns the current request instance.This is the same as the first method but with a little bit of magic :)

...
public function store() { 
  $email = request('email');
}

Validations

Laravel provides lots of ways request data can be validated. The simplest way is by using the validate method provided by the request object. The validation method accepts an array of validation rules. Here is an example on how to validate an email field.

public function store() { 
  request()->validate([ 
      'email' => 'required|email:filter',
  ]);
}

The example above will make sure an email it field is present and then apply filter validator, which uses PHP's filter_var function under the hood. If any of the validation fails, it will return $error variable, an instance MessageBag class and perform automatic redirection.

You can find available validation rules on the laravel docs.

Validation Errors

Displaying the validation error requires @error blade directive. This blade directive will check if a validation error message exits. Here is an example on how to display the email error message in a blade view.

@error('email') 
<p class="text-red-500">{{ $errors->first('email') }}</p> 
@enderror

I believe you noticed that the email error was wrapped inside double curly brackets. The brackets is used to display data passed to the blade view. This is an equivalent of <?phpecho $errors->first('email'); ?>, but with more security. By default, Blade {{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks.

Updates: EmailController

Now that we have a basic understanding of Laravel HTTP requests and validations, lets update our controller methods.

    ...
    public function showAddEmailForm()
    {
        return view('add-email');
    }

    public function saveEmail()
    {
        $data = request()->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email:rfc|max:255',
        ]);
    }

    public function showSendEmailForm()
    {
        return view('send-email');
    }

    public function sendEmail()
    {
        $data = request()->validate([
            'subject' => 'required|string|max:255',
            'message' => 'required',
        ]);
    }

Updates: Views

Apart from the new error directives for validation error messages, we need to add @csrf directive to our forms. This will include a hidden CSRF token field in our form. This is basically security check.

We also used old helper function to set the old input values if the validation fails.

<!-- add-email.blade.php -->
<form class="px-8 pt-6 pb-8 mb-4" action="{{url('email/add')}}" method="POST">
    @csrf
    <div class="mb-4">
        <label class="block mb-2 text-sm font-bold text-gray-700">
            Name
        </label>
        <input name="name" value="{{old('name')}}"
            class="w-full px-3 py-3 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
            type="text" placeholder="Enter your name" />
        @error('name')
        <p class="text-red-500 text-xs italic pt-1">{{ $errors->first('name') }}</p>
        @enderror
    </div>
    <div class="mb-8">
        <label class="block mb-2 text-sm font-bold text-gray-700">
            Email
        </label>
        <input name="email" value="{{old('email')}}"
            class="w-full px-3 py-3 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
            type="email" placeholder="Enter your email" />
        @error('email')
        <p class="text-red-500 text-xs italic pt-1">{{ $errors->first('email') }}</p>
        @enderror
    </div>
    <div class="mb-6 text-center">
        <button
            class="w-full px-4 py-2 font-bold text-white bg-teal-400 rounded-full hover:bg-teal-500 focus:outline-none focus:shadow-outline"
            type="submit">
            Submit
        </button>
    </div>
</form>

send-email.blade.php

<!-- send-email.blade.php -->
<form class="px-8 pt-6 pb-8 mb-4" action="{{url('email/send')}}" method="POST">
    @csrf
    <div class="mb-4">
        <label class="block mb-2 text-sm font-bold text-gray-700">
            Subject
        </label>
        <input name="subject" value="{{old('subject')}}"
            class="w-full px-3 py-3 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
            type="text" placeholder="Enter email subject" />
        @error('subject')
        <p class="text-red-500 text-xs italic pt-1">{{ $errors->first('subject') }}</p>
        @enderror
    </div>
    <div class="mb-4">
        <label class="block mb-2 text-sm font-bold text-gray-700">
            Message
        </label>
        <textarea name="message" value="{{old('message')}}"
            class="w-full px-3 py-2 text-sm leading-tight text-gray-700 border rounded shadow appearance-none focus:outline-none focus:shadow-outline"
            rows="12" placeholder="Message goes here..."></textarea>
        @error('message')
        <p class="text-red-500 text-xs italic pt-1">{{ $errors->first('message') }}</p>
        @enderror
    </div>
    <div class="mb-6 text-center">
        <button
            class="w-full px-4 py-2 font-bold text-white bg-teal-400 rounded-full hover:bg-teal-500 focus:outline-none focus:shadow-outline"
            type="submit">
            Send
        </button>
    </div>
</form>

There is a lot more to controllers, request and validations but as a beginner I am going to keep it simple.

Our next lesson will be about Migrations And Eloquent Models.

Questions

Drop your question on the comment box, send me a DM on twitter or send an e-mail.

Subscribe here to receive email updates of this series directly to your inbox.


Hey, have you tried Litehost lately?

Litehost is my side project which is a shared hosting platform with PHP & Laravel developers in mind. It has Composer, Git & PHP CLI pre-installed on its servers. SSH access is also granted on request. Litehost is pretty affordable. Try it today.