Integrating FCKeditor Into CakePHP
There are two different methods of FCKeditor integration to choose from with CakePHP: PHP and JavaScript. I will cover both of them here but I think my personal choice would be using the JavaScript method and replacing the textarea. That way there is a fall back for people with JavaScript turned off. For this example I will be using my previous post about creating a CMS using Cake and adding the famous rich text editor to the add and edit content pages.
The first thing you want to do is download the latest version of FCKeditor. At the time of this writing the current stable version is 2.6.3. You could try the beta version or the nightly build if you feel adventurous but personally I like sticking with stable versions.
PHP Integration Method
After you have finished downloading FCKeditor extract the archive and upload the fckeditor folder to your webroot, /app/webroot/fckeditor. I know most people might say to put this in /app/vendors but I have a reason. Instead of using App::import to import the /fckeditor/fckeditor.php file I took the contents of that file and created a helper with it. I would have imported the distributed class into the helper to make it more portable, but I wanted to rewrite the CreateHtml function to make it a little more CakePHP friendly.
Here is the Fck Helper.
/app/views/helpers/fck.php
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
<?php
class FckHelper extends AppHelper { var $InstanceName; var $InstanceId; var $BasePath; var $Width; var $Height; var $ToolbarSet; var $Config; var $Value; var $Error; function __construct() { $this->BasePath = '/fckeditor/'; $this->Width = '100%'; $this->Height = '400'; $this->ToolbarSet = 'Default'; $this->Config = array(); } function IsCompatible() { if ( isset( $_SERVER ) ) { $sAgent = $_SERVER['HTTP_USER_AGENT'] ; } else { global $HTTP_SERVER_VARS ; if ( isset( $HTTP_SERVER_VARS ) ) { $sAgent = $HTTP_SERVER_VARS['HTTP_USER_AGENT'] ; } else { global $HTTP_USER_AGENT ; $sAgent = $HTTP_USER_AGENT ; } } if ( strpos($sAgent, 'MSIE') !== false && strpos($sAgent, 'mac') === false && strpos($sAgent, 'Opera') === false ) { $iVersion = (float)substr($sAgent, strpos($sAgent, 'MSIE') + 5, 3) ; return ($iVersion >= 5.5) ; } else if ( strpos($sAgent, 'Gecko/') !== false ) { $iVersion = (int)substr($sAgent, strpos($sAgent, 'Gecko/') + 6, 8) ; return ($iVersion >= 20030210) ; } else if ( strpos($sAgent, 'Opera/') !== false ) { $fVersion = (float)substr($sAgent, strpos($sAgent, 'Opera/') + 6, 4) ; return ($fVersion >= 9.5) ; } else if ( preg_match( "|AppleWebKit/(\d+)|i", $sAgent, $matches ) ) { $iVersion = $matches[1] ; return ( $matches[1] >= 522 ) ; } else return false ; } function Create($instance) { $instance = explode('/', $instance); $this->InstanceName = 'data['.$instance[0].']['.$instance[1].']'; $this->InstanceId = $instance[0].Inflector::camelize($instance[1]); $HtmlValue = htmlspecialchars( $this->Value ) ; $Html = '' ; if ( $this->IsCompatible() ) { if ( isset( $_GET['fcksource'] ) && $_GET['fcksource'] == "true" ) $File = 'fckeditor.original.html' ; else $File = 'fckeditor.html' ; $Link = "{$this->BasePath}editor/{$File}?InstanceName={$this->InstanceName}"; if ( $this->ToolbarSet != '' ) $Link .= "&Toolbar={$this->ToolbarSet}" ; $Html .= "<input type=\"hidden\" id=\"{$this->InstanceId}\" name=\"{$this->InstanceName}\" value=\"{$HtmlValue}\" style=\"display:none\" />"; $Html .= "<input type=\"hidden\" id=\"{$this->InstanceId}___Config\" value=\"" . $this->GetConfigFieldString() . "\" style=\"display:none\" />"; $Html .= "<iframe id=\"{$this->InstanceId}___Frame\" src=\"{$Link}\" width=\"{$this->Width}\" height=\"{$this->Height}\" frameborder=\"0\" scrolling=\"no\"></iframe>"; } else { if ( strpos( $this->Width, '%' ) === false ) $WidthCSS = $this->Width . 'px'; else $WidthCSS = $this->Width; if ( strpos( $this->Height, '%' ) === false ) $HeightCSS = $this->Height . 'px' ; else $HeightCSS = $this->Height ; $Html .= "<textarea name=\"{$this->InstanceName}\" id=\"{$this->InstanceId}\" rows=\"4\" cols=\"40\" style=\"width: {$WidthCSS}; height: {$HeightCSS}\">{$HtmlValue}</textarea>" ; } if ( !empty( $this->Error ) ) { $Html .= '<div class="error-message">'.$this->Error.'</div>'; } return $Html ; } function GetConfigFieldString() { $sParams = '' ; $bFirst = true ; foreach ( $this->Config as $sKey => $sValue ) { if ( $bFirst == false ) $sParams .= '&' ; else $bFirst = false ; if ( $sValue === true ) $sParams .= $this->EncodeConfig( $sKey ) . '=true' ; else if ( $sValue === false ) $sParams .= $this->EncodeConfig( $sKey ) . '=false' ; else $sParams .= $this->EncodeConfig( $sKey ) . '=' . $this->EncodeConfig( $sValue ) ; } return $sParams ; } function EncodeConfig( $valueToEncode ) { $chars = array( '&' => '%26', '=' => '%3D', '"' => '%22' ) ; return strtr( $valueToEncode, $chars ) ; } } ?> |
After you have this helper in place you can enable it by adding it to your $helpers array in whatever controller you are working with. I will be using the content controller from my previous post about a simple cms.
class ContentController extends AppController {
var $name = 'Content';
var $helpers = array('Fck');
After you have that, open your view and pick the field you want to change. Still following the cms example you will want to edit /app/views/content/add.ctp and /app/views/content/edit.ctp like the following.
|
1
2 3 4 5 6 7 8 |
// Replace this
echo $form->input('body', array('rows' => '10', 'cols' => '70')); // With this if(!empty($this->data['Content']['body'])) $fck->Value = $this->data['Content']['body']; if(!empty($this->validationErrors['Content']['body'])) $fck->Error = $this->validationErrors['Content']['body']; echo $fck->Create('Content/body'); |
There are several other configuration options available. You can look at the documentation for more information. Any options available with their php integration method should also be available with this helper.
The only problem with this method so far is there is no non-JavaScript fall back to a plain text area. There is if the browser is not supported. Maybe there is something there that can be expanded on?
For more information on the PHP Integration method please check out the FCKeditor documentation.
JavaScript Integration Method
There are 3 different JavaScript integration methods to choose from. As I mentioned earlier I personally prefer the textarea replacement method with JQuery. So that is the only one I will go over here.
To get started go ahead and download FCKeditor and place it in your webroot just like with the php method above. Then download JQuery and put it in your /app/webroot/js folder. I usually rename the file to jquery.js to make updates easier. Now enable the JavaScript helper in your controller and add the javascript to your view. Using the cms example the add content view would look like this.
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<h2>New Page</h2>
<?php echo $form->create('Content', array('url' => '/content/add')); echo '<div>'; echo ' <label for="ContentParentId">Parent</label>'; echo ' <select name="data[Content][parent_id]" id="ContentParentId">'; echo ' <option value="0"'.((@$this->data['Content']['parent_id'] == 0) ? ' selected' : '').'>None</option>'; if(!empty($parents)) { foreach($parents as $i) { echo '<option value="'.$i['Content']['id'].'" style="padding-left: '.($i['Content']['depth'] + 1).'em;"'.((@$this->data['Content']['parent_id'] == $i['Content']['id']) ? ' selected' : '').'>'.$i['Content']['title'].'</option>'; } } echo ' </select>'; echo '</div>'; echo $form->input('title', array('size' => 60)); echo $form->input('slug', array('size' => '20', 'after' => ' The Slug is the word used for the URL of this page.')); echo $form->input('body', array('rows' => '10', 'cols' => '70')); echo '<div><input type="submit" value="Save" /> or '.$html->link('Cancel', array('action' => 'index')).'</div>'; echo '<fieldset>'; echo ' <legend>META Data</legend>'; echo $form->input('keywords', array('size' => '60')); echo $form->input('description', array('rows' => '3', 'cols' => '65')); echo '</fieldset>'; echo $form->end(); #FCKeditor stuff $javascript->link('jquery', false); $javascript->link('/fckeditor/fckeditor.js', false); ?> <script type="text/javascript"> $(document).ready(function() { var oFCKeditor = new FCKeditor('ContentBody', '100%', '400', 'Default'); oFCKeditor.ReplaceTextarea(); }); </script> |
For this to work with everything in your webroot the way it is we also need to add a couple of lines to the bottom of our .htaccess file.
/app/webroot/.haccess
AddType text/css .css
That should be all you need to do. If you would like more information on the JavaScript integration method please check out the FCKeditor documentation.
Enable The File/Image Upload
First you need to create 4 folders:
- /app/webroot/files/file
- /app/webroot/files/flash
- /app/webroot/files/image
- /app/webroot/files/media
Each folder need to be writable by the web server.
Now edit /app/webroot/fckeditor/editor/filemanager/connectors/php/config.php and make the following changes for each line (Line numbers may change according to your version).
|
30
|
$Config['Enabled'] = false ;
|
|
34
|
$Config['UserFilesPath'] = '/files/' ;
|
Be sure and set this next one to the full path of your files directory.
|
40
|
$Config['UserFilesAbsolutePath'] = '/var/www/mywebsite.com/htdocs/app/webroot/files/' ;
|
It should now be working. There is also a lot more information on the CakePHP Bakery that could be useful to you.













I did exactly the things you said (both methods), but still it doesn’t work.
for the javascript method there is the error: “FCKEditor is not defined”.
Jquery installed, fckeditor in webroot. everything just the way you said.
hoping for help…i did spend the whole day with this
It looks like I left something out for the JavaScript method. You need to include the fckeditor.js file.. here is an example of how you can do it with jquery after your form:
$javascript->link('/fckeditor/fckeditor.js', false);
?>
<script type="text/javascript">
$(document).ready(function() {
var oFCKeditor = new FCKeditor('FieldId', '100%', '400', 'Default');
oFCKeditor.ReplaceTextarea();
});
</script>
The only thing here you will want to change is possibly the path to your fckeditor.js file and the Id of the textarea field you are replacing in the FCKeditor constructor.
Hope that helps :-/
Hello Joseph.
error is gone, but still it doesn’t work.
cakephp shows the form and everything, but doesn’t show “body textarea”, where I expect the fckeditor to be. first method didn’t worked as well. what do i wrong?
it’s really frustrating. i am testing it on my local host (mamp/mac os x)…
further looking for help…
hello again.
i followed the steps on http://bakery.cakephp.org/articles/view/using-fckeditor-with-cakephp and comment no. 11 helped.
BUT…still FCKeditor doesn’t work on my local machine (mamp/mac os x). after uploading it to my server it works fine… any clue?
Followed your tutorial line by line. Did your CMS tutorial and replaced those lines… does not work. Instead I get a “cannot find fckeditor.html” message. I copied the whole fckeditor folder into /webroot/ straight from the zip without removing or touching any file. I created the helper. Added the reference to the helper. Line by line. Did it 3 times.. same result. =(
Will try javascript method.
after doing some tinkering with the code I found that the helper only works if youre working on a project that’s on the ROOT folder of the directory meaning if im working in localhost/myproject I have to replace
$this->BasePath = ‘/fckeditor/’;
with $this->BasePath = ‘myproject/fckeditor/’;
Thanks for the awesome tutorial! hope this helps someone.
Thanks Leo. Your comment really helped me. Firstly, when I try your suggestion I still found error. Then I changed the code with this
$this->BasePath = ‘../myproject/fckeditor/’;
and it worked!
FYI, I was using XAMPP and Windows XP. Thanks also for this tutorial
Thank you so much for this tutorial – I wasted a whole evening trying 3 other methods – none of which worked.
You’re a star!!
Thanks
thx a lot, for the script but i have an error when i try PHP Integration Method, the add.ctp work very good but edit.ctp don’t work!
link for see error:
http://www.cakephp-it.org/topic278-problema-con-fckeditor.html
Hi Joseph, thank you!!
But i have the same problem with edit.ctp
Thanks again
Hi again Joseph, but i fix it, i forgto to include the id field in edit ctp
Thanks. Saved my life.
Thanks a lot Joseph. Am using php integration method which works fine. But if i want to place fckeditor in vendor insted of js, so how can i do that?
Hey, I am trying to cahnge the language to sapnish and it doesn’t seem to work. Any help?
I’m sorry but I don’t know Spanish. You could try the FCKeditor website.
I have not had luck with using FCKeditor from the vendor folder. I have tried because it seems the obvious place to put it but gave up and took the easy way out.
Thanks. Saved my life.
For your info.
Now the FCKEditor is changed to CKEditor with the relase of CKEditor 3.0.
Integrating latest version of FCKEditor(CKEditor) with cake php is very easy. You
can see the simple steps here.
Integrating CKEditor with CakePHP
Hi, its great…. after changing in $this->BasePath =Url project/fckeditor/ its working cool thanks for giving this article….
Hello its working but if we change the name of $fck->create(‘ModelName/ActionName’) then not work. we should always define name like $fck->create(‘ModelName/content’). Is this problem in your helper ???
I have inserted Ckeditor 3.x in my page and i submit my form data (along with the text area)to the controller. I am trying to save data to Mysql database but not able to save. I wonder if this is a correct way of doing it.
Form name = Admin
Field name = content
Controller name = Admins
Modelname = Admin
Mycontroller code:
$grn3 = $this->data['Admin']['content'] ;
$this->Session->setFlash($grn3);
$this->Admin->set($this->data ); //setting data to model
$this->Admin->saveField(‘content’, $grn3); //saving single field
Setflash method flashes the data content, but save is not working. I am not sure if this is the way of saving text editor data to database. Please show me how to save editor data to database.
Thankx
John M.
Now FCKEditor is replaced by CKEditor. So you can see the installation of CKEditor with Cake php in the following URL.
http://www.robinthomas.in/php/ckeditor-cakephp/