** Warning: Heavy Webdev Jargon Post — Javascript, PHP, Object-oriented concepts **
So, I spent my entire weekend trying to wrap my head around how CakePHP does things, but I spent more time trying to figure out how to make different AJAX methods to work with it.
Well, for starters, CakePHP is an rapid development MVC framework for PHP. It’s similar with RoR and Groovy and Grails. It implements ORM… and a lot more. ( If you have trouble with some of the jargon they have on the site, you can ask me here and I’ll try explaining them. )
Here’s my supposed laundry list of AJAX stuff to try:
- Inline editing
- Drag and Drop
- Dynamic updating of selects
- Quick saving
So far, I’ve finished… 1 of 4. X3
Inline Editing
Guides: The 15-minute blog, Cakebaker, CakePHP.bee.pl
I was initially following the 15 minute blog tutorial just to reinforce my *baking* skills, and nothing beats going through the basics again. I stopped at around 10.1.13 Routes and then proceeded with Cakebaker’s guide. Though, Cakebaker’s guide is complete by itself (he’s got code for the Model, View and Controller), it is still pretty important that you let the MVC paradigm sink in first before you follow any other guide that does not deal with the basics. Oddly enough, I can’t get it to work. I’m copy-pasting his code onto mine and making the appropriate changes but still, doesn’t work. So, after reading through the comments, I followed a link to a JQuery-based AJAX helper for CakePHP. (The default is for prototype and script.aculo.)
The said helper had a built-in method for inline editors, so I said, hey, what the heck. Might as well try. The examples were great as it showed you that it does what you need.. but eventually you’ll realize there’s something missing. Yep, the code for the controller. So, combining the Cakebaker’s guide and the documentation for this helper, I managed to (finally) make inline editing work. For this example, we’re using Cakebaker’s model and controller (Post) but we’re using the syntax of the helper for the view. I’ve also modified Cakebaker’s controller method to work with the helper.
Here are the relevant files:
In app/app_controller.php: [1]
<?php class AppController extends Controller { public $helpers = array('Html','Form','Javascript','Ajax'); public $components = array('RequestHandler'); } ?>
In app/views/posts/index.ctp: [2]
<?php foreach ($posts as $post): ?> <div class="post" id="div_<?php echo $post['Post']['id']; ?>"><?php echo $post['Post']['title']; ?></div> <?php echo $ajax->editor( "div_".$post['Post']['id'], array( 'controller' => 'Posts', 'action' => 'updateTitle' ), array( 'submit' => 'OK', 'style' => 'inherit', 'submitdata' => array ('id' => $post['Post']['id']), 'tooltip' => 'Click to edit', ) );?> <?php endforeach; ?>
In app/controllers/posts_controller.php: [3]
public function index() { $this->set('posts', $this->Post->find('all')); } public function updateTitle() { /* echo $this->params['form']['id']; echo $this->params['form']['value']; */ if ($this->RequestHandler->isAjax()) { App::import('Core', 'sanitize'); $title = Sanitize::clean($this->params['form']['value']); $this->Post->id = $this->params['form']['id'];; $this->Post->saveField('title', $title); Configure::write('debug', 0); $this->set('posttitle', $title); } }
In app/views/forms/update_title.ctp: [4]
<?php echo $posttitle;?>
Now for the explainin’:
[1] I’ve put the helpers and components array in the app_controller.php so that I don’t need to update *every single one* of my controllers. This is more of a convenience and I’m sure, on production level sites, this is not advisable as you will incur overhead for loading extra stuff that you won’t need anyway.
[2] This is taken from the documentation of the AJAX helper. Basically, it iterates over all of the posts and generates both a display div and an editor for each post title.
[3] The index function is there in order for the index view to work. Just gets all of the posts.
[3] If you look closely, updateTitle looks *almost* the same as the one at Cakebaker’s but I’ve changed how I get the data. Apparently, $this->data does not contain anytihng. I’ve tried echoing it, and even the word Array doesn’t show up. So, instead, I turned to $this->params['form'] to get all of the data passed on by any form in the page. The RequestHandler is there to check if the Request is an Ajax request. The reason for this is that we need to turn debugging levels to 0 (Configure::write) since we’re basically passing on a view and if debug levels weren’t set to 0, it passes on the whole debug messages back (including SQL stats). >_<
[4] The view to be rendered to replace the updated data in the editor div.
Note: I’ve read this article that utilizes the beforeFilter behavior in the AppController to detect if the request is an AJAX request and then changes debug levels appropriately. This could potentially save a lot of time but could incur overhead, I s’pose.
While this took me literally hours to figure it, the enlightenment I got makes it worth it.
I’ll be working on Quick Save, Dynamic Selects and Drag and Drop, in that order in the next few days and I’ll make sure I will put up any learnings I get here. This makes for a very convenient documentation place. X3
*Naku, may mga projects pa ako at ito ang inaatupag ko. (doh)*
[...] This post was mentioned on Twitter by Rystraum. Rystraum said: CakePHP and AJAX: Inline Editing ( http://bit.ly/a9Lt9f ) [...]
Tweets that mention CakePHP and AJAX: Inline Editing at Stream of Ry -- Topsy.com
4 Apr 10 at 06:53
Try using syntax highlighter for your code.
Jeune
4 Apr 10 at 10:42
@Jeune: That took me a while to fix up. But it should be okay now. I was wrestling with escaping html characters for some 5 or so updates. X3
rystraum
4 Apr 10 at 16:20
What problem did you encounter with the code from my blog? You simply mention it didn’t work…
Daniel Hofstetter
5 Apr 10 at 08:03
If I remember correctly, the changes aren’t being saved to the database. Now that I think about it, I should have checked with the javascript if I’m calling the proper class/method. I may update on this, but since I started working in Code Igniter again, it could take a little more while before I get to try it out again.
rystraum
8 Apr 10 at 02:31
i have a problem with retrieving data from the DB…
Here’s my select query:
And here’s the view:
Edit: Enclosed code in pre tags
new
26 Jul 10 at 23:46
Try replacing the view from your:
to:
Your problem could be related to your foreach operating over the keys and values instead of just for each instance in the array.
Then again, your question is a bit too broad so I don’t know if *this* is the cause of your problem.
I haven’t been doing PHP (let alone Cake) for quite a while so pardon me if I don’t remember it much.
rystraum
27 Jul 10 at 02:53