Laravel 11 - CkEditor (Upload Images)
Laravel 11 - CkEditor (Upload Images)
In this tutorial, we will explore how to upload images using CKEditor in Laravel 11, enhancing content management with rich media integration.
If you're a video person, feel free to skip the post and check out the video instead!
Quick Overview
This guide walks you through setting up CKEditor with image upload functionality in a Laravel project. It begins by creating a fresh Laravel project and configuring it with MySQL and Pest for testing. You will then generate the Post model and migration, followed by creating the PostController to handle displaying posts, saving new posts, and managing image uploads via CKEditor. Next, routes are defined to connect the frontend with the controller methods, and the Blade view is updated to include a CKEditor form for rich text editing and image uploads. After creating a storage symlink for public file access, you will test the functionality by starting the Laravel development server and verifying image uploads through CKEditor. This integration enables smooth handling of both text and media within your Laravel application.
Step # 1 : Set Up a New Laravel Project.
Start by creating a new Laravel project or use an existing one. If Laravel is installed globally, run.
laravel new ckeditor
Otherwise, use Composer.
composer create-project laravel/laravel --prefer-dist ckeditor
During setup, make the following choices.
- Starter kit: None
- Testing framework: Pest
- Database: MySQL
- Run migrations: No
This will create a fresh Laravel project named ckeditor with Pest for testing, MySQL as the database, and no initial migrations. We'll handle the database setup in the next steps.
Step # 2 : Navigate to the Project Directory.
Open your terminal (e.g., Git Bash) and move into the root directory of your Laravel project. For example.
cd c:/xampp/htdocs/ckeditor
Make sure you're inside the project folder before running any Laravel commands.
Step # 3 : Create the Post Model and Migration.
Generate a new model along with its corresponding migration using.
php artisan make:model Post -m
Next, open the generated migration file (create_posts_table) and add a body column.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
//Add body column
$table->text('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Then, update the Post model to make the body field mass assignable.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'body',
];
}
Finally, run the migration to create the table.
php artisan migrate
This sets up a posts table with a body column and prepares the model for use in your application.
Step # 4 : Create the Post Controller.
Generate a controller using the following command.
php artisan make:controller PostController
Then, update the generated PostController with the following logic.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
use Illuminate\Support\Facades\Storage;
class PostController extends Controller
{
// Display all posts on the welcome page
public function index()
{
$posts = Post::all();
return view('welcome', compact('posts'));
}
// Store a new post in the database
public function store(Request $request)
{
$request->validate([
'body' => 'required',
]);
Post::create([
'body' => $request->body,
]);
// Redirect back to the previous page with a success message
return redirect()->back()->with('success', 'Post created successfully!');
}
// Handle image uploads for CKEditor
public function uploadImage(Request $request)
{
// Check if an image file is uploaded
if ($request->hasFile('upload')) {
$request->validate([
'upload' => 'image|mimes:jpeg,png,jpg,gif|max:2048',
]);
$path = $request->file('upload')->store('uploads', 'public');
// Get the publicly accessible URL of the uploaded image
$url = Storage::url($path);
// Return a JSON response indicating the image upload was successful, with the image URL
return response()->json([
'uploaded' => true,
'url' => $url,
]);
}
// If the image upload fails, return an error response
return response()->json(['uploaded' => false], 400);
}
}
This controller handles displaying all posts, saving new ones to the database, and processing image uploads from CKEditor. The index() method fetches all posts for display, store() validates and saves new posts, and uploadImage() manages file uploads by validating the image, storing it in the public directory, and returning a usable URL for CKEditor integration.
Step # 5 : Define Application Routes.
Open the web.php file and register your routes by importing the PostController and defining the necessary endpoints.
use App\Http\Controllers\PostController;
// Routes for displaying posts, storing new posts, and handling CKEditor image uploads
Route::get('/', [PostController::class, 'index']);
Route::post('/store', [PostController::class, 'store']);
Route::post('/upload/image', [PostController::class, 'uploadImage']);
These routes connect your frontend to the controller methods: the home route (/) displays all posts, /store handles form submissions for new posts, and /upload/image processes image uploads from CKEditor.
Step # 6 : Update the Blade View.
Edit the welcome.blade.php file to include a form for post submission and integrate CKEditor via CDN.
<!DOCTYPE html>
<html>
<head>
<title>Laravel 11 - CKEditor (Upload Image) - Code Shotcut</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- CKEditor CDN -->
<script src="https://cdn.ckeditor.com/ckeditor5/41.4.2/classic/ckeditor.js"></script>
</head>
<body>
<div class="container mt-5">
<form action="{{ url('store') }}" method="POST" enctype="multipart/form-data" class="mb-4">
@csrf
<div class="mb-3">
<label for="body" class="form-label">Body:</label>
<!-- Textarea for CKEditor -->
<textarea id="body" name="body" class="form-control"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<!-- Check if there are posts to display -->
@if($posts)
<div class="mt-5 p-4 bg-light border rounded">
<h1>All Posts</h1>
@foreach($posts as $post)
<div class="mb-3">
<strong>Post ID:</strong> {!! $post->id !!} <br>
{!! $post->body !!}
</div>
@endforeach
</div>
@endif
</div>
<!-- CKEditor configuration -->
<script>
ClassicEditor
.create(document.querySelector('#body'), {
ckfinder: {
uploadUrl: '{{ url("/upload/image").'?_token='.csrf_token() }}' // URL for image upload
}
})
.catch(error => {
console.error(error);
});
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
This view includes a simple Bootstrap-styled form using CKEditor for rich text editing, with support for image uploads. Submitted posts are displayed below the form, and the CKEditor is configured to send uploaded images to the /upload/image route, including the CSRF token for security.
Step 7 : Create the Storage Symlink.
Run the following Artisan command to create a symbolic link from public/storage to storage/app/public.
php artisan storage:link
This command ensures that any images uploaded by CKEditor (or other files stored publicly) are accessible through the browser. Without this link, uploaded files stored in Laravel’s storage/app/public directory wouldn’t be available via public URLs.
Step # 8 : It's time to test.
Now it's time to test everything. Start the Laravel development server with the following command.
php artisan serve
Next, open your browser and visit: 127.0.0.1:8000.
Once you're there, try uploading images through CKEditor to verify that everything is working correctly.


Conclusion
By following this guide, you've successfully integrated CKEditor into your Laravel application with image upload functionality. Your application is now equipped to handle rich text content along with media uploads, making it more dynamic and user-friendly. With CKEditor properly set up, you can easily manage text and images within posts, and the storage symlink ensures seamless access to uploaded images. Moving forward, you can customize CKEditor further, explore additional features, and integrate other tools to enhance your application’s capabilities.
For more details on CKEditor configuration and usage, refer to the official CKEditor documentation.
For more details on CKEditor configuration and usage, refer to the official CKEditor documentation.
Share this with friends!
To engage in commentary, kindly proceed by logging in or registering
Subscribe to Our Newsletter
Stay ahead of the curve! Join our newsletter to see what everyone’s talking about.
0 Comments