How to intregrate CK editor in Laravel

In this tutorial, we are going to create a new Laravel application for creating blogs or posts. While creating a blog we'll use CKEditor to take input or HTML input and store it in our database.

Before starting, let's understand why CKEditor is useful compared to HTML elements like text-area or inputs. The CKEditor is a rich text editor which means it has basic formatting abilities like font size, color, family, and more. But with the latest release, you can almost use it like Microsoft Word. You can show tables, headers, images, links, and many more things with help of CKEditor.

As you know HTML text area or input can allow us to submit some data as text but can not take inputs like HTML elements titles or tables. Plugins like CKEditor provides a way to create HTML based format converting user input into text.

For a better understanding of implementation we have divided the program into a few steps :

  • Step 1: Create New Laravel Application
  • Step 2: Database Configuration
  • Step 3: Creating Model and Migrations
  • Step 4: Controller Logic
  • Step 5: Adding Views
  • Step 6: Define Routes
  • Step 7: Testing Application

Create New Laravel Application

Let's begin this tutorial by creating a new Laravel application. Navigate to your localhost directory based on XAMPP or WAMPP then you can create a fresh Laravel application with one of the below commands:

composer create-project --prefer-dist laravel/laravel Blog
//If you already installed laravel globel installer
laravel new Blog

It will take some time to create a new application and downloading/set new files.

Database Configuration

Let's configure a database for our application. If you don't have a database then create a new one. After making database open .env file from root directory of your project. The .env file defines many common environment variables

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=YOUR_DATABASE_NAME
DB_USERNAME=USERNAME
DB_PASSWORD=PASSWORD

Creating Model and Migrations

In this example, we will integrate CKEditor and store its input into our database and render it back whenever we require. For database operation in Laravel, we need to create model which handles database operation for a particular table.

Here, we will simply create a post model and define two columns to store title and content. In actual project, you can define numbers of columns into your model as per your requirements.

To create model and migration enter below command to terminal :

php artisan make:model Post -m

This will create a Contact model and a migration file. In the terminal, we get an output similar to:

Model created successfully.
Created Migration: 2019_01_27_193840_create_posts_table

After completion of command's execution. let's define table schema for post table. Open the database/migrations/xxxxxx_create_posts_table migration file and update it accordingly:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

Here, We added the title and body fields in the posts table structure.

Let's make some changes into our model so we can use mass assignment for this table. Open the app/models/Post.php file and update it accordingly:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = [
        'title',
        'body',
    ];
}

Now, we have defined database structure and made necessary changes to our model. It's time to create actual table in our database. Open terminal and enter below command:

php artisan migrate

It will generate table into your database specified in .ENV file. You can verify that in phpMyAdmin.

Controller Logic

Controllers are meant to group associated request-handling logic within a single class. For operations related to Post, we have to create a controller. You can use any other controller or existing controller for this task but we suggest create seperate controller as per your logic. It will help you to maintain minimum response time and code understanding.

In your terminal, run the following command to create a controller:

php artisan make:controller PostController

This command will generate a controller at app/Http/Controllers/PostController.php. Here, we will define methods for post-operations. Let's modify it as per our logic:

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index() {
        $posts =  Post::orderBy("id", "desc")->paginate(10);
        return view("welcome", compact("posts"));
    }

    public function create() {
        return view("create_post");
    }

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

        Post::create([
            "title"  =>  $request->title,
            "body" => $request->body
        ]);

        return back()->with("success", "Post has been created");
    }
}

Here, we have used Post Model and defined three different methods. The index method will get all post data and pass it to show a listing of posts/blogs. While create method will just return create a view which contains Form with CKEditor. At last, the store method will handle the save process based on user input.

Adding Views

The view performs all front-end functionality of our application like displaying data, getting user input or getting requests. In this example, we need to create 1 view and we will modify the default welcome view. The first view will be displayed on home page and shows stored post data while the second view will be used to get post-related user input.

We'll use the default welcome view to display list of posts. Open welcome view and modify as below:

<!doctype html>
<html lang="en">
    <head>
        <title>  Laravel CKEditor Example </title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <style>
            table td p {
                word-break: break-all;
            }
        </style>
    </head>
    <body>
        <div class="container mt-4">
            <div class="row">
                <div class="col-xl-8">
                    <h3 class="text-right"> Laravel CKEditor Example</h3>
                </div>
                <div class="col-xl-4 text-right">
                    <a href="{{url('create')}}" class="btn btn-primary"> Add Post </a>
                </div>
            </div>
            <div class="table-responsive mt-4">
                <table class="table table-striped table-bordered">
                    <thead>
                        <tr>
                            <th> Id </th>
                            <th style="width:30%;"> Title </th>
                            <th> Content </th>
                        </tr>
                    </thead>
                    <tbody>
                        @foreach($posts as $post)
                            <tr>
                                <td> {{ $post->id }} </td>
                                <td> {{ $post->title }} </td>
                                <td> {!! html_entity_decode($post->body) !!} </td>
                            </tr>
                        @endforeach
                    </tbody>
                </table>
            </div>
            {{ $posts->links() }}
        </div>
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    </body>
</html>

Here, we just added simple link to navigate to post creation page and table to display posts. At bottom of table, we have included pagination links too so it will display 10 posts at a time.

Let's create another view for form which will handle post inputs. Create new file with name as create_post.blade.php and add below code in it.

<!doctype html>
<html lang="en">
    <head>
        <title> Laravel 8 Install CKEditor Example </title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        {{-- CKEditor CDN --}}
        <script src="https://cdn.ckeditor.com/ckeditor5/23.0.0/classic/ckeditor.js"></script>
    </head>
    <body>
        <div class="container mt-5">
            <form action="{{url('store')}}" method="POST">
                @csrf
                <div class="row">
                    <div class="col-md-12 m-auto">
                        @if(Session::has('success'))
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert">×</button>
                                {{ Session::get('success') }}
                            </div>
                        @elseif(Session::has('failed'))
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert">×</button>
                                {{ Session::get('failed') }}
                            </div>
                        @endif
                        <div class="card shadow">
                            <div class="card-header">
                                <h4 class="card-title"> Create Post </h4>
                            </div>
                            <div class="card-body">
                                <div class="form-group">
                                    <label> Title </label>
                                    <input type="text" class="form-control" name="title" placeholder="Enter the Title">
                                </div>
                                <div class="form-group">
                                    <label> Body </label>
                                    <textarea class="form-control" id="content" placeholder="Enter the Description" rows="5" name="body"></textarea>
                                </div>
                            </div>
                            <div class="card-footer">
                                <button type="submit" class="btn btn-success"> Save </button>
                                <a href="{{ url('/') }}" class="btn btn-danger"> Back </a>
                            </div>
                        </div>
                    </div>
                </div>
            </form>
        </div>
        <script>
            ClassicEditor.create( document.querySelector( '#content' ) )
                .catch( error => {
                    console.error( error );
                } );
        </script>
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    </body>
</html>

Here, we have created a simple form which takes two input. First one is title and second is body part of post. We have also added CDN for CKEditor at header.

In the script part, we have initialized the CKEditor instance on text-area input by passing ID of input. It will convert normal text area into a Rich text editor using CKEditor plugin functionality.

Define Routes

In this step, we will define routes for posts. This route will handle user requests and deliver it to a specific controller and its method. In Laravel, All web routes must be added to a particular file routes/web.php. Although you can create a custom route file and bind it to your application.

Open the web routes file and update it accordingly:

<?php

use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;

Route::get('/', [PostController::class, "index"]);
Route::get("create", [PostController::class, "create"]);
Route::post('store', [PostController::class, "store"]);

Testing Application

For Running or Testing the CRUD application enter below command :

php artisan serve

It will produce output like below :

Starting Laravel development server: http://127.0.0.1:8000
PHP 7.4.6 Development Server (http://127.0.0.1:8000) started

Open your browser and go to below URL and test your application.

http://127.0.0.1:8000

In case, you are facing an issue while running application verify the CKEditor link or check the console for error logs.

Conclusion

In this article, we have created functionality to create post using CKEditor and display it using table. There are many useful methods and functionality of CKEditor which can be useful as Image upload, enabling or disabling some formatting functionality, showing HTML code based on user input, or many more.