Laravel 5 Crud Tutorial Example Step By Step From Scratch For Beginners

Laravel 5 Crud Example

In this tutorial, we are going to cover the crud operation with laravel 5.8 from scratch. This tutorial also covers the installation and configuration of laravel.

Note: I am using ubuntu OS for this tutorial. I am assuming you are familiar with a basic command of ubuntu.

Also, In this tutorial, I am assuming php, required laravel php extension and MySQL is already installed in your system. if not, you can follow below link

How to install linux php apache2 mysql on ubuntu 18.04.

Make sure the composer is installed as well. if not you can run below command to install composer in your system.

sudo apt update
sudo apt install composer

Let's get started.

Step 1. Install Laravel Project via Composer

To create a new project in laravel. Enter the following command

#/var/www/html
composer create-project laravel/laravel crud --prefer-dist

Note: I have given my laravel project name crud. you can specify your own if you want.

This command will install the fresh laravel project. After installation set the permission of storage and bootstrap directory. The below command will do the job.

#/var/www/html/crud
sudo chmod -R 777 storage/ bootstrap/

Note: It is not good practice to give 777 permission on the server.

Next, Generate the application encryption key with the following command.

php artisan key:generate

Run the project

To run the project enter the below command.

php artisan serve

and open http://127.0.0.1:8000

 Laravel installation success

Step 2. Configure the database

By default, laravel ships with .env.example file. So we need to change it to .env. To do so copy and rename it with the following command.

#/var/www/html/crud
cp .env.example .env

Next, edit the .env file and configure the database

#/var/www/html/crud/.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crud
DB_USERNAME=root
DB_PASSWORD=

My database name is crud, the username is root and I don't have any password for MySQL in my local machine. so I left it blank

Step 3. Create migration

According to laravel doc migration is like a version control where you share the table schema and allow to edit with your team.

To create a migration, use make:migration. To do so, enter the following command

 #/var/www/html/crud
php artisan make:migration create_post_table

This command will generate a file in database > migrations > create_posts_table.

Next, Edit the file and add the table

public function up()
{
    Schema::create('post', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('title');
        $table->string('title_slug');
        $table->text('post');
        $table->timestamps();
    });
}

Next, Run the below command to migrate in your terminal.

#/var/www/html/crud
php artisan migrate

This should output the below response

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table
Migrating: 2019_04_18_080711_create_post_table
Migrated:  2019_04_18_080711_create_post_table

Step 4. Create a model

Now the migration is done. Create a model for post table

#/var/www/html/crud
php artisan make:model Post

Note: All models are located in the app directory.

Run the following command to generate Authentication.

#/var/www/html/crud
php artisan make:auth

Note: we are using this command to use in-built laravel layouts.

Next, Edit the model

#/var/www/html/crud/app/Post.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Post extends Model
{
    protected $table = 'posts';

    protected $fillable = ['title', 'title_slug', 'category', 'post'];

    public function setTitleAttribute($value)
    {
    	$this->attributes['title'] = Str::title($value);
    	$this->attributes['title_slug'] = Str::slug($value);
    }
}

Here we are using laravel mutators which are used to format the eloquent values. we are using Str::title to set the Title Case and Str::slug to set the title URL friendly.

Step 5. Add URL to the route

#crud/routes/web.php

Route::get('/posts', 'PostController@index')->name('post-list');
Route::get('/post/create', 'PostController@create')->name('post-create');
Route::post('/post/store', 'PostController@store')->name('post-store');
Route::get('/post/edit/{id}', 'PostController@edit')->name('post-edit');
Route::post('/post/edit/{id}', 'PostController@update')->name('post-update');
Route::get('/post/destroy/{id}', 'PostController@destroy')->name('post-destroy');

/posts - display all the posts.

/post/create - create a new post.

/post/store - store a new post.

/post/edit/{id} - edit a single post.

/post/edit/{id} - update the post.

/post/destroy/{id} - delete post.

Step 6. Create a Controller

Next, Create a PostController. To do so, Enter the following command

#/var/www/html/crud
php artisan make:controller PostController

Edit PostController and update the following code

#/app/Http/Controllers/PostController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Post;

class PostController extends Controller
{
	public function index()
	{
		$posts = Post::all();

		return view('post.index', compact('posts'));
	}

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

    public function store(Request $request)
    {
    	$validatedData = $request->validate([
	        'title' => 'required|unique:posts|max:255',
	        'category' => 'required|max:10',
	        'post' => 'required',
	    ]);

	    Post::create($request->all());

    	return redirect()->to(route('post-list'));
    }

    public function edit($id)
    {
    	$post = Post::findOrFail($id);

    	return view('post.edit', compact('post'));
    }

    public function update(Request $request, $id)
    {
    	Post::find($id)->update($request->only('title', 'category', 'post'));

    	return redirect()->to(route('post-list'));
    }

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

    	return redirect()->to(route('post-list'));
    }
}

Step 7. Create a view

Next, Create index.blade.php file to list all the posts.

#/resources/views/post/index.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Create new post</div>

                <div class="card-body">

                    <table class="table">
                        <thead>
                            <tr>
                                <th>Title</th>
                                <th>Category</th>
                                <th>Post</th>
                                <th>Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            @foreach($posts as $post)
                            <tr>
                                <td>{{ $post->title }}</td>
                                <td>{{ $post->category }}</td>
                                <td>{{ $post->post }}</td>
                                <td>
                                    <a href="{{ route('post-edit', $post->id) }}">Edit</a> /
                                    <a href="{{ route('post-destroy', $post->id) }}">Delete</a>
                                </td>
                            </tr>
                            @endforeach
                        </tbody>
                    </table>

                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Next, Create create.blade.php file to create the post.

#/resources/views/post/create.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Create new post</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('post-store') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="title" class="col-md-4 col-form-label text-md-right">{{ __('Title') }}</label>

                            <div class="col-md-6">
                                <input id="title" type="title" class="form-control{{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" value="{{ old('title') }}" required autocomplete="title" autofocus>

                                @if ($errors->has('title'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('title') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="category" class="col-md-4 col-form-label text-md-right">{{ __('Category') }}</label>

                            <div class="col-md-6">
                                <input id="category" type="category" class="form-control{{ $errors->has('category') ? ' is-invalid' : '' }}" name="category" value="{{ old('category') }}" required autocomplete="category" autofocus>

                                @if ($errors->has('category'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('category') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="post" class="col-md-4 col-form-label text-md-right">{{ __('Post') }}</label>

                            <div class="col-md-6">
                                <textarea id="post" type="post" class="form-control{{ $errors->has('post') ? ' is-invalid' : '' }}" name="post" value="{{ old('post') }}" required autocomplete="post">{{ old('post') }}</textarea>

                                @if ($errors->has('post'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('post') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Create') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Next, Create the edit file to edit the post.

#/resources/views/post/edit.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Update Post</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('post-update', $post->id) }}">
                        @csrf

                        <div class="form-group row">
                            <label for="title" class="col-md-4 col-form-label text-md-right">{{ __('Title') }}</label>

                            <div class="col-md-6">
                                <input id="title" type="title" class="form-control{{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" value="{{ $post->title }}" required autocomplete="title" autofocus>

                                @if ($errors->has('title'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('title') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="category" class="col-md-4 col-form-label text-md-right">{{ __('Category') }}</label>

                            <div class="col-md-6">
                                <input id="category" type="category" class="form-control{{ $errors->has('category') ? ' is-invalid' : '' }}" name="category" value="{{ $post->category }}" required autocomplete="category" autofocus>

                                @if ($errors->has('category'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('category') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="post" class="col-md-4 col-form-label text-md-right">{{ __('Post') }}</label>

                            <div class="col-md-6">
                                <textarea id="post" type="post" class="form-control{{ $errors->has('post') ? ' is-invalid' : '' }}" name="post" required autocomplete="post">{{ $post->post }}</textarea>

                                @if ($errors->has('post'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('post') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Update') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Step 8. Test the crud operation in browser

To test the crud operation in browser You need to start the Laravel project using the below command.

php artisan serve

Creating new post

 

Screenshot of listing posts

Listing posts

 

Screenshot of editing a post

Laravel editing a post