How to implement Rich text editor in Laravel - Using CK Editor

How to implement CK Editor in Laravel

How to implement Rich text editor in Laravel - Using CK Editor


When building web applications, adding rich text editing features can significantly enhance user experience. Laravel, being a powerful PHP framework, allows for seamless integration of tools like CKEditor to enable rich text editing. CKEditor is a popular WYSIWYG (What You See Is What You Get) editor that lets users create and format content as they would in a word processor.

There are other alternatives of CKEditor and we will go through them in a separate article. CKEditor is one of the best and easy to use Rich text editor for Laravel.

In this article we will see how to implement CK Editor in Laravel with a example, where will integrate CK Editor, add our desired content and display the contents in a separate page.

Create your Route : 

Let's create the following route and here we will show a form and integrate our CKEditor there.

Route::get('/content-upload', [UserController::class, 'getCKEditor']);

UserController.php : 

public function getCKEditor(){
        return view('userContent');
    }

UserContent.blade.php : 

Let's integrate our form here along with CKEditor. To include CKEditor in your view file, include the following Script CDN.

<script src="https://cdn.ckeditor.com/ckeditor5/35.1.0/classic/ckeditor.js"></script>

Then you need to add some additional script to initialize the CKEditor and to handle image upload on that editor as shown in the below code snippet. In the script section you have to provide the id of the <textarea> on the script to initialize CKEditor on that specific input.

You need to create another api / route to handle image uploads, whenever any image is being uploaded on CKEditor that particular api will be triggered. you can refer the code below for better understanding.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>CKEditor</title>

        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    </head>
    <body class="font-sans antialiased dark:bg-black dark:text-white/50">
       <div class="container mt-5">
        <form method="post" action="/submit-content">
            @csrf
            <div class="mb-3">
              <label for="exampleInputPassword1" class="form-label">Write your content here</label>
              <textarea type="text" class="form-control" id="content" name="content"></textarea>
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
          </form>
       </div>
    </body>
        <script src="https://cdn.ckeditor.com/ckeditor5/35.1.0/classic/ckeditor.js"></script>
        <script>
            ClassicEditor
                .create(document.querySelector('#content'), {
                    ckfinder: {
                        uploadUrl: "{{ route('ckeditor.upload', ['_token' => csrf_token() ]) }}"
                    },
                    toolbar: [
                        'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'imageUpload', '|', 'undo', 'redo'
                    ]
                })
                .then(editor => {
                    window.editor = editor;
                })
                .catch(error => {
                    console.error(error);
                });
        </script>
        
</html>

As shown in the above code here the route and code snippet that handles image upload. Make sure the response structure is same as shown in below code snippet otherwise it might give you error.

Image upload route : 

Route::post('/upload-image', [UserController::class, 'uploadImage'])->name('ckeditor.upload');

Image upload code :

public function uploadImage(Request $request)
    {
        if($request->hasFile('upload')) {
            $originName = $request->file('upload')->getClientOriginalName();
            $fileName = pathinfo($originName, PATHINFO_FILENAME);
            $extension = $request->file('upload')->getClientOriginalExtension();
            $fileName = $fileName.'_'.time().'.'.$extension;

            $request->file('upload')->move(public_path('uploads'), $fileName);

            $url = asset('uploads/'.$fileName); 
            return response()->json([
                'url' => $url,
                'fileName' => $fileName,
                'uploaded' => 1
            ]);
        }
    }


Now your Rich Text editor is ready to use. Now we need to create a route that will save the content that is coming from CKEditor. You have to save it as it is in the database without any modification. For this i am not storing it in database but you can store it directly in database.

Route to submit form :

Route::post('/submit-content', [UserController::class, 'submitContent'])->name('submit.content');

Form submission code :

public function submitContent(Request $request){
        $content = $request->content;
        // You can add your additional code here to store content on database.
        // Make sure that you are storing the content as it is without any modification
        return view('showContent',compact('content'));
    }

Now here is the following View where we will show the content that is coming from CKEditor.

showContent.blade.php: 

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>CKEditor</title>

        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <style>
            img{
                height: 200px;
                width: 200px;
            }
        </style>
    </head>
    <body class="font-sans antialiased dark:bg-black dark:text-white/50">
       <div class="container mt-5">
        {!! $content !!}
       </div>
    </body>
        
</html>

Working Demo : 


Thank you for reading this article 😊

For any query do not hesitate to comment 💬


Previous Post Next Post

Contact Form