There are lot of tutorials out their regarding CRUD operation using Laravel 5.5 but, still I would like to show you some of the quickest ways to perform CRUD operation using Laravel.
There are lots of things we can cover in this tutorial but I want to make it straight and simple.
Every project start with some blueprint in mind. Before building a house we have to go through an architect who will create a blueprint of a house then builder will starts building a house in reality. Same thing is applicable in case of IT projects as well. So we will start this project with database design.
We are going to create database design for simple to-do list web application. We will allow users to register their self and create their own to-do list. Every project requires strong database design at its core to make it work efficiently. For our to-do list project we will use this database design:
One of the essential features almost every project needed is authentication. Laravel provides built-in authentication, which is easy to implement. So we are going to use it in this project. Laravel comes with a command-line interface which helps you to auto-generate some of the essential things.
Once you execute this artisan command it will generate all the necessary files required for authentication. Now we have authentication functionality available with remember me and forgot password.
Before proceed further you have to fill database credentials in your .env file.
Before try to run your migration you have to follow few steps to avoid this error regarding specified key is too long.
To fix this error you have to go todo/app/Providers/AppServiceProvider.php and add this 2 line:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191);
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
?>
Now you can run your migration using this artisan command:
php artisan migrate
This artisan command will run all the migrations which are generated in database/migrations directory.
Now it’s time to create migration, model and resource controller for our todo table. We have single artisan command to auto generate all this stuff which save your lot of time.
Now we have generated migration, model and controller. It’s time to define schema inside our migration file.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTodosTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('todos', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->text('description')->nullable();
$table->boolean('is_completed');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('todos');
}
}
?>
Now we will run artisan command to run this new migration file.
We are going to add resource route in routes/web.php like this:
route::resource(‘todos’,’TodoController’);
We are going to add one navigation link to show todo’s list. We are going to add route name todos.index in href in layouts/app.blade.php layout.
Now first we will modify TodoController’s index action to show list of todos.
<?php
namespace App\Http\Controllers;
use App\Todo;
use Illuminate\Http\Request;
class TodoController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$todos = Todo::where('user_id',auth()->user()->id)->get();
return view('todos.index',compact('todos'));
}
}
?>
The view we have specified in view helper is not exist now. We are going to create this view now inside views/todo folder (index.blade.php).
I have just modified code inside views/todos/index.blade.php to show list of todos.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
Todo List
<div class="pull-right">
<a href="{{ route('todos.create') }}" class="btn btn-primary btn-sm">Add Todo</a>
</div>
<div class="clearfix"></div>
</div>
<div class="panel-body">
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
<table class="table">
<thead>
<th>ID</th>
<th>Description</th>
<th>Is Completed?</th>
<th>Action</th>
</thead>
<tbody>
@forelse ($todos as $todo)
<td>{{ $todo->id }}</td>
<td>{{ $todo->description }}</td>
<td>{{ $todo->is_completed }}</td>
<td>
<a href="{{ route('todos.edit', $todo->id) }}" class="btn btn-md btn-success">Edit</a>
<form style="display:inline" action="{{ route('todos.destroy', $todo->id) }}" onsubmit='return confirm("Are you sure want to delete todo?");' method="post">
{!! csrf_field() !!}
{!! method_field('DELETE') !!}
<input type="submit" class="btn btn-danger" value="Delete" />
</form>
</td>
@empty
<td colspan="3" class="text-center">No todos</td>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@endsection
This is how it looks like in browser.
Now we are going to modify on TodoController’s create and store action to create todos.
<?php
namespace App\Http\Controllers;
use App\Todo;
use Illuminate\Http\Request;
class TodoController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
…
public function create()
{
return view('todos.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$todo = new Todo();
$todo->user_id = auth()->user()->id;
$todo->description = $request->description;
if($request->has('is_completed'))
$todo->is_completed = $request->is_completed;
else
$todo->is_completed = 0;
$todo->save();
return redirect()->route('todos.index')->with('success', 'Todo created successfully!');
}
}
Now we are going to work on views/todos/create.blade.php to show how to create todo.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
Add Todo
</div>
<div class="panel-body">
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
<form class="form-horizontal" action="{{ route('todos.store') }}" method="post">
{!! csrf_field() !!}
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="description" name="description" placeholder="Description">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" name="is_completed" value="1"> Is completed?
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Add</button>
<a href="{{ route('todos.index') }}" class="btn btn-default">Back</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Now it looks like this in your browser:
We are going to follow similar approach for edit and update todos:
<?php
namespace App\Http\Controllers;
use App\Todo;
use Illuminate\Http\Request;
class TodoController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
…
public function edit(Request $request, $id)
{
$todo = Todo::find($id);
return view('todos.edit',compact('todo'));
}
public function update(Request $request, $id)
{
$todo = Todo::find($id);
$todo->user_id = auth()->user()->id;
$todo->description = $request->description;
if($request->has('is_completed'))
$todo->is_completed = $request->is_completed;
else
$todo->is_completed = 0;
$todo->save();
return redirect()->route('todos.index')->with('success', 'Todo updated successfully!');
}
}
We are going to copy create view and modify it for edit view:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
Edit Todo
</div>
<div class="panel-body">
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
<form class="form-horizontal" action="{{ route('todos.update', $todo->id) }}" method="post">
{!! csrf_field() !!}
{!! method_field('PUT') !!}
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="description" value="{{ $todo->description }}" name="description" placeholder="Description">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" name="is_completed" value="1" {{ $todo->is_completed == 1 ? 'checked':'' }}> Is completed?
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Update</button>
<a href="{{ route('todos.index') }}" class="btn btn-default">Back</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Now it looks like this in your browser:
For delete todos we have to make delete request which is already done in todos/index.blade.php and in TodoController we have to write some code in destroy action:
<?php
namespace App\Http\Controllers;
use App\Todo;
use Illuminate\Http\Request;
class TodoController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
…
public function destroy(Request $request, $id)
{
Todo::find($id)->delete();
return redirect()->route('todos.index')->with('success', 'Todo deleted successfully!');
}
}
That’s all! Let me know if you are facing any difficulties while following tutorial.