Saving CKEditor data to MySQL Database

NOTICE: UPDATED TUTORIAL USING PDO INSTEAD OF THE DEPRECATED MYSQL_ METHOD CAN NOW BE FOUND AT https://manzwebdesigns.com/2013/07/17/save-retrieve-ckeditor-data-pdo-mysql/!

Yesterday, I needed to give a client a What-You-See-Is-What-You-Get (WYSIWYG) editor for a text-area.  So, I’m thinking, “ahhh, no problem, should take about 30 minutes…”  I figured I could just whip up some jquery that would call a PHP page to submit the CKEditor information to the database.

While that may have been possible, I decided to look into the CKEditor API documentation and found that there is an easier way.  You will also need the jquery.form plugin, which can be downloaded here. Let’s look at the code for the index.php file (I always use the PHP file type instead of htm* because I may need to insert some php code sometime… only for testing pages, though, not for production.

Here is the code for the homepage…

<!DOCTYPE html>
<html>
    <head>
        <title>Writer</title>
        <meta content="text/html; charset=utf-8" http-equiv="content-type" />
        <script type="text/javascript" src="ckeditor/ckeditor.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
        <script type="text/javascript" src="js/jquery.form.js"></script>
        <style>
            .cke_contents {
                height: 400px !important;
            }
        </style>
		<script type="text/javascript">
			$(document).ready(function() {
				CKEDITOR.replace( 'editor',
				{
					fullPage : true,
					uiColor : '#9AB8F3',
					toolbar : 'MyToolbar'
				});
			});
		</script>
    </head>
    <body>
        <form action="result.php" method="post">
            <textarea class="editor" id="editor" name="editor"></textarea>
			<div id="messages"></div>
        </form>
    </body>
</html>

Note that the only purpose for having the form element is to enable the save button, we will be saving this with jQuery, so there will not be an actual form submission.

In the javascript here, we are using the .replace() function from the API to replace the control whose ID is ‘editor’, then setting the editor to be the fullPage width, setting the color for the interface, and telling it to use a custom toolbar named ‘MyToolbar’.

If you haven’t already downloaded the ckeditor, you can get the latest here.  Extract the zipped (or tar-gzipped) file into the root of your site directory.

Now for the ckeditor plugin, open to the directory ‘ckeditor/plugins’ and create a new directory called ‘ajaxsave’ and, in that directory, create a new file called ‘plugin.js’.  Now let’s put the following code in that file:

CKEDITOR.plugins.add('ajaxsave',
    {
        init: function(editor)
        {
            var pluginName = 'ajaxsave';
            editor.addCommand( pluginName,
            {
                exec : function( editor )
                {
                    $.post("result.php", {
                        data : editor.getSnapshot()
                    } );
                },
                canUndo : true
            });
            editor.ui.addButton('Ajaxsave',
            {
                label: 'Save Ajax',
                command: pluginName,
                className : 'cke_button_save'
            });
        }
    });

Basically, what is happening is we are adding a command to a button known as ‘ajaxsave’ in the toolbar and telling it to post to the file “result.php” the data contained in the editor using the getSnapshot() function from the API.

Now I chose to only give a subset of commands available along with my newly created and defined “Ajax Save” button by modifying the “config.js” file for the CKEditor (found in /ckeditor/):

/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/

CKEDITOR.editorConfig = function( config )
{
    // Define changes to default configuration here. For example:
    // config.language = 'fr';
    // config.uiColor = '#AADC6E';

    config.uiColor = '#AADC6E';
    config.resize_enabled = false;

    config.toolbar = 'MyToolbar';

    config.toolbar_MyToolbar = [
        ['NewPage','Preview','Ajaxsave'],
        ['Cut','Copy','Paste','PasteText','PasteFromWord','-','Scayt'],
        ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
        ['Table','HorizontalRule','Smiley','SpecialChar'],
        '/',
        ['Styles','Format'],
        ['Bold','Italic','Strike'],
        ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
        ['Link','Unlink','Anchor'],
        ['Maximize','-','About']
    ];

    config.extraPlugins = 'ajaxsave';

};

For a complete list of all non-custom buttons, see the documentation at the bottom of this page for them.

Now to actually save it to the database.  Create a new PHP file, result.php, in the same directory as your index.php file and use the following code as a sample to insert the data into the database…

<?php
  $host   = 'localhost'; // alternatively, you can put '127.0.0.1' here
  $dbUser = 'root'; // I would never use root for a production
                    // user, but for a local installation, it is ok...
  $dbPass = '1234'; // or whatever it is set to be...

  $dbName = 'test'; // use your database name here
  $dbConn = mysql_connect($host, $dbUser, $dbPass)
                  or trigger_error(mysql_error(), E_USER_ERROR);
  mysql_select_db($dbName, $dbConn);

  /* Table:  messages
   * Fields: id      (INT, primary key, auto-increment)
   *         message (TEXT)
   */
  $sql = "INSERT INTO messages VALUES(NULL, '" . mysql_real_escape_string($_POST['data']) . "');";
  $queryResource = mysql_query($sql, $dbConn) or die(mysql_error());
?>

I hope this helps, please comment below!

Bud Manz
Owner – Manz Web Designs, LLC
https://manzwebdesigns.com/

63 thoughts on “Saving CKEditor data to MySQL Database”

  1. Hi,

    Excellent post. Very clear and seemingly simple. Except I can’t get the custom button to show up. I am using CKE 3.6.2 in Firefox 7. I know the docs are really, really poor but I would think I could at least get the icon to show up. Did you have any problems initializing the plugin?

    Thanks again!

  2. Hi Todd,

    Thanks, I try to write my tutorials so they can be understood. Make sure that this section in your config.js file looks has ‘Ajaxsave’ in it:

    config.toolbar_MyToolbar = [
    [‘NewPage’,’Preview’,’Ajaxsave’],

    and later in the file, you need to make sure that the editor is aware of the new button:

    config.extraPlugins = ‘ajaxsave’;

    Other than that, I would need to see your code to determine why it is not showing up.

    HTH,
    Bud

  3. Actually, I finally got the button to appear. I do appreciate your help thought! If not for your article, I might still be banging my head!

    I had to call extraPlugins from within the CKEDITOR.replace() method call. Once I did that I was able to setup the plugin to use my Prototype-specific method of pushing the data. In case you or anybody else may be interested, here’s my plugin.js for Prototype.

    CKEDITOR.plugins.add(‘ajaxsave’, { init: function(editor) { var pluginName = ‘ajaxsave’;

    editor.addCommand( pluginName,
    {
    exec : function( editor )
    {
    new Ajax.Request(‘ajaxsave.php’,
    {
    method: “POST”,
    parameters: { filename: ‘index.html’, editor: editor.getData() },
    onFailure: function() { ThrowError(“Error: The server has returned an unknown error”); },
    on0: function() { ThrowError(‘Error: The server is not responding. Please try again.’); },
    onSuccess: function(transport) {

    var resp = transport.responseText;

    //Successful processing by ckprocess.php should return simply ‘OK’.
    if(resp == “OK”) {
    //This is a custom function I wrote to display messages. Nicer than alert()
    ShowPageMessage(‘Changes have been saved successfully!’);
    } else {
    ShowPageMessage(resp,’10’);
    }
    }
    });
    },

    canUndo : true
    });

    editor.ui.addButton(‘ajaxsave’,
    {
    label: ‘Save’,
    command: pluginName,
    className : ‘cke_button_save’
    });
    }

    });

  4. Sounds Great, glad I was a help to you! And thanks for posting your solution, I appreciate it! I haven’t messed with prototype, but have heard good things about it… I am a jQuery guy, myself 🙂

    Bud

  5. Thank you so much for this! Works perfect. I’m starting a project that uses ckeditor and will be needing to populate mysql with this user entered data. You’ve saved me so much time, thank you.

  6. Hi Bud,

    I like you tutorials it seems like it’s all in post is related to JQuery. To me JQuery is very difficult to understand. I can’t seem to see the data in the result.php. I think the issue is

    $.post(“result.php”, {data : editor.getSnapshot()} );

    Do I need to link the API to see the data in the result.php?

    I just want to say “Thanks” for the tutorial!

    1. Hi,

      Thank you! I am glad I can help!

      In your file structure, is result.php in the same directory as the page that you are instantiating the ckeditor? It should be.

      HTH,
      Bud

  7. Hi Bud,

    Thanks for replying back. I appreciated your help.

    Is this what you meant same directory:

    I create a folder called “New” and I put the “ckeditor” folder, “js” folder, result.php and index.php in it and I upload it to my server.

          1. Hi Bud,

            Sorry for the confusion. It’s the first post. You haven’t change the link on my first post. which is on:

            July 6, 2012 at 5:56 pm

            Hi Bud,

            Yes, I created the database and table. I also created the login credential too in the result.php. I don’t why when I type something and click on the ‘ajaxsave’ button. Then I open the link: http://xxxxxxxxxxxxxxxxx/New/result.php to see the results and I don’t see anything.

            – Mitt

          1. Hi Bud,

            Yes, there is data in the table!! Wow, this example code you wrote works. It’s take a lot patience to think and write this example. More power to you! I will move on to the next lesson on “Posting MySQL data back to the CKEditor instance” Thanks

  8. Hi Bud

    I’m not good a web developer I’m just learning. I’m really sorry for typing that address. I meant not type my website. I never used wordpress. I don’t know to do now.

  9. Hi Bud, first off, broken record here but awesome post! So helpful. Question. I need to send another piece of data along with the text that is saved so that I can track what is being placed in the DB. something to the effect of adding another field in the table like “docType” then sending a value to result.php in addition to the text so I can put it in the DB.

    I thought of trying to send the data thru a url, but since the form only enables the save button that won’t work. I did go into the plugin and when I did this:

    {
    $.post(“result.php?doctype=5”, {
    data : editor.getSnapshot()
    } );
    },

    That was passed into result.php and I was able to add $doctype to the db. So in a nutshell, is there a way I can get a value from the main index.php into the plugin so I can use that value? Or some other clever way I can get a variable value into result.php so I can insert it into the DB along with the main text?

    Thanks!

  10. Day 2: still cant figure out the redirect…I believe it would have something to do with a onclick(event) such as:

    function onClick(event)
    {
    window.location = “index.html”;
    }

    But I cant figure out where to put it, if someone knows, I would sure appreciate it!

        1. Thanks so much! I’m still working on this, I’m by no means a pro at it, but can usually work my way though this kind of code, I’ve tried so many different combos with still no luck. I did add a input button and was getting it to post and redirect the url though the results.php…But I know there has to be a better way of doing it! Thanks!

          1. My last post I was referring to:

            for some reason it didn’t show all my code…I just know that this isn’t the best way of doing it and would really like to try and add the redirect after the save it pressed 🙂

          2. Hi Mitt,

            Life has been a little crazy and I apologize for the late response! Are you still needing help with this?

            You need to know that the post is happening here:
            [code]
            {
            $.post(“result.php?, {
            data : editor.getSnapshot()
            } );
            },
            [/code]

            if you want to redirect after you could do it in the result.php file using the header function (check out the php.net site).

            Please let me know if you need more help!

            Bud

  11. Sorry, I should have known not to post php code…

    In an attempt to get the page to refresh (and post the updated content), I added the following to the result.php page:

    include ‘includes/config.inc.php’;
    $referral = $_SERVER[“HTTP_REFERER”];
    $info = pathinfo($referral);
    $table = basename($referral,’.’.$info[‘extension’]);
    $table = $table.”_text”;
    $dbConn = mysql_connect($host, $dbUser, $dbPass) or trigger_error(mysql_error(), E_USER_ERROR);
    mysql_select_db($dbName, $dbConn);
    $sql = “INSERT INTO “.$table.” VALUES(NULL, ‘” . mysql_real_escape_string($_POST[‘data’]) . “‘);”;
    $queryResource = mysql_query($sql, $dbConn) or die(mysql_error());
    header(“Location: $referral”);

    After clicking the “Ajax Save” button, however, the page never refreshes, and the Firebug console shows:
    POST …/result.php 302 Moved Temporarily 176ms jquery-latest.js (line 8416)
    GET http://(www…./calling_page).php 200 OK (SPINNING DIAL) 94ms

    The GET request never finishes, and the “SPINNING DIAL” continues ad infinitum.
    If the page is manually refreshed at this point, then the new content is rendered on the refreshed page.
    By using the code from your “Posting” article, the code gets the new content using code like this:

    div class=”content-inner-txt” id=”content-inner-txt” name=”content-inner-txt”
    code
    while ($row = mysql_fetch_assoc($queryResource)) {
    $content = $row[‘message’];
    $content = stripslashes($content);
    }
    code
    code echo $content; code
    div

    So, it seems that the SQL statement (in result.php) is executed, but “header(“Location: $referral”);” stalls out somehow.

    Furthermore, if a “Submit” input button is added to the div code:

    form action=’submit.php’ method=’post’
    input name=’data’ type=”hidden” value = “test”
    textarea class=”editor” id=”editor” name=”editor” code echo $content; code textarea
    input type=”submit” name=”submit” value=”Submit”
    form

    …then the “header(“Location: $referral”);” DOES execute, and “test” is rendered on the page AND in the ckeditor window.

    So, either the “Ajax Save” button needs to successfully run all the way through the “Location: $referral” code, OR I need to get the “editor.getSnapshot()” data into the hidden ‘data’ control.

    Any help –> much appreciation!

    1. Here’s a way to pass the ckeditor data along to the result.php page using the hidden field AND get the page to refresh with the new content. In the form mentioned above, construct the Submit button with an added onClick event…

      form action=’submit.php’ method=’post’ name=’form1′
      input name=’data’ type=”hidden”
      textarea class=”editor” id=”editor” name=”editor” php echo $content; php textarea
      input type=”submit” name=”submit” value=”Submit” onclick=’make_edit()’
      form

      Then assign the ckeditor data to the hidden field by adding the following script to the page…

      script type=”text/javascript”>
      function make_edit()
      {
      document.form1.data.value =CKEDITOR.instances.editor1.getData();
      }
      script

      The ckeditor data will now be sent to the result.php page, and the header(“Location: $referral”); will refresh the page with the new content. Note that the Ajax save button will still work to save the edited data as you go along, but (as stated above), the calling page won’t refresh (for unknown reasons).

  12. Hi, I Have un error

    table= pages
    ID
    Content

    Please….. Error in this row

    $sql = “INSERT INTO pages VALUES(NULL, ‘” . mysql_real_escape_string($_POST[‘data’]) . “‘);”;

    —————————————————-
    Notice: Undefined index: data in J:\wamp\www\botanikpedia\result.php on line 16
    Call Stack
    # Time Memory Function Location
    1 0.0004 384288 {main}( ) ..\result.php:0
    —————————————————–

    This is the myadmin.php

    ADMIN

    .cke_contents {
    height: 400px !important;
    }

    $(document).ready(function() {
    CKEDITOR.replace( ‘editor’,
    {

    fullPage : true,
    uiColor : ‘#9AB8F3’,
    toolbar : ‘MyToolbar’

    });
    });

    // This is the bouton that work

    ————————————————————-

    And this is the result.php

  13. Hellò… now it work, but:

    -Bouton saveajax in Toolbar not work
    -Other Bouton ( )
    save the text ok, but creates another ID -Content

    how can I save the same content open in ckeditor???
    Thank
    ( excuse my english )

    1. Hi Aldolfo!

      I will write another tutorial on how to update an existing record in the next couple of days… hopefully that will explain what you are trying to accomplish. I will reply to this post when it is done.

      Thanks,
      Bud

      1. Hi Aldolfo,

        Looks like my “next couple of days” will be pushed off to a week. I will do my best to get it done and posted by the weekend; I had a few things come up last weekend that prevented me from working on it.

        Thanks for your patience!
        Bud

  14. $host = ‘localhost’; // alternatively, you can put ‘127.0.0.1’ here
    $dbUser = ‘root’; // I would never use root for a production
    // user, but for a local installation, it is ok…
    $dbPass = ”; // or whatever it is set to be…

    $dbName = ‘page’; // use your database name here

    $dbConn = mysql_connect($host, $dbUser, $dbPass)
    or trigger_error(mysql_error(), E_USER_ERROR);
    mysql_select_db($dbName, $dbConn);

    $sql = “INSERT INTO pages VALUES(NULL, ‘” . mysql_real_escape_string($_POST[‘editor’]) . “‘);”;
    $queryResource = mysql_query($sql, $dbConn) or die(mysql_error());

  15. Hello Bud;

    Congratulations for the accomplished work!

    I am trying to accomplish an update in the base utilizanto his/her code.

    You can help myself with this problem, I don’t get to catch the id of the table to accomplish an update.

    Thank you!

    1. Hi Aldair,

      Thanks for the kind words! The table structure was in the code for the file, results.php:
      /* Table: messages
      * Fields: id (INT, primary key, auto-increment)
      * message (TEXT)
      */

      If this is not what you meant, please clarify and I will do my best to help you!

      Thanks,
      Bud

  16. Bud;

    thank you for the Return!

    But I think I didn’t go clear in mine he/she doubts.

    My problem is the following:

    He/she would like to accomplish an updating in the database (BD).

    In his/her code I found only the option of inserting a new registration in the database (BD).

    Thank you!

    1. Hi Aldair,

      Looks like my “next couple of days” will be pushed off to a week. I will do my best to get it done and posted by the weekend; I had a few things come up last weekend that prevented me from working on it.

      Thanks for your patience!
      Bud

  17. Hi Bud,

    Great tutorial, but I have a problem, I followed all your steps, but somehow the ‘save ajax’ button is empty, and when I click it it has no effect at all.
    Hope you have time to respond.

    Daan

  18. Great tutorial. I was wondering, how do I retrieve the response text from the xhr object? I’m guessing I need a function in the success portion of the ajax call in plugin.js, but since the XMLHttpRequest was never named, I don’t know how to reference it.

  19. hi,
    Great tutorial. I need one more thing. Right Now, only editor.getSnapShot() data is delivered to result.php but I need to send id for that editor so i can update that data. please give me solution.

    You help is appreciated.

  20. Hi,

    pleas can some body help me

    i have this code .I am not able to submit a my query from ckeditor but before i was using simple textarea that is working fine.

    my code is;-

    <?php
    session_start();
    $userid=$_SESSION['userid'];

    $headline=$_POST['headline'];
    $designation=$_POST['designation'];
    $functionalarea=$_POST['functionalarea'];
    $currentindustry=$_POST['currentindustry'];
    $cprofile=$_POST['cprofile'];
    $country=$_POST['country'];
    $city=$_POST['city'];
    $salary=$_POST['salary'];
    $skills=$_POST['skills'];
    $experience=$_POST['experience'];
    require_once('../connect.php');
    $responseText="From server";

    $query="insert into posted_job(emp_id,heading,designation,functional_area, industry, profile, country, city, salary, skills, experience,posted_on) values('$userid','$headline','$designation',
    '$functionalarea','$currentindustry','$cprofile','$country','$city','$salary','$skills','$experience',curdate())";

    $result=mysql_query($query, $con)or die("Not able to insert into posted_job");
    if($result==1)
    {
    $responseText="Successfully Inserted”;
    }else{
    $responseText=”Some Error in Inserting data”;
    }

    echo “$responseText”;

    ?>

  21. and this is my html pages

    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.j

    .cke_contents {
    height: 100px !important;
    }

    $(document).ready(function() {
    CKEDITOR.replace( ‘editor’,
    {
    fullPage : true,
    uiColor : ‘#9AB8F3’,
    toolbar : ‘MyToolbar’
    });
    });

    // Replace the with an CKEditor
    // instance, using default configurations.
    CKEDITOR.replace( ‘editor1’, {
    uiColor: ‘#dadbda’,
    toolbar: [
    [ ‘Bold’, ‘Italic’, ‘-‘, ‘NumberedList’, ‘BulletedList’, ‘-‘, ‘Link’, ‘Unlink’ ],
    [ ‘FontSize’, ‘TextColor’, ‘BGColor’ ]
    ]
    });

  22. Hi vikas,

    First, there are a couple of things that you will want to consider… you are (probably because of my post which was written almost 2 years ago) using the deprecated mysql_ functions. Please consider updating your code to using either mysqli or PDO. Also, take a look at http://www.php.net/manual/en/ref.mysql.php and while you are there learning about those at the filter_var() function and sanitize your inputs. (I tend to favor the PDO option)

    For example, in your code “$headline=$_POST[‘headline’];”, change that to “$headline=filter_var($_POST[‘headline’], FILTER_SANITIZE_STRING);” (see http://php.net/manual/en/filter.filters.sanitize.php and http://www.php.net/manual/en/function.filter-var.php)

  23. Hello Sir,
    I hope you can help me. I am trying to figure out how to save the content that is entered. I got the button working. It was hard to find at first, but I guess the blank square at the top left corner is the ajax button because that is what the alt text says. It doesn’t save anything. I was expecting (the novice that I am) that this was a tutorial to teach me how to do the saving side of this. ckeditor gives us the code for it but the saving of it is up to us they say. But I don’t know how to make a saving application. I also don’t know how to set up a username/ password login application. Is this tutorial supposed to be to teach us how to save the data once it is entered?

Leave a Comment

Scroll to Top