CKEditor 5 在 PHP 项目中的完整使用教程
CKEditor 5 是一个功能强大、现代化的富文本编辑器,它不再是传统的全局变量模式,而是基于 ES6 模块构建的,这使得集成方式与旧版 CKEditor 4 有所不同。

本教程将涵盖以下核心内容:
- 环境准备:搭建 PHP 开发环境。
- 下载与集成:获取 CKEditor 5 并将其集成到你的 PHP 页面中。
- 基本配置:自定义工具栏、语言等。
- 核心功能:文件上传:配置 CKEditor 5 上传图片到服务器。
- 后端处理:编写 PHP 脚本接收并保存上传的文件。
- 数据保存与显示:如何将编辑器内容安全地存入数据库并安全地显示在页面上。
- 进阶配置:自定义内容过滤等。
第一步:环境准备
你需要一个支持 PHP 的 Web 服务器环境,最简单的方式是使用集成环境包:
- XAMPP (Windows, macOS, Linux)
- WAMP (Windows)
- MAMP (macOS)
确保你的环境已经启动,Apache 和 MySQL 服务都在运行。
第二步:下载与集成 CKEditor 5
我们将使用 CKEditor 5 的 "经典编辑器" 版本,因为它最接近传统编辑器的体验。

下载 CKEditor 5
访问 CKEditor 5 下载页面,选择 "Classic editor",然后点击 "Download",你会得到一个 ZIP 压缩包。
解压并放置文件
将下载的 ZIP 包解压,你会得到一个名为 ckeditor 的文件夹,我们将这个文件夹复制到你的 PHP 项目根目录下。
你的项目结构现在看起来应该像这样:
/my-php-project/
├── ckeditor/ <-- 从官网下载的 CKEditor 5 文件夹
│ ├── build/
│ ├── lang/
│ ├── samples/
│ └── ...
├── uploads/ <-- 我们稍后会创建这个文件夹,用于存放上传的图片
├── save_data.php <-- 用于接收和处理编辑器数据的 PHP 文件
└── index.php <-- 包含编辑器的页面
在 PHP 页面中引入 CKEditor 5
打开你的 index.php 文件,我们需要引入 CKEditor 5 的 JavaScript 和 CSS 文件。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">CKEditor 5 PHP 教程</title>
<!-- 1. 引入 CKEditor 5 的 CSS 文件 -->
<link rel="stylesheet" href="ckeditor/contents.css">
<!-- 2. 引入 CKEditor 5 的核心 JavaScript 文件 -->
<!-- 注意:这里我们使用 build/ckeditor.js -->
<script src="ckeditor/build/ckeditor.js"></script>
</head>
<body>
<h1>CKEditor 5 PHP 集成示例</h1>
<!-- 3. 创建一个 textarea 元素,作为编辑器的容器 -->
<!-- CKEditor 5 会将这个 textarea 替换成一个功能完整的编辑器 -->
<form action="save_data.php" method="post">
<textarea name="editor_content" id="editor"></textarea>
<br><br>
<button type="submit">保存内容</button>
</form>
<!-- 4. 在页面底部编写初始化脚本 -->
<script>
// 使用 ClassicEditor 初始化编辑器
// 'editor' 是上面 textarea 的 id
ClassicEditor
.create(document.querySelector('#editor'), {
// 配置选项将在这里添加
})
.then(editor => {
console.log('编辑器已初始化', editor);
})
.catch(error => {
console.error('初始化编辑器时出错', error);
});
</script>
</body>
</html>
在浏览器中打开 index.php,你应该能看到一个功能齐全的富文本编辑器了!
第三步:基本配置
让我们对编辑器做一些简单的自定义,比如设置语言和工具栏。
在 index.php 的 ClassicEditor.create() 中添加配置对象:
<script>
ClassicEditor
.create(document.querySelector('#editor'), {
// 语言配置
language: 'zh-cn', // 或者 'zh'
// 工具栏配置
toolbar: {
items: [
'heading', '|',
'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|',
'outdent', 'indent', '|',
'blockQuote', 'insertTable', 'undo', 'redo'
]
}
})
.then(editor => { /* ... */ })
.catch(error => { /* ... */ });
</script>
刷新页面,你会看到工具栏和界面都变成了中文,并且只显示了你配置的那些按钮,你可以根据需要从 官方文档 中查找更多配置项。
第四步:核心功能 - 配置文件上传
这是整个教程中最关键的一步,我们需要让 CKEditor 5 能够将图片上传到我们服务器的 uploads 目录。
创建上传目录
在你的项目根目录下创建一个名为 uploads 的文件夹,并确保 Web 服务器(如 Apache 的 www-data 用户)对该目录有写入权限。
在 Linux/macOS 上,你可以执行:
sudo chown -R www-data:www-data /path/to/your/my-php-project/uploads sudo chmod -R 755 /path/to/your/my-php-project/uploads
在编辑器配置中添加上传适配器
修改 index.php 中的 ClassicEditor.create() 配置,添加一个 simpleUpload 适配器。
<script>
ClassicEditor
.create(document.querySelector('#editor'), {
// ... 其他配置 ...
language: 'zh-cn',
toolbar: { /* ... */ },
// 新增的文件上传配置
simpleUpload: {
// 上传服务器的 URL
uploadUrl: 'upload.php',
// 可选:携带到请求头中的信息,CSRF Token
// headers: {
// 'X-CSRF-Token': 'CSRF_TOKEN_VALUE'
// }
}
})
.then(editor => { /* ... */ })
.catch(error => { /* ... */ });
</script>
配置说明:
uploadUrl: 指向一个处理文件上传的 PHP 脚本的 URL,我们接下来会创建这个脚本。
处理上传请求:创建 upload.php
在项目根目录下创建 upload.php 文件,这个脚本将接收文件、验证它、保存它,并返回一个 JSON 响应给 CKEditor 5。
<?php
// upload.php
// 设置响应头为 JSON
header('Content-Type: application/json');
// --- 1. 配置 ---
$uploadDir = __DIR__ . '/uploads/'; // 上传目录
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif']; // 允许的文件类型
$maxSize = 5 * 1024 * 1024; // 最大文件大小 (5MB)
// --- 2. 创建上传目录(如果不存在) ---
if (!file_exists($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
// --- 3. 处理上传 ---
$response = [
'default' => $uploadDir // 给 CKEditor 一个默认路径
];
if (isset($_FILES['upload']) && $_FILES['upload']['error'] === UPLOAD_ERR_OK) {
$file = $_FILES['upload'];
$fileName = $file['name'];
$fileTmpName = $file['tmp_name'];
$fileSize = $file['size'];
$fileType = $file['type'];
// --- 4. 验证 ---
// 验证文件类型
if (!in_array($fileType, $allowedTypes)) {
http_response_code(415); // Unsupported Media Type
echo json_encode(['error' => '不支持的文件类型。']);
exit;
}
// 验证文件大小
if ($fileSize > $maxSize) {
http_response_code(413); // Payload Too Large
echo json_encode(['error' => '文件太大。']);
exit;
}
// --- 5. 生成安全的文件名并移动文件 ---
// 获取文件扩展名
$fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
// 生成唯一文件名
$newFileName = uniqid('img_', true) . '.' . $fileExtension;
$destination = $uploadDir . $newFileName;
if (move_uploaded_file($fileTmpName, $destination)) {
// --- 6. 返回成功响应 ---
// CKEditor 5 期望的响应格式
echo json_encode([
'url' => 'uploads/' . $newFileName // 返回文件的相对 URL
]);
exit;
} else {
http_response_code(500); // Internal Server Error
echo json_encode(['error' => '文件移动失败。']);
exit;
}
} else {
// --- 7. 处理错误 ---
$error = '上传失败。';
if (isset($_FILES['upload']['error'])) {
switch ($_FILES['upload']['error']) {
case UPLOAD_ERR_INI_SIZE:
$error = '上传的文件超过了 php.ini 中 upload_max_filesize 指令限制的值。';
break;
case UPLOAD_ERR_FORM_SIZE:
$error = '上传文件的大小超过了 HTML 表单中指定的 MAX_FILE_SIZE。';
break;
case UPLOAD_ERR_PARTIAL:
$error = '文件只有部分被上传。';
break;
case UPLOAD_ERR_NO_FILE:
$error = '没有文件被上传。';
break;
}
}
http_response_code(400); // Bad Request
echo json_encode(['error' => $error]);
exit;
}
?>
upload.php 的工作流程:
- 设置响应头为
application/json。 - 定义上传目录、允许的文件类型和最大大小。
- 检查
$_FILES数组中是否有名为upload的文件(CKEditor 5 默认使用这个字段名)。 - 验证文件类型和大小,确保安全性。
- 生成一个唯一的文件名(避免文件名冲突和覆盖),然后将文件从临时目录移动到
uploads目录。 - 如果成功,返回一个包含
url字段的 JSON 对象,CKEditor 5 会用这个 URL 来显示图片。 - 如果失败,返回一个包含
error字段的 JSON 对象,并设置相应的 HTTP 状态码。
回到 index.php,尝试点击编辑器中的图片上传按钮,你应该可以选择一张图片并成功上传到 uploads 目录。
第五步:数据保存与显示
现在编辑器可以用了,我们来处理用户编辑后的内容。
创建 save_data.php
这个脚本会接收 index.php 表单提交的数据,并将其保存到数据库或文件中。
假设我们使用 MySQL 数据库:
创建一个数据库和一张表:
CREATE DATABASE ckeditor_db; USE ckeditor_db; CREATE TABLE `posts` ( `id` INT AUTO_INCREMENT PRIMARY KEY, VARCHAR(255) NOT NULL, `content` TEXT NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
创建 save_data.php:
<?php
// save_data.php
// 数据库连接信息 (请替换成你自己的)
$host = 'localhost';
$dbname = 'ckeditor_db';
$user = 'root'; // 你的数据库用户名
$pass = ''; // 你的数据库密码
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$dbname;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// 获取表单提交的数据
$title = $_POST['title'] ?? '无标题'; // 假设你有一个 title 输入框
$content = $_POST['editor_content'] ?? '';
// 准备 SQL 语句
$sql = "INSERT INTO posts (title, content) VALUES (:title, :content)";
$stmt = $pdo->prepare($sql);
// 绑定参数并执行
$stmt->execute([
':title' => $title,
':content' => $content
]);
echo "内容已成功保存!<br>";
echo "<a href='view_post.php?id=" . $pdo->lastInsertId() . "'>查看文章</a>";
?>
注意:这个例子假设你的表单中还有一个 title 字段,如果没有,你可以去掉它。
安全地显示内容:创建 view_post.php
直接从数据库输出 HTML 内容是极其危险的,因为它可能导致 Cross-Site Scripting (XSS) 攻击,CKEditor 5 的内容可能包含 <script> 标签等恶意代码。
为了安全地显示内容,我们应该使用 PHP 的 strip_tags() 函数来移除所有 HTML 标签,或者使用更复杂的 HTML Purifier 库来净化内容。
简单移除所有 HTML (不推荐,会丢失格式)
<?php
// view_post.php (不安全示例)
$id = $_GET['id'] ?? 1;
$pdo = new PDO("mysql:host=localhost;dbname=ckeditor_db;charset=utf8mb4", "root", "");
$stmt = $pdo->prepare("SELECT * FROM posts WHERE id = ?");
$stmt->execute([$id]);
$post = $stmt->fetch();
// !!! 危险 !!! 直接输出未经处理的 HTML
echo "<h1>" . htmlspecialchars($post['title']) . "</h1>";
echo "<div>" . $post['content'] . "</div>"; // 这行代码是 XSS 漏洞
?>
安全地显示内容 (推荐)
最佳实践是使用一个专门的库来净化 HTML,HTML Purifier。
-
安装 HTML Purifier: 最简单的方式是通过 Composer:
composer require ezyang/htmlpurifier
-
创建
view_post.php(安全版本):<?php // view_post.php (安全示例) require_once 'vendor/autoload.php'; // 引入 Composer 的自动加载器 use HTMLPurifier_Config; use HTMLPurifier; // 数据库连接 (同上) $id = $_GET['id'] ?? 1; $pdo = new PDO("mysql:host=localhost;dbname=ckeditor_db;charset=utf8mb4", "root", ""); $stmt = $pdo->prepare("SELECT * FROM posts WHERE id = ?"); $stmt->execute([$id]); $post = $stmt->fetch(); if (!$post) { die("文章未找到。"); } // 配置并创建 HTML Purifier 实例 $config = HTMLPurifier_Config::createDefault(); // 允许的 HTML 标签和属性 $config->set('HTML.Allowed', 'p,b,i,u,a[href|title],ul,ol,li,br,strong,em,div,span[style],img[src|alt|style],table,thead,tbody,tr,th,td'); // 允许的 CSS 样式 (为了安全,只允许特定样式) $config->set('CSS.AllowedProperties', 'text-align, float'); $config->set('URI.AllowedSchemes', [ 'http' => true, 'https' => true, // 'data' => true, // 不允许内嵌的 base64 图片 ]); $purifier = new HTMLPurifier($config); // 净化从数据库获取的内容 $clean_html = $purifier->purify($post['content']); // 安全地输出 ?> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title><?php echo htmlspecialchars($post['title']); ?></title> </head> <body> <h1><?php echo htmlspecialchars($post['title']); ?></h1> <div> <?php echo $clean_html; // 输出净化后的 HTML ?> </div> </body> </html>
当你保存内容后,点击“查看文章”,你就能看到格式良好的、安全的 HTML 内容了。
总结与进阶
恭喜!你已经成功地在 PHP 项目中集成了 CKEditor 5,并实现了完整的内容编辑、上传、保存和显示流程。
回顾关键点:
- 引入方式:通过
<script src="ckeditor/build/ckeditor.js">引入,并在页面底部用ClassicEditor.create()初始化。 - 配置:在
create()函数的第二个参数中传入配置对象。 - 文件上传:通过
simpleUpload.uploadUrl指向一个自定义的 PHP 处理脚本 (upload.php)。 upload.php:负责接收文件、验证、保存,并返回 JSON 响应。- 数据安全:永远不要直接输出用户提交的 HTML,使用
strip_tags()或更强大的 HTML Purifier 来净化内容,防止 XSS 攻击。
进阶学习方向:
- 自定义插件:学习如何创建自己的 CKEditor 5 插件,添加特殊功能。
- 内容过滤:深入研究
editor.config中的ckbox或contentSecurityPolicy等高级配置,以实现更精细的内容控制。 - API 集成:CKEditor 5 支持通过 API 与后端服务交互,可以实现更复杂的业务逻辑。
希望这份详细的教程能帮助你顺利地在项目中使用 CKEditor 5!
