This tutorial provides all the steps required to perform CRUD operations in applications developed using the Laravel Framework. It provides the complete steps following the MVC (Model View Controller) architecture for the most recent version of Laravel i.e. Laravel 8. Also, it provides the steps to Create, Read, Update, and Delete using the MongoDB database.
It provides the simple steps to perform the CRUD operations to manage the tasks by creating a task manager application using Laravel 8. In order to keep this tutorial simple, it does not cover the authentication of users using the login and registration process.
Prerequisites
This tutorial assumes that PHP, Apache Web Server, and MongoDB are already installed on your system. You can follow How To Install XAMPP On Windows or How To Install WampServer on Windows to install PHP and Apache Web Server. You may follow How To Install PHP 8 On Ubuntu 20.04 LTS, How To Install Apache 2 On Ubuntu 20.04 LTS, How To Install MongoDB 5 on Ubuntu 20.04 LTS, How To Install PHP 8 On Windows 10, How To Install Apache 2 On Windows, and How To Install MongoDB 5 on Windows to install them separately on either Ubuntu or Windows. You are also required to have Composer installed on your system. You can follow How To Install Composer On Ubuntu 20.04 and How To Install Composer As PHP Dependency Manager On Windows to install Composer.
Also, configure MongoDB extension for PHP as shown in How To Configure MongoDB for PHP on Windows and Ubuntu and Laravel MongoDB fails installing jenssegers/mongodb. It's required to enable Authentication as shown in How To Install MongoDB 5 on Ubuntu 20.04 LTS and How To Install MongoDB 5 on Windows.
Notes: I have used WampServer with PHP 7.4.9, Apache 2.4.46, and MongoDB 5 installed on my system. Also, this tutorial installs Laravel using Composer and does not cover the Docker way of installing Laravel.
Install Laravel 8
In this step, we will create the project using the composer and install the most recent version of Laravel 8 using the command as shown below.
# Create the project by installing Laravel 8 composer create-project laravel/laravel=8.* mvccruddemo --prefer-dist
# Output Creating a "laravel/laravel=8.*" project at "./mvccruddemo" Installing laravel/laravel (v8.6.8) - Downloading laravel/laravel (v8.6.8) - Installing laravel/laravel (v8.6.8): Extracting archive .... .... Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fruitcake/laravel-cors Discovered Package: laravel/sail Discovered Package: laravel/sanctum Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. 77 packages you are using are looking for funding. Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi No publishable resources for tag [laravel-assets]. Publishing complete.
> @php artisan key:generate --ansi Application key set successfully.
The above command creates the default project structure of Laravel 8 and installs the dependencies in the vendor directory as shown in Fig 1.
Also, install the MongoDB extension for Laravel using the command as shown below.
# CD cd mvccruddemo
# MongoDB Extension for Laravel composer require jenssegers/mongodb
Create and Configure Database
In this step, we will create the MongoDB database required to perform the CRUD operations using the Laravel 8 application installed by us in the previous step. We will also configure the project environment to use the database created by us. You can create the database either using the console or MongoDB Compass.
# Connect to MongoDB from Console mongosh --username admin --password <password> --authenticationDatabase admin
Instead of using the root user, you may create a specific user to manage the application database by providing appropriate privileges.
# Switch Database use mvccruddemo
# Output switched to db mvccruddemo
# Create User db.createUser( { user: "mvccrud", pwd: "<password>", roles: [ { db: "mvccruddemo", role: "readWrite" } ] } )
# Output { ok: 1 }
Now, configure the Laravel 8 CRUD application to use the MongoDB database and user by updating the .env file located at the root of the project as shown below.
.... .... DB_CONNECTION=mongodb DB_HOST=127.0.0.1 DB_PORT=27017 DB_DATABASE=mvccruddemo DB_USERNAME=mvccrud DB_PASSWORD="<password>" .... ....
Notes: Avoid using # in your password, else enclose it in quotes.
Now, update the database configuration by updating config/database.php as shown below.
.... .... //'default' => env('DB_CONNECTION', 'mysql'), 'default' => env('DB_CONNECTION', 'mongodb'), .... .... 'connections' => [ .... .... 'mongodb' => [ 'driver' => 'mongodb', 'host' => env('DB_HOST'), 'port' => env('DB_PORT'), 'database' => env('DB_DATABASE'), 'username' => env('DB_USERNAME'), 'password' => env('DB_PASSWORD'), 'options' => [ 'database' => env('DB_DATABASE') ] ], .... ....
Create Migrations
In this step, we will create the migration to create the database collections to store the tasks. Open the console and navigate to the project root directory. Also, create the migration using the command as shown below.
# Create Migration php artisan make:migration create_tasks_table --create=tasks
# Output Created Migration: 2021_12_05_093945_create_tasks_table
The above command will create the migration script in the database/migrations directory. You may notice few migration scripts are already there in the migrations directory. These were created by Laravel as part of the project installation step. The possible fields of task documents required to manage the tasks are shown below.
Id | The unique id to identify the task. |
User Id | The user id to identify the corresponding user. |
Created By | The user id to identify the user who added the task. |
Updated By | The user id to identify the user who updated the task. |
Title | The title of the Task. |
Description | The description of the Task. |
Status | The status of the task can be New, In-Progress, or Completed. |
Hours Required | The total hours required by the Task. It can be filled while creating the task. |
Hours Consumed | The total hours consumed by the Task. It can be manually filled on task completion. |
Created At | It stores the date and time at which the task is created. |
Updated At | It stores the date and time at which the task is updated. |
Planned Start Date | It stores the date and time at which the task is planned to start. |
Planned End Date | It stores the date and time at which the task is planned to end. |
Actual Start Date | It stores the actual date and time at which the task started. |
Actual End Date | It stores the actual date and time at which the task is finished. |
Content | The field is used to store the task details. |
It uses the field status to track the status of the task. The status can be either New, In-Progress, or Completed. Also, the user can manually fill the hours required to complete the task.
Now, open the tasks migration script and update it as shown below. We will simply add an index for the status field as shown below.
public function up() {
Schema::create( 'tasks', function( Blueprint $table ) {
$table->index('status'); }); }
Use the below-mentioned command to run the migration scripts to create the database collections as shown below. Make sure to run this command from the project root directory.
# Create Migrations php artisan migrate
# Create Migrations -> If using multiple database systems php artisan migrate --database=mongodb
# Output Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (149.13ms) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (173.55ms) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (114.40ms) Migrating: 2019_12_14_000001_create_personal_access_tokens_table Migrated: 2019_12_14_000001_create_personal_access_tokens_table (142.53ms) Migrating: 2021_12_05_093945_create_tasks_table Migrated: 2021_12_05_093945_create_tasks_table (445.90ms)
This completes the migrations and creates the collections corresponding to the migration scripts as shown in Fig 2.
Configure Providers
In this step, we will configure the providers to use the MongoDB extension provided by Jens Segers by updating the config/app.php file as shown below.
.... .... 'providers' => [ .... .... Jenssegers\Mongodb\MongodbServiceProvider::class ], .... ....
Create Controller And Model
In this step, we will create the TaskController and the corresponding resource model as shown below.
# Create Controller and Resource Model php artisan make:controller TaskController --resource --model=Task
# Output A App\Models\Task model does not exist. Do you want to generate it? (yes/no) [yes]: > yes
Model created successfully. Controller created successfully.
The create controller command asks to create the model as shown above. Enter yes to create the Task model. The command will create the TaskController in the app/Http/Controllers directory with the default CRUD methods and Task model in the app/Models directory.
Add Resource Route
In this step, we will add a resource route to perform the CRUD operations using the TaskController created by us in the previous step. Update the routes/web.php to add the resource route as shown below.
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\TaskController;
....
....
Route::resource( 'tasks', TaskController::class );
Update Controller And Model
In this step, we will update the controller and model to perform the CRUD operations. I have updated the default methods created by the create controller command as shown below.
<?php namespace App\Http\Controllers;
use App\Models\Task; use Illuminate\Http\Request;
class TaskController extends Controller {
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() {
$tasks = Task::latest()->paginate( 10 );
$statusMap = Task::$statusMap;
return view( 'tasks.index', compact( 'tasks', 'statusMap' ) )
->with( 'i', ( request()->input( 'page', 1 ) - 1 ) * 10 ); }
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create() {
$statusMap = Task::$statusMap;
return view( 'tasks.create', compact( 'statusMap' ) ); }
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store( Request $request ) {
$request->validate([
'title' => 'required',
'status' => 'required|numeric|min:0|not_in:0',
'hoursRequired' => 'numeric|nullable|min:0|not_in:0',
'hoursConsumed' => 'numeric|nullable|min:0|not_in:0',
'plannedStartDate' => 'nullable|date_format:Y-m-d',
'plannedEndDate' => 'nullable|date_format:Y-m-d',
'actualStartDate' => 'nullable|date_format:Y-m-d',
'actualEndDate' => 'nullable|date_format:Y-m-d'
]);
Task::create( $request->all() );
return redirect()->route( 'tasks.index' )
->with( 'success', 'Task created successfully.' );
}
/**
* Display the specified resource.
*
* @param \App\Models\Task $task
* @return \Illuminate\Http\Response
*/
public function show( Task $task ) {
return view( 'tasks.show', compact( 'task' ) );
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Task $task
* @return \Illuminate\Http\Response
*/
public function edit( Task $task ) {
$statusMap = Task::$statusMap;
return view( 'tasks.edit', compact( 'task', 'statusMap' ) );
}
/** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param \App\Models\Task $task * @return \Illuminate\Http\Response */
public function update( Request $request, Task $task ) {
$request->validate([
'title' => 'required',
'status' => 'required|numeric|min:0|not_in:0',
'hoursRequired' => 'numeric|nullable|min:0|not_in:0',
'hoursConsumed' => 'numeric|nullable|min:0|not_in:0',
'plannedStartDate' => 'nullable|date_format:Y-m-d',
'plannedEndDate' => 'nullable|date_format:Y-m-d',
'actualStartDate' => 'nullable|date_format:Y-m-d',
'actualEndDate' => 'nullable|date_format:Y-m-d' ]);
$task->update( $request->all() );
return redirect()->route( 'tasks.index' )
->with( 'success', 'Task updated successfully.' ); }
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Task $task
* @return \Illuminate\Http\Response
*/
public function destroy( Task $task ) {
$task->delete();
return redirect()->route( 'tasks.index' )
->with( 'success', 'Task deleted successfully.' );
} }
I have also updated the model as shown below.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Jenssegers\Mongodb\Eloquent\Model;
class Task extends Model {
const CREATED_AT = 'createdAt';
const UPDATED_AT = 'updatedAt';
const STATUS_NEW = 10;
const STATUS_PROGRESS = 20;
const STATUS_COMPLETED = 30;
public static $statusMap = [
self::STATUS_NEW => 'New',
self::STATUS_PROGRESS => 'In Progress',
self::STATUS_COMPLETED => 'Completed'
];
use HasFactory;
/**
* The storage format of the model's date fields.
*
* @var string
*/
protected $dateFormat = 'Y-m-d H:i:s';
protected $fillable = [
'title', 'description', 'status',
'hoursRequired', 'hoursConsumed',
'plannedStartDate', 'plannedEndDate',
'actualStartDate', 'actualEndDate',
'content'
];
public function getStatusStr() {
return self::$statusMap[ $this->status ]; } }
Create Layout And Views
In this step, we will create the layout used for the CRUD operations. We will also create the views to perform the CRUD operations.
Task Layout - <project root>/resources/views/layouts/task.blade.php
<!DOCTYPE html> <html> <head> <!-- Meta --> <meta charset="utf-8"> <meta name="title" content="@yield( 'metaTitle' ) | Task Manager"> <meta name="description" content="@yield('metaDescription')" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Title --> <title>@yield( 'metaTitle' ) | Task Manager</title>
<!-- Favicon --> <link rel="shortcut icon" href="{{ url('/images/icons/favicon.ico') }}"> <link rel="apple-touch-icon-precomposed" href="{{ url('/images/icons/apple-icon-precomposed.png') }}">
<!-- jQuery --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous"></script>
<!-- Bootstrap --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker3.min.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
<!-- Font Awesome --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<script type="text/javascript"> jQuery( document ).ready(function() { jQuery( '.datepicker' ).datepicker(); jQuery( '.trigger-info' ).click( function() { var info = jQuery( this ).closest( '.row-task-main' ).next( '.row-task-info' ); jQuery( '.row-task-info' ).not( info ).hide();
if( info.is( ':visible' ) ) {
info.slideUp( 'fast' );
}
else {
info.slideDown( 'slow' );
}
});
});
</script>
<style type="text/css"> .cursor-pointer { cursor: pointer; }
.row-task-info { display: none; } </style> </head> <body> <header> <div class="p-5 text-center bg-light"> <h1 class="mb-3">Task Manager</h1> <h4 class="mb-3">(Manage Tasks)</h4> </div> </header> <div class="container"> @yield( 'content' ) </div> </body> </html>
Tasks Index - <project root>/resources/views/tasks/index.blade.php
@extends( 'layouts.task' ) @section( 'metaTitle', 'All Tasks' ) @section( 'metaDescription', 'Shows the list of all the tasks.' ) @section( 'content' ) <div class="clearfix pt-4 pb-2"> <div class="float-left"> <h2>Manage Tasks</h2> </div> <div class="float-right"> <a class="btn btn-success" href="{{ route( 'tasks.create' ) }}" title="Create Task"> <i class="fas fa-plus"></i> </a> </div> </div> @if( $message = Session::get( 'success' ) ) <div class="alert alert-success"> <p>{{ $message }}</p> </div> @endif <div class="container"> <div class="row text-2xl"> <div class="col p-2 border border-right-0"><h5>Title</h5></div> <div class="col-6 p-2 border border-right-0"><h5>Description</h5></div> <div class="col p-2 border border-right-0"><h5>Status</h5></div> <div class="col p-2 border"><h5>Actions</h5></div> </div> @foreach( $tasks as $task ) <div class="row row-task-main"> <div class="col p-2 border border-right-0">{{ $task->title }}</div> <div class="col-6 p-2 border border-right-0">{{ $task->description }}</div> <div class="col p-2 border border-right-0">{{ $task->getStatusStr() }}</div> <div class="col p-2 border"> <form action="{{ route( 'tasks.destroy', $task->id ) }}" method="POST"> <span class="trigger-info cursor-pointer" title="Info"> <i class="fas fa-info text-success fa-lg"></i> </span> <a href="{{ route( 'tasks.show', $task->id ) }}" title="View"> <i class="fas fa-eye text-success fa-lg"></i> </a> <a href="{{ route( 'tasks.edit', $task->id) }}"> <i class="fas fa-edit fa-lg"></i> </a> @csrf @method( 'DELETE' ) <button type="submit" title="Delete" style="border: none; background-color:transparent;"> <i class="fas fa-trash fa-lg text-danger"></i> </button> </form> </div> </div> <div class="row row-task-info border border-top-0 p-3"> <div class="row"> <div class="col-md-6"> <span class="font-weight-bold">Hours Estimated:</span> {{ $task->hoursRequired }}<br/> <span class="font-weight-bold">Hours Consumed:</span> {{ $task->hoursConsumed }} </div> <div class="col-md-6"> <span class="font-weight-bold">Planned Start Date:</span> {{ $task->plannedStartDate }}<br/> <span class="font-weight-bold">Planned End Date:</span> {{ $task->plannedEndDate }} </div> <div class="col-md-6"> <span class="font-weight-bold">Actual Start Date:</span> {{ $task->actualStartDate }}<br/> <span class="font-weight-bold">Actual End Date:</span> {{ $task->actualEndDate }} </div> </div> </div> @endforeach </div> {!! $tasks->links() !!} @endsection
Create Task - <project root>/resources/views/tasks/create.blade.php
@extends( 'layouts.task' ) @section( 'metaTitle', 'Create Task' ) @section( 'metaDescription', 'Create a new task.' ) @section( 'content' ) <div class="clearfix pt-4 pb-2"> <div class="float-left"> <h2>Add Task</h2> </div> <div class="float-right"> <a class="btn btn-primary" href="{{ route( 'tasks.index' ) }}" title="All Tasks"> <i class="fa fa-arrow-left"></i> </a> </div> </div> @if($errors->any()) <div class="alert alert-danger"> Resolve the errors to create the task.<br/> <ul> @foreach( $errors->all() as $error ) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route( 'tasks.store' ) }}" method="POST"> @csrf <div class="row"> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Title *</label> <input type="text" name="title" class="form-control" placeholder="Title" value="{{old('title')}}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Status *</label> <select name="status" class="form-control"> <?php foreach( $statusMap as $key => $value ) {
if( !empty( old( 'status' ) ) && $key == old( 'status' ) ) { ?> <option value="<?= $key ?>" selected><?= $value ?></option> <?php } else { ?> <option value="<?= $key ?>"><?= $value ?></option> <?php } } ?> </select> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <div class="form-group"> <label>Description</label> <textarea name="description" class="form-control" placeholder="Description">{{old('description')}}</textarea> </div> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Hours Estimated</label> <input type="text" name="hoursRequired" class="form-control" placeholder="Hours Estimated" value="{{old('hoursRequired')}}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Hours Consumed</label> <input type="text" name="hoursConsumed" class="form-control" placeholder="Hours Consumed" value="{{old('hoursConsumed')}}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Planned Start Date</label> <input type="text" name="plannedStartDate" class="form-control datepicker" placeholder="Planned Start Date" data-date-format="yyyy-mm-dd" value="{{old('plannedStartDate')}}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Planned End Date</label> <input type="text" name="plannedEndDate" class="form-control datepicker" placeholder="Planned End Date" data-date-format="yyyy-mm-dd" value="{{old('plannedEndDate')}}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Actual Start Date</label> <input type="text" name="actualStartDate" class="form-control datepicker" placeholder="Actual Start Date" data-date-format="yyyy-mm-dd" value="{{old('actualStartDate')}}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Actual End Date</label> <input type="text" name="actualEndDate" class="form-control datepicker" placeholder="Actual End Date" data-date-format="yyyy-mm-dd" value="{{old('actualEndDate')}}"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <div class="form-group"> <label>Notes</label> <textarea name="content" class="form-control" placeholder="Notes">{{old('content')}}</textarea> </div> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center p-3"> <button type="submit" class="btn btn-primary">Create</button> </div> </div> </form> @endsection
Update Task - <project root>/resources/views/tasks/edit.blade.php
@extends( 'layouts.task' ) @section( 'metaTitle', 'Update Task' ) @section( 'metaDescription', 'Update an existing task.' ) @section( 'content' ) <div class="clearfix pt-4 pb-2"> <div class="float-left"> <h2>Update Task</h2> </div> <div class="float-right"> <a class="btn btn-primary" href="{{ route( 'tasks.index' ) }}" title="All Tasks"> <i class="fa fa-arrow-left"></i> </a> </div> </div> @if($errors->any()) <div class="alert alert-danger"> Resolve the errors to create the task.<br/> <ul> @foreach( $errors->all() as $error ) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route( 'tasks.update', $task->id ) }}" method="POST"> @csrf @method('PUT') <div class="row"> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Title *</label> <input type="text" name="title" class="form-control" placeholder="Title" value="{{ $task->title }}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Status *</label> <select name="status" class="form-control"> <?php foreach( $statusMap as $key => $value ) {
if( $key == $task->status ) { ?> <option value="<?= $key ?>" selected><?= $value ?></option> <?php } else { ?> <option value="<?= $key ?>"><?= $value ?></option> <?php } } ?> </select> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <div class="form-group"> <label>Description</label> <textarea name="description" class="form-control" placeholder="Description">{{ $task->description }}</textarea> </div> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Hours Estimated</label> <input type="text" name="hoursRequired" class="form-control" placeholder="Hours Estimated" value="{{ $task->hoursRequired }}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Hours Consumed</label> <input type="text" name="hoursConsumed" class="form-control" placeholder="Hours Consumed" value="{{ $task->hoursConsumed }}"> </div>
</div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Planned Start Date</label> <input type="text" name="plannedStartDate" class="form-control datepicker" placeholder="Planned Start Date" data-date-format="yyyy-mm-dd" value="{{ $task->plannedStartDate }}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Planned End Date</label> <input type="text" name="plannedEndDate" class="form-control datepicker" placeholder="Planned End Date" data-date-format="yyyy-mm-dd" value="{{ $task->plannedEndDate }}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Actual Start Date</label> <input type="text" name="actualStartDate" class="form-control datepicker" placeholder="Actual Start Date" data-date-format="yyyy-mm-dd" value="{{ $task->actualStartDate }}"> </div> </div> <div class="col-xs-6 col-sm-6 col-md-6"> <div class="form-group"> <label>Actual End Date</label> <input type="text" name="actualEndDate" class="form-control datepicker" placeholder="Actual End Date" data-date-format="yyyy-mm-dd" value="{{ $task->actualEndDate }}"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <div class="form-group"> <label>Notes</label> <textarea name="content" class="form-control" placeholder="Notes">{{ $task->content }}</textarea> </div> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center p-3"> <button type="submit" class="btn btn-primary">Update</button> </div> </div> </form> @endsection
View Task - <project root>/resources/views/tasks/show.blade.php
@extends( 'layouts.task' ) @section( 'metaTitle', 'View Task' ) @section( 'metaDescription', 'View task details.' ) @section( 'content' ) <div class="clearfix pt-4 pb-2"> <div class="float-left"> <h2>Task Details ({{ $task->title }})</h2> </div> <div class="float-right"> <a class="btn btn-primary" href="{{ route( 'tasks.index' ) }}" title="All Tasks"> <i class="fa fa-arrow-left"></i> </a> </div> </div> <div class="row pt-3"> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Title - </strong> {{ $task->title }} </div> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Status - </strong> {{ $task->getStatusStr() }} </div> </div>
<div class="row pt-3"> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Description - </strong> {{ $task->description }} </div> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Notes - </strong> {{ $task->notes }} </div> </div> <div class="row pt-3"> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Hours Estimated - </strong> {{ $task->hoursRequired }} </div> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Hours Consumed - </strong> {{ $task->hoursConsumed }} </div> </div> <div class="row pt-3"> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Planned Start Date - </strong> {{ $task->plannedStartDate }} </div> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Planned End Date - </strong> {{ $task->plannedEndDate }} </div> </div> <div class="row pt-3"> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Actual Start Date - </strong> {{ $task->actualStartDate }} </div> <div class="col-xs-6 col-sm-6 col-md-6"> <strong>Actual End Date - </strong> {{ $task->actualEndDate }} </div> </div> @endsection
This completes the views section.
Configure The Application
Optionally, we can configure the application to use it as a sub-directory on localhost by updating the configuration files as shown below.
# Update <project root>/.env .... .... APP_URL=http://localhost/mvccruddemo .... ....
# Update <project root>/public/.htaccess .... .... RewriteEngine On RewriteBase /mvccruddemo/ .... ....
Run The Application
In the previous steps, we have created the application, database, migrations, controller, model, and views. We have also configured the environment to use the database created by us and updated the routes to include our resource route. In this step, we will launch the application using the development server as shown below.
# Launch Application php artisan serve
# Output Starting Laravel development server: http://127.0.0.1:8000 [Sun Dec 5 15:33:10 2021] PHP 7.4.9 Development Server (http://127.0.0.1:8000) started
We can also launch the application using the Apache Web Server by adding an alias pointing to the public directory located at the project root.
Now open the application using your preferred web browser using the URL http://127.0.0.1:8000. The default page on launching the application shows the Laravel details as shown in Fig 3.
Now open the tasks page using your preferred web browser using the URL http://127.0.0.1:8000/tasks. The tasks page shows the tasks created by us as shown in Fig 4. Initially, it won't show any task.
Summary
This tutorial provided all the steps required to perform the CRUD operations using Laravel 8 and MongoDB. You can download the complete source code from GitHub.