Table of contents

tinymce in php

In this post, I'm sharing how to integrate or implement TinyMCE in PHP & MySQL using ajax. In my previous tutorials, I shared the basics about TinyMCE now let's talk about how to save the data in the database using PHP & MySQL via ajax request.


I will give you a step-by-step process on saving TinyMCE content in PHP & MySQL and integrate it into your project.


Step 1: Create your database

You will need to create your database first in any name you want. Just open your command prompt and do the process using MySQL command for easier just use PHPMyAdmin if you have installed it already at your localhost.


Step 2: Create a table

Then run this SQL named "posts" table.

CREATE TABLE `posts` (
  `id` int(11) NOT NULL,
  `title` varchar(150) NOT NULL,
  `content` text NOT NULL




Step 3: Create file save.php

This process will save your content via ajax request. See the following code:


$host     = 'localhost';
$db       = 'demos';
$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);

     ':title' => $_REQUEST['title'],
     ':content' => $_REQUEST['content']

echo "Post saved successfully!";


Step 4: Create our HTML file with TinyMCE javascript code and ajax

Below is the complete code on saving TinyMCE content to PHP & MySQL with an ajax request.

<!DOCTYPE html>
	<meta charset="utf-8">
	<title>Integrate TinyMCE in PHP & MySQL Using Ajax</title>

	<link rel="stylesheet" href="">
    <script src=""></script>
	<script type="text/javascript" src="assets/plugins/tinymce/js/tinymce.min.js"></script>

	<script type="text/javascript">
	        selector: 'textarea#tinymce',
	        plugins: [
                "advlist autolink lists link image charmap print preview anchor",
                "searchreplace visualblocks code fullscreen",
                "insertdatetime media table paste codesample"
                "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"],
	        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
	                        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

	                            // close the dialog
	                        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) {

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

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

	<div class="container mt-5">
		<form method="post" id="save-content-form">
			<div class="form-group">
				<input type="text" name="title" class="form-control">
			<div class="form-group mt-4">
				<textarea id="tinymce"></textarea>
			<button class="btn btn-primary mt-4" type="submit">Submit</button>


That's pretty much it. I hope it helps. Thank you for reading :)