Laravel Guide - Part 3. Creating forms

Categories:   web development  
Tags:   laravel   websites  

This is part 3 of the “Laravel Guide”.

You can check the previous post here.

Create a website using laravel

This is my personal notes on laravel for future reference.

Writing posts like these help me learn quicker.

Where Credit is due

Laravel Guide - Part 3. Creating forms

This section will cover:

  • Creating a form
  • Editing a post
  • Deleting a post

Creating a Form

Preparations

We will make a form in yourwebsite/posts/create to create new posts.

We’ll return the view for our post create function in PostsController.php:

public function create()
    {
        return view('posts.create');
    }

let’s make a new file: posts/create.blade.php and add:

@extends('layouts.app')

@section('content')
    <h1>Create Post</h1>
@endsection

The page should now be visible at yourwebsite/posts/create.

Add the form

goto https://laravelcollective.com/ and click on “HTML & FORMS” for reference.

Install the package with composer:

composer require "laravelcollective/html":"^5.4.0"

Add the providers in config/app.php:

Collective\Html\HtmlServiceProvider::class,

Add the two aliases in the same file:

'Form' => Collective\Html\FormFacade::class,
'Html' => Collective\Html\HtmlFacade::class,

the form mark up

Add the mark up in create.blade.php so it looks like:

@extends('layouts.app')

@section('content')
    <h1>Create Post</h1>
    {!! Form::open(['action' => 'PostsController@store', 'method' => 'POST']) !!}
        <div class="form-group">
            {{Form::label('title', 'Title')}}
            {{Form::text('title', '', ['class' => 'form-control', 'placeholder' => 'Title'])}}
        </div>
        <div class="form-group">
            {{Form::label('body', 'Body')}}
            {{Form::textarea('body', '', ['id' => 'article-ckeditor', 'class' => 'form-control', 'placeholder' => 'Body Text'])}}
        </div>
            {{Form::submit('Submit', ['class'=>'btn btn-primary'])}}
    {!! Form::close() !!}

@endsection

The form will send a POST to the PostsController store function.

Let’s update the store function in PostsController.php:

public function store(Request $request)
    {
        $this->validate($request, [
            'title' => 'required',
            'body' => 'required'
        ]);

        // Create Post
        $post = new Post;
        $post->title = $request->input('title');
        $post->body = $request->input('body');
        $post->save();

        return redirect('/posts')->with('success', 'Post Created');
    }

This will validate, create a new post and redirect user with a message.

Let’s add the messages.

view/inc/messages.blade.php:

@if (count($errors) > 0)
    @foreach($errors->all() as $error)
    <div class="alert alert-danger">
        {{$error}}
    </div>
    @endforeach
@endif

@if(session('success'))
    <div class="alert alert-success">
        {{session('success')}}
    </div>
@endif

@if(session('error'))
    <div class="alert alert-danger">
        {{session('error')}}
    </div>
@endif

layouts/app.blade.php:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="{{asset('css/app.css')}}">
        <title>{{config('app.name', 'LSAPP')}}</title>
    </head>
    <body>
        @include('inc.navbar')
        <div class="container">
            @include('inc.messages')
            @yield('content')   
        </div>
    </body>
</html>

We now have a working form to create new posts.

Let’s add this page to our navbar, view/inc/navbar.blade.php:

<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="/">{{config('app.name', 'LSAPP')}}</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
        <ul class="nav navbar-nav">
            <li><a href="/">Home</a></li>
            <li><a href="/about">About</a></li>
            <li><a href="/services">Services</a></li>
            <li><a href="/posts">Blog</a></li>
        </ul>
        <ul class="nav navbar-nav navbar-right">
            <li><a href="/posts/create">Create Post</a></li>
        </ul>
        </div><!--/.nav-collapse -->
    </div>
</nav>

Adding an editor to the form

We can also add an editor to the form.

Go to https://github.com/UniSharp/laravel-ckeditor for instructions:

  • install package with composer:
composer require unisharp/laravel-ckeditor
  • Add providers in config/app.php:
Unisharp\Ckeditor\ServiceProvider::class,
  • Publish the resources with the artisan command:
php artisan vendor:publish --tag=ckeditor

To use the editor we need to do two things.

Add the script to layouts/app.blade.php:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="{{asset('css/app.css')}}">
        <title>{{config('app.name', 'LSAPP')}}</title>
    </head>
    <body>
        @include('inc.navbar')
        <div class="container">
            @include('inc.messages')
            @yield('content')   
        </div>
        <script src="/vendor/unisharp/laravel-ckeditor/ckeditor.js"></script>
        <script>
            CKEDITOR.replace( 'article-ckeditor' );
        </script>
    </body>
</html>

Add the id to the forms body in posts/create.blade.php:

@extends('layouts.app')

@section('content')
    <h1>Create Post</h1>
    {!! Form::open(['action' => 'PostsController@store', 'method' => 'POST']) !!}
        <div class="form-group">
            {{Form::label('title', 'Title')}}
            {{Form::text('title', '', ['class' => 'form-control', 'placeholder' => 'Title'])}}
        </div>
        <div class="form-group">
            {{Form::label('body', 'Body')}}
            {{Form::textarea('body', '', ['id' => 'article-ckeditor', 'class' => 'form-control', 'placeholder' => 'Body Text'])}}
        </div>
            {{Form::submit('Submit', ['class'=>'btn btn-primary'])}}
    {!! Form::close() !!}

@endsection

Finally we need to update show.blade.php to parse the html:

@extends('layouts.app')

@section('content')
    <a href="/posts" class="btn btn-default">Go Back</a>
    <h1>{{$post->title}}</h1>
    <small>Written on {{$post->created_at}}</small>
    <hr>
    <div>
        {!!$post->body!!}
    </div>
@endsection

We changed the {{ }} to {!! !!}

The text editor should now be working.

Edit a POST

Adding the markup

We will add a link in the show.blade.php file:

@extends('layouts.app')

@section('content')
    <a href="/posts" class="btn btn-default">Go Back</a>
    <h1>{{$post->title}}</h1>
    <small>Written on {{$post->created_at}}</small>
    <hr>
    <div>
        {!!$post->body!!}
    </div>

    <a href="/posts/{{$post->id}}/edit" class="btn btn-default">Edit</a>
@endsection

This link us to the edit page with a specific post id.

We will update the edit function in the PostsController.php file:

public function edit($id)
    {
        $post = Post::find($id);
        return view('posts.edit')->with('post', $post);
    }

We just find the post id and return the view to posts/edit.

We need to create the file edit.blade.php and add:

@extends('layouts.app')

@section('content')
    <h1>Edit Post</h1>
    {!! Form::open(['action' => ['PostsController@update', $post->id], 'method' => 'POST']) !!}
        <div class="form-group">
            {{Form::label('title', 'Title')}}
            {{Form::text('title', $post->title, ['class' => 'form-control', 'placeholder' => 'Title'])}}
        </div>
        <div class="form-group">
            {{Form::label('body', 'Body')}}
            {{Form::textarea('body', $post->body, ['id' => 'article-ckeditor', 'class' => 'form-control', 'placeholder' => 'Body Text'])}}
        </div>
            {{Form::hidden('_method', 'PUT')}}
            {{Form::submit('Submit', ['class'=>'btn btn-primary'])}}
    {!! Form::close() !!}

@endsection

This file is similar to the create file but the action is changed to the update function.

Note: The method needs to be set to PUT and we spoof it here near the bottom of the form.

We also display the title and body text from the database.

We now need to create the update function in PostsController.php:

public function update(Request $request, $id)
    {
        $this->validate($request, [
            'title' => 'required',
            'body' => 'required'
        ]);

        // Update Post
        $post = Post::find($id);
        $post->title = $request->input('title');
        $post->body = $request->input('body');
        $post->save();

        return redirect('/posts')->with('success', 'Post Updated');
    }

This is similar to the store function but instead of a new Post, we will find post.

The update function should now be working.

Delete a post

We will add the delete form in show.blade.php:

@extends('layouts.app')

@section('content')
    <a href="/posts" class="btn btn-default">Go Back</a>
    <h1>{{$post->title}}</h1>
    <small>Written on {{$post->created_at}}</small>
    <hr>
    <div>
        {!!$post->body!!}
    </div>

    <a href="/posts/{{$post->id}}/edit" class="btn btn-default">Edit</a>

    {!!Form::Open(['action' => ['PostsController@destroy', $post->id], 'method' => 'POST', 'class' => 'pull-right'])!!}
        {{Form::hidden('_method', 'DELETE')}}
        {{Form::submit('DELETE', ['class' => 'btn btn-danger'])}}
    {!!Form::Close()!!}
@endsection

Like the update form, we will spoof the delete method with a hidden form.

We now need to create the destroy function in PostsController.php:

public function destroy($id)
    {
        $post = Post::find($id);
        $post->delete();

        return redirect('/posts')->with('success', 'Post Deleted');
    }

Here we find the specific post and delete it.

We should now be able to delete posts.

We now have a CRUD function working on our Laravel site.


I think we will end this section here.

In the next post we’ll learn about user authentication.

Related Products



Categories:   web development  
Tags:   laravel   websites