Hướng dẫn
Quảng cáo

Tích hợp TinyMCE trong PHP & MySQL bằng Ajax

Mỗi dự án PHP thường cần sử dụng trình soạn thảo như TinyMCE, CKEditor ... Bài này hướng dẫn cách tích hợp trình soạn thảo TinyMCE vào PHP bằng Ajax.

Trước đây về TinyMCE mình đã có hướng dẫn qua về TinyMCE textarea và biểu mẫu (Form) đăng bằng ajax. Trong bài viết này mình sẽ hướng dẫn chi tiết từng bước để tích hợp TinyMCE vào trong dự án PHP: Cách lưu dữ liệu lấy được từ trình soạn thảo TinyMCE vào MySQL bằng Ajax. Nào chúng ta cùng đi xem từng bước nhé

Bước 1: Tạo cơ sở dữ liệu lưu trữ thông tin bài viết

Bạn cần tạo một CSDL trong đó có một bảng posts để lưu trữ thông tin bài viết như Tiêu đề, Nội dung. Bạn có thể dùng mã SQL như bên dưới để tạo bảng posts

Ví dụ

CREATE TABLE `posts` (
  `id` int(11) NOT NULL,
  `title` varchar(150) NOT NULL,
  `content` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `posts`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `posts`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
COMMIT;

Bước 2: Tạo tệp tinh save.php để lưu thông tin bài viết

Để lưu thông tin bài viết qua Ajax bạn cần sử dụng tệp tin PHP để kết nối tới CSDL và thực hiện hành động lưu dữ liệu, nội dung tệp save.php như bên dưới:

Ví dụ

<?php

$host     = 'localhost';
$db       = 'demophp';
$user     = 'root';
$password = '';

$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";

try {
     $conn = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

} catch (PDOException $e) {
     echo $e->getMessage();
}

$sql = 'INSERT INTO posts(title, content) VALUES(:title, :content)';

$statement = $conn->prepare($sql);

$statement->execute([
     ':title' => $_REQUEST['title'],
     ':content' => $_REQUEST['content']
]);

echo "Đăng bài viết thành công!";

Bước 3: Tạo tệp tin HTML với mã TinyMCE Javasctipt và Ajax

Dưới đây là đoạn mã hoàn chỉnh về cách lưu nội dung TinyMCE vào PHP & MySQL với Ajax

Ví dụ

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Tích hợp TinyMCE trong PHP & MySQL bằng Ajax</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>

    <script type="text/javascript">
        tinymce.init({
            selector: 'textarea#tinymce',
            plugins: [
                "advlist autolink lists link image charmap print preview anchor",
                "searchreplace visualblocks code fullscreen",
                "insertdatetime media table paste codesample"
            ],
            toolbar:
                "undo redo | fontselect styleselect fontsizeselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | codesample action section button | custom_button",
            // content_css: [window.location.origin+"/assets/css/custom_css_tinymce.css"],/*Tùy chọn thêm vào css tùy chỉnh cho tinymce của bạn, như: Định dạng trích dẫn, danh sách ... giống với cách hiển thị trên website*/
            font_formats:"Segoe UI=Segoe UI;",
            fontsize_formats: "8px 9px 10px 11px 12px 14px 16px 18px 20px 22px 24px 26px 28px 30px 32px 34px 36px 38px 40px 42px 44px 46px 48px 50px 52px 54px 56px 58px 60px 62px 64px 66px 68px 70px 72px 74px 76px 78px 80px 82px 84px 86px 88px 90px 92px 94px 94px 96px",
            codesample_languages: [
                {text: 'HTML/XML', value: 'markup'},
                {text: 'JavaScript', value: 'javascript'},
                {text: 'CSS', value: 'css'},
                {text: 'PHP', value: 'php'},
                {text: 'Ruby', value: 'ruby'},
                {text: 'Python', value: 'python'},
                {text: 'Java', value: 'java'},
                {text: 'C', value: 'c'},
                {text: 'C#', value: 'csharp'},
                {text: 'C++', value: 'cpp'}
            ],
            height: 600,
            setup: function (editor) {
                editor.ui.registry.addButton('custom_button', {
                    text: 'Add Button',
                    onAction: function() {
                        // Open a Dialog
                        editor.windowManager.open({
                            title: 'Add custom button',
                            body: {
                                type: 'panel',
                                items: [{
                                    type: 'input',
                                    name: 'button_label',
                                    label: 'Button label',
                                    flex: true
                                },{
                                    type: 'input',
                                    name: 'button_href',
                                    label: 'Button href',
                                    flex: true
                                },{
                                    type: 'selectbox',
                                    name: 'button_target',
                                    label: 'Target',
                                    items: [
                                        {text: 'None', value: ''},
                                        {text: 'New window', value: '_blank'},
                                        {text: 'Self', value: '_self'},
                                        {text: 'Parent', value: '_parent'}
                                    ],
                                    flex: true
                                },{
                                    type: 'selectbox',
                                    name: 'button_rel',
                                    label: 'Rel',
                                    items: [
                                        {text: 'No value', value: ''},
                                        {text: 'Alternate', value: 'alternate'},
                                        {text: 'Help', value: 'help'},
                                        {text: 'Manifest', value: 'manifest'},
                                        {text: 'No follow', value: 'nofollow'},
                                        {text: 'No opener', value: 'noopener'},
                                        {text: 'No referrer', value: 'noreferrer'},
                                        {text: 'Opener', value: 'opener'}
                                    ],
                                    flex: true
                                },{
                                    type: 'selectbox',
                                    name: 'button_style',
                                    label: 'Style',
                                    items: [
                                        {text: 'Success', value: 'success'},
                                        {text: 'Info', value: 'info'},
                                        {text: 'Warning', value: 'warning'},
                                        {text: 'Error', value: 'error'}
                                    ],
                                    flex: true
                                }]
                            },
                            onSubmit: function (api) {

                                var html = '<a href="'+api.getData().button_href+'" class="btn btn-'+api.getData().button_style+'" rel="'+api.getData().button_rel+'" target="'+api.getData().button_target+'">'+api.getData().button_label+'</a>';

                                // insert markup
                                editor.insertContent(html);

                                // close the dialog
                                api.close();
                            },
                            buttons: [
                                {
                                    text: 'Close',
                                    type: 'cancel',
                                    onclick: 'close'
                                },
                                {
                                    text: 'Insert',
                                    type: 'submit',
                                    primary: true,
                                    enabled: false
                                }
                            ]
                        });
                    }
                });
            }
        });

        $(document).ready(function() {
            $('#save-content-form').on('submit', function(e) {
                e.preventDefault();

                var data = $('#save-content-form').serializeArray();
                data.push({name: 'content', value: tinyMCE.get('tinymce').getContent()});

                $.ajax({
                    type: 'POST',
                    url: window.location.origin+'/save.php',
                    data: data,
                    success: function (response, textStatus, xhr) {
                        console.log(response)
                    },
                    complete: function (xhr) {
                        
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        var response = XMLHttpRequest;

                    }
                }); 
            });
        });
    </script>
</head>
<body>
    <div class="container mt-5">
        <form method="post" id="save-content-form">
            <div class="form-group">
                <label>Tiêu đề</label>
                <input type="text" name="title" class="form-control">
            </div>
            <div class="form-group mt-4">
                <label>Nội dung</label>
                <textarea id="tinymce"></textarea>
            </div>
            
            <button class="btn btn-primary mt-4" type="submit">Đăng</button>
        </form>
    </div>
    
</body>
</html>

Nếu có thắc mắc gì trong quá trình sử dụng TinyMCE cho các dự án của mình các bạn có thể liên hệ lại với mình nhé, chúng ta sẽ cùng trao đổi.

Bài viết này đã giúp ích cho bạn?

Bài viết mới

Advertisements