guideLaravel

本指南介绍了在 Laravel 应用程序中集成 CKBox。如果您想直接跳转到代码,您可以在 GitHub 上找到本指南中描述的 完整应用程序代码

# 先决条件

在我们开始之前,请确保您已经在系统中安装了 composer。如果命令行中没有此工具,请先按照 Composer 的安装说明 进行操作。

# 创建应用程序

作为示例的基础,我们将使用 Composer 的 create-project 命令创建一个新的 Laravel 项目

composer create-project laravel/laravel ckbox-laravel-example

项目创建后,您可以进入目录并启动开发服务器

cd ckbox-laravel-example
php artisan serve

该应用程序将可通过 http://127.0.0.1:8000 访问。

# 创建控制器

首先,让我们创建一个控制器。该控制器将包含两个操作:一个用于显示示例的 HTML 内容,另一个用于提供令牌 URL,用于在 CKBox 中对用户进行身份验证。

# 令牌 URL

CKBox,与其他 CKEditor 云服务一样,使用 JWT 令牌进行身份验证和授权。所有这些令牌都在您的应用程序端生成,并使用您可以在 CKEditor 生态系统仪表板 中获取的共享密钥进行签名。有关如何创建访问凭据的信息,请参阅 CKEditor 云服务身份验证指南 中的“创建访问凭据”文章。

现在我们有了所需的访问凭据,即:环境 ID 和访问密钥,让我们创建令牌端点。作为基础,我们将使用 PHP 中的通用令牌端点 的代码。

首先,让我们安装 firebase/php-jwt 库来创建 JWT 令牌

composer require firebase/php-jwt

作为基础,我们将使用 PHP 中的通用令牌端点 的代码。让我们将 PHP 令牌端点逻辑封装在 Laravel 操作中,并使用 CKBox 所需的负载 生成令牌。

# 完整的控制器代码

// app/Http/Controllers/CKBoxExampleController.php

namespace App\Http\Controllers;

use \Firebase\JWT\JWT;
use Illuminate\Http\Response;
use Illuminate\View\View;

class CKBoxExampleController extends Controller
{
    /**
     * Show the CKBox example.
     */
    public function show(string $example = null): View
    {
        if (in_array($example, ['ckeditor', 'modal', 'full-page'])) {
            return view('ckbox-example-' . $example);
        }

        return view('ckbox-example-list');
    }

    /**
     * Create CKBox JWT token.
     */
    public function token(): Response
    {
        $environmentId = env('CKBOX_ENVIRONMENT_ID');
        $accessKey = env('CKBOX_ACCESS_KEY');

        $payload = [
            'aud' => $environmentId,
            'iat' => time(),
            'sub' => 'unique-user-id', // Unique user ID in your application
            'auth' => [
                'ckbox' => [
                    'role' => 'superadmin',
                ]
            ]
        ];

        $jwtToken = JWT::encode($payload, $accessKey, 'HS256');

        return new Response($jwtToken);
    }
}

如上面的代码清单所示,签名 JWT 令牌所需的访问凭据是从环境变量中获取的。这样一来,您可以方便地将它们添加到 .env 文件中

# .env
CKBOX_ENVIRONMENT_ID=REPLACE-WITH-ENVIRONMENT-ID
CKBOX_ACCESS_KEY=REPLACE-WITH-ACCESS-KEY

现在,让我们注册所需的路由

// routes/web.php

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

Route::get('/ckbox/token', [CKBoxExampleController::class, 'token'])->name('ckbox_token');
Route::get('/{example?}', [CKBoxExampleController::class, 'show'])->name('ckbox_example');

# 将 CKBox 脚本添加到页面

CKBox 可以通过 多种方式 嵌入到应用程序中。为了简单起见,在我们的示例中,我们将使用从 CDN 提供的 CKBox 脚本。

本指南中的示例将涵盖使用 CKBox 的三种常见场景

  • 与 CKEditor 集成的 CKBox
  • 用作对话框模式的文件选择器的 CKBox
  • 用作全页应用程序的 CKBox

为了避免代码重复,让我们准备一个包含 CKBox 脚本的基础 Blade 模板,我们将在所有三个示例中重复使用它

<!-- resources/views/ckbox-example-layout.blade.php -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <script src="https://cdn.ckbox.io/ckbox/2.5.1/ckbox.js"></script>
        @stack('head')
        <title>CKBox example</title>
    </head>
    <body>
    @yield('content')
    </body>
</html>

现在,让我们为三个示例添加视图。

# CKBox 与 CKEditor 5

在本示例中,我们将使用运行 CKEditor 5 的最快速便捷方式——从 CDN 提供。对于更高级的集成场景,请参阅 CKEditor 5 文档

让我们创建扩展我们在上一步中创建的布局的子视图

<!-- resources/views/ckbox-example-ckeditor.blade.php -->
@extends('ckbox-example-layout')

@push('head')
    <script type="importmap">
        {
            "imports": {
                "ckeditor5": "https://cdn.ckeditor.com/ckeditor5/42.0.0/ckeditor5.js",
                "ckeditor5/": "https://cdn.ckeditor.com/ckeditor5/42.0.0/"
            }
        }
    </script>
    <link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/42.0.0/ckeditor5.css" />
@endpush

@section('content')
    <textarea id="editor"><?php echo htmlspecialchars('<h1>Example</h1><p>Hello world</p>'); ?></textarea>

    <script type="module">
        import {
            ClassicEditor,
            CKBox,
            Essentials,
            Bold,
            Italic,
            Font,
            Paragraph
        } from 'ckeditor5';

        ClassicEditor
            .create( document.querySelector( '#editor' ), {
                plugins: [ CKBox, Essentials, Bold, Italic, Font, Paragraph ],
                ckbox: {
                    tokenUrl: 'https://your.token.url',
                    theme: 'lark'
                },
                toolbar: [
                    'ckbox', '|', 'undo', 'redo', '|', 'bold', 'italic', '|',
                    'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor'
                ],
            } )
            .catch( error => {
                console.error( error );
            } );
    </script>
@endsection

上面的示例包含一个从 CDN 提供的 预定义的 CKEditor 构建,其中包含所需的 CKBox 插件。然后,CKEditor 被配置为通过设置 ckbox 属性的所需参数来使用 CKBox。请注意,在 ckbox.tokenUrl 配置选项中,我们传递了之前步骤中创建的令牌端点的 URL,该 URL 将用于获取用于在 CKBox 中对用户进行身份验证的 JWT 令牌。

# CKBox 作为文件选择器

常见场景之一是使用 CKBox 作为文件选择器,用户可以在其中选择文件管理器中存储的文件之一。选择文件后,我们希望获取所选文件的相关信息,尤其是它们的 URL。这可以通过使用作为 CKBox 配置选项传递的 assets.onChoose 回调来实现

<!-- resources/views/ckbox-example-modal.blade.php -->
@extends('ckbox-example-layout')

@section('content')
    <input type="text" id="file-url"></input><button id="choose">Choose file</button>
    <div id="ckbox"></div>
    <script>
        document.getElementById('choose').addEventListener('click', function () {
            CKBox.mount(document.querySelector('#ckbox'), {
                tokenUrl: '{{ route('ckbox_token') }}',
                dialog: true,
                assets: {
                    // Callback executed after choosing assets
                    onChoose: (assets) => {
                        document.getElementById('file-url').value = assets[0].data.url;

                        assets.forEach((asset) => {
                            console.log(asset.data.url);
                        })
                    }
                }
            });
        });
    </script>
@endsection

# 全页模式下的 CKBox

要以全页模式启动 CKBox,您可以将其附加到 document.body 并调整所需的 CSS 样式

@extends('ckbox-example-layout')

@push('head')
    <style>
        html, body {
            margin: 0;
            padding: 0;
            height: 100vh;
        }
    </style>
@endpush

@section('content')
    <script>
        CKBox.mount(document.body, {
            tokenUrl: '{{ route('ckbox_token') }}'
        });
    </script>
@endsection

# 完整代码

您可以在 GitHub 上找到本指南中描述的 完整应用程序代码