Forms — Laravel 10 Discovery Training

In this chapter we will attack the form part of Laravel and we will see how to ensure that we can submit information to create or modify an article. Laravel does not necessarily provide tools to generate the HTML code of the forms (if we compare it to what Symfony offers) but provides various things that will simplify the task for us for the generation of the views.

Useful methods

@csrf

By default Laravel offers CSRF protection which protects against attacks of the # Cross-site request forgery type which consists of posting a form from an external site.

Also, if you create a classic form you will get an error when submitting it and you will have to create a hidden field containing a CSRF key for your form to work. The directive @csrf allows you to do this automatically.

@error

In the event of an error, the user is automatically redirected to the previous page with the validation errors saved in session. To handle the display of errors Laravel offers the directive @error which is used to display a message in the event of an error or to condition the display of a class.

old()

In addition to errors, in the event of a redirection, we also want to be able to redisplay the latest information entered by the user in the form. The method old() will precisely allow to retrieve this information from the session. We can also pass a default value to it as a second parameter to apply if there is no value from the session.

old('firstname', $post->firstname);

@method

Finally, a last directive will allow you to create a hidden field that will allow you to simulate methods that are not supported by basic HTML forms.

@method("PUT")

Example

Here is a small example of a form built with

<form action="{{ route('post.create') }}" method="post" class="vstack gap-2">
    @csrf
    <div class="form-group">
        <label for="title">Titre</label>
        <input type="text" class="form-control @error("title") is-invalid @enderror" id="title" name="title" value="{{ old('title') }}">
        @error("title")
            <div class="invalid-feedback">
                {{ $message }}
            </div>
        @enderror
    </div>
    <div class="form-group">
        <label for="slug">Slug</label>
        <input type="text" class="form-control @error("slug") is-invalid @enderror" id="slug" name="slug" value="{{ old('slug') }}">
        @error("slug")
            <div class="invalid-feedback">
                {{ $message }}
            </div>
        @enderror
    </div>
    <div class="form-group">
        <label for="content">Contenu</label>
        <textarea id="content" class="form-control @error("content") is-invalid @enderror"  name="content">{{ old('content') }}</textarea>
        @error("content")
            <div class="invalid-feedback">
                {{ $message }}
            </div>
        @enderror
    </div>
    <button class="btn btn-primary">
        Créer
    </button>
</form>

Improvement

Form creation can quickly become very verbose, so don’t hesitate to create reusable template pieces to make yourself more efficient.

<form action="{{ route('post.create') }}" method="post" class="vstack gap-2">
    @csrf
    @include('shared.input', ['name' => 'title', 'label' => 'Titre'])
    @include('shared.input', ['name' => 'slug', 'label' => 'URL'])
    @include('shared.input', ['name' => 'content', 'label' => 'Contenu', 'type' => 'textarea'])
    <button class="btn btn-primary">
        Créer
    </button>
</form>

You can also use blade components but that’s something we’ll see later.