Adding Ajax Panels to the CakePHP Status Plugin
Previously On...
Last time we made a simple panel that showed the last 10 users that signed up for you web app. It was a good example for using the requestAction approach (or as AD7six pointed out you can skip the requestAction part and go right to the model).
Let's Get Ajaxy Up In This Mofo
This time we'll do a panel that shows the number of sign ups based on a time frame. We'll add a drop down that let's you select day, week, month or year and it'll show a breakdown of new users for that period. The updates will use ajax.
The Element
Just like last time we're going to create a new element: /app/views/elements/panels/signups.ctp. This time, however, the element will contain a form:
<?php echo $form->create('User', array('id' => 'SignupsForm')); ?>
<h1>
<?php __('Signups'); ?>
<?php echo $form->input('signup_span', array('type' => 'select', 'div' => false, 'label' => false,
'options' => array('day' => 'day',
'week' => 'week',
'month' => 'month',
'year' => 'year')));
?>
</h1>
<?php echo $form->end(); ?>
<div id="signup-table">
<p><?php echo $html->image('/status/img/ajax-loader.gif') ?></p>
</div>
In addition to the form, there is a div (signup-table) that will be used to hold the result of the Ajax call. For now we'll just stick a spinny icon in there.
The JavaScript
<script type="text/javascript">
$(function(){
$("#UserSignupSpan").change(function() {
$("#signup-table").html("<p><img src=\"/status/img/ajax-loader.gif\" \></p>");
$.get("/users/signups/" + $(this).val(), function(data) {
$("#signup-table").html(data);
});
}).change();
});
</script>
Pretty standard jQuery. We catch the change in the span select, set the holder div to the spinny icon and make the request for the updated data.
The Controller
function signups($span=1) {
if (!Configure::read('Status.allow')) {
die;
}
switch ($span) {
default:
case 'day':
$field = 'SUBSTR(created, 1, 13)';
$limit = 24;
break;
case 'week':
$field = 'SUBSTR(created, 1, 10)';
$limit = 7;
break;
case 'month':
$field = 'SUBSTR(created, 1, 7)';
$limit = 12;
break;
case 'year':
$field = 'SUBSTR(created, 1, 4)';
$limit = 5;
break;
}
$data = $this->User->find('all', array('fields' => array($field . ' AS span', 'count(*) as cnt'),
'group' => 'span',
'order' => 'span DESC',
'limit' => $limit));
$this->set('data', $data);
}
In practice I would move most of this code to a custom find type, but for the sake of this example I'll put it all in the controller. An important note: Unlike the example in the previous post, this action has a view associated with it. That means you can access it directly without going through the status panel. To protect against that we add the check at the top to make sure the user is allowed to access the status panel.
Include The New Panel
Remember to add the panel to the list of panels in bootstrap.php:
Configure::write('Status.panels', array('panels/signups'));
What It Looks Like

Adding Custom Panels to the CakePHP Status Plugin
Intro
A few weeks ago I released a status plugin for CakePHP. It is basically a single page where you can get a quick snapshot of your app. The plugin ships with a few random panels, but it's easy enough to add your own. This post will tell you how.
Make sure to get the latest version from GitHub. Also note that the way to include the default panels has changed. You now have to include the "Status." prefix.
requestAction vs Ajax
There are two different ways to add a panel - using requestAction or Ajax. The general rule is if the panel is pretty fast to load and content is static use requestAction. If the panel takes some time or you want to be able to interact with it then use Ajax. For example, the logs panel uses requestAction since it's pretty quick to grab the log entries and you really don't need to interact with them. The Google Analytics panel, on the other hand, takes a few seconds to query the API and has options to change the timeframe, so it uses Ajax.
Packaging Your Panel
Panels can be packaged as plugins or just files in your app. For this example we'll just put the files as part of the app. Making your panel as a plugin is pretty much the same, you just need to put all the files in the plugin's directory and include the plugin name as a prefix when setting which panels to use. Check out the click plugin for an example. I'm just going to cover the requestAction approach today. Look for another post of using Ajax soon.
The requestAction Way
The Element
Let's build a panel that shows the last 10 users that signed up for your app. The first thing you need is an element. In /app/views/elements/panels (note the extra directory level - this is optional, but helps to keep things clean) create a file called 'latest_users.ctp'. In that file put:
<?php
$users = $this->requestAction(array('controller' => 'users', 'action' => 'latest'));
?>
The Controller
In the users controller we now need to add an action called latest that will get the user data and pass it back to the element.
function latest() {
return $this->User->find('all', array('order' => 'created desc', 'limit' => 10));
}
Since there is no view associated with this action anyone trying to access it directly with just get an error. If you wanted to extra sure that no one unauthorized could exploit this action you could add this to the beginning:
if (!Configure::read('Status.allow')) {
die;
}
Back To The Element
Now you have a list of $users so it's just a matter of displaying them. Here's the complete element:
<?php
$users = $this->requestAction(array('controller' => 'users', 'action' => 'latest'));
?>
<h1><?php __('Latest Users') ?></h1>
<?php if($users) { ?>
<table>
<?php foreach($users as $user) { ?>
<tr>
<td><?php echo $user['User']['email'] ?></td>
<td><?php echo $time->timeAgoInWords($user['User']['created']) ?></td>
</tr>
<?php } ?>
</table>
<?php } else { ?>
<p>Your app has no users...loser!</p>
<?php } ?>
Including Your Panel
Now you just have to include your panel on the status dashboard. In /app/bootstrap.php add the line:
Configure::write('Status.panels', array('panels/latest_users'));
Here's What It Looks Like

6 More Questions With Nate Abele - Lead Developer of CakePHP
If you missed part 1 you can check it out here.
From what I've seen the relationship between the maintainers of the top JavaScript frameworks is pretty friendly. How would characterize the relationship between the top PHP frameworks?
While there's been a fair bit of professional rivalry between different frameworks at different times, for the most part I'd say it's all in good fun. I've been fortunate enough to have met lead developers / prominent representatives from all the major PHP frameworks. They're all really great guys and I get along with all of them quite well, especially Paul M. Jones (of SolarPHP) and Matthew Weier O'Phinney (of Zend Framework). They're both very insightful, and I've never had an uninteresting conversation with either of them.
If you weren't the lead dev of CakePHP and Cake didn't exist what other framework would you be using (any language)?
Since we're going with any language, I'd have to say Node.js, which is (wait for it...) a JavaScript framework. I've always loved JavaScript, and it's probably the only language that would tempt me away from PHP for server-side development.
Do you get to code Cake apps at your day job? Are you able to work on the Cake core during the day or do you do everything off hours.
Well, my current job is with a startup, Hoopla Software, and I'm developing an app on Cake 1.3 that talks to SalesForce. I even wrote a database driver that speaks SalesForce SQL, which we plan on releasing later on. At my previous job with OmniTI, I'd say about 50% of my projects were in Cake. In both cases, work on the core itself usually happens in conjunction with something specifically work-related, with the occasional quick bugfix during the day. Both my current and previous employer are very supportive of Open Source, so I've been fortunate in that regard.
Favorite coding beverage during the day? for after hours?
I'd have to go with Coke for both. I was recently introduced to a drink called Club-Mate in Germany, but that stuff is dangerously powerful.
Favorite music to code to?
Well, I don't really have a favorite, and my musical tastes are pretty varied, so this list could go on for a while. Some of the highlights: The Who, Switchfoot, G. Love, The Police, Weezer, Bowie, The Beatles, Simon & Garfunkel, Guster, Jet, Sinatra, Death Cab, Café Tacuba, Cheap Trick, Cake (!), U2, Peter Gabriel, Relient K, The Proclaimers, The Caesars, The Specials, The Cure, Citizen Cope, Sanctus Real, Bob Marley, Elvis Costello, more Switchfoot, and Garrett's favorite: Oasis.
What apps have you built using the CakePHP framework?
Besides the one I'm working on right now, most of what I've worked on I'm not technically supposed to discuss, particularly not in print (see! if you were at CakeFest, you'd have heard the stories). In very general terms, I've written a tool related to security testing, a very big and high-profile tracking tool for a company that everybody's heard of, a bunch of smaller sites and tools around a database and suite of analytics tools for helping political campaigns analyze several terabytes of voter data, a portal for a football magazine, a couple of smaller, more personal CMS-y type stuff, mainly for the heck of it, a very JavaScript-heavy calendar app with iCal syncing, and a couple dozen smaller for-fun side-projects, most of which will probably never see the light of day.
Aside from those projects, on which I've been the principal developer (or one of), I've had my hands in or on several other CakePHP projects (and non-Cake / non-PHP projects), public, private and Open Source.
The End
Thanks to Nate for being so open and giving some awesome answers. I will now freeze myself, Cartman stlye, rather then endure the wait for Cake3. Someone please remember to dig me out when it's released.
9 Questions With Nate Abele - Lead Developer of CakePHP
Intro
Yeah, yeah, I know. This has been done before. What can I say - I had questions, Nate had answers. This is part one and covers general Cake and Cake3 questions. Look for part two tomorrow, which has a bunch of random questions.
General Cake Questions
The end game looks like there will be three CakePHP versions, which can be confusing to new developers. I haven't seen this explicitly defined, so stop me if I'm wrong:
The 1.3 branch is for anyone developing for PHP4
The v2 branch is for anyone developing new projects for PHP5-5.2 OR for PHP 5.3 users looking for an easier upgrade for a 1.2 app.
The v3 branch is for 5.3 apps.
That's about right. Once the 1.3 branch goes stable, that'll close off principle development on the 1.x branch, barring bug and security fixes and so forth. We haven't completely ruled out the possibility of back-porting future 2.x features, but that will largely depend on demand, which at this point we don't expect; and yes, 2.0 should be a direct upgrade from 1.3 (which has very few API changes from 1.2). 3.0, on the other hand, is still under pretty heavy development, so it isn't recommended for anything other than experimental applications just yet.
How many people are actively contributing to the three new versions of Cake. Whats the breakdown in terms of # of developers working on each branch or does everyone work a bit on each branch?
Well, in total I think we have something like 16 active team members working on various different things, including things other than the code itself. 1.3 has had about a half-dozen active developers, with the bulk of the work being done by the Canuckistani dream team: Mark Story and Joël Perras. In order to manage the extra work, Larry has brought in a few developers from the Cake Development Corporation to help out on the 2.x branch, particularly Graham Weldon (a.k.a. Predominant) who's been doing a lot of the heavy lifting to get the current code base fully strict-mode compatible.
Finally, I'm leading development on the 3.0 branch, with Joël, Garrett, David Persson, and Tim & Felix (of Debuggable) contributing.
Cake3 Questions
Right now 1.3 and 2 are still licensed as MIT. Cake3 is BSD licensed (although some files are still MIT (stuff in app) and the license.txt file doesn't specify any particular license). Whats the deal with the change? How will this affect developers?
Practically speaking, this won't affect developers at all. In terms of what you can do with the software, the BSD license is just as permissive if not more so than MIT. The change was mainly due to my own personal preference: the BSD is an older license with a more distinguished Open Source history. Garrett was also very supportive of the change, as the BSD license includes a specific clause that shields the CakePHP brand and the CSF from being abused for commercial purposes, which we've always been very much against. We're really excited to see people building businesses off of the code we write, but people using our name to promote themselves is just not in the spirit of what we're trying to do.
As for the places where the MIT license still appears, that's just some cleaning up we have left to do from the old CakePHP distribution. It'll be all BSD all the time before a release goes out.
Cake3 is switching to returning objects for result sets instead of array. I'm probably remembering wrong, but I thought you preferred the array approach. Was this change something need to be convinced about or was it something planned all along.
Well, that's close. My position was always that I preferred the array approach in context. Since the context at the time was PHP4, and PHP4 had all the array-hacking functions you could ever hope for and a crippled object model, it was the natural choice. Now that we've progressed beyond that, there's just no need to stick with arrays anymore, which I'm all for, as it frees us from a lot of the restrictions we had on how we design things.
Was there anything that came from the google group "hate" thread that you hadn't planned to implement or prefer a different approach, but were swayed by the community?
Probably my biggest reversal of position (and this is in general, not only regarding the 'hate' thread) has been regarding multi-column key support. The thing about single-column keys is that they make things consistent and easy all the way up and down the stack (REST APIs, etc.), and that's great. But what I realize is that there are often (again, in context) some good arguments for using multi-column keys, and even if we don't support them at higher levels, this is something that any well-designed data abstraction layer should support.
Say I'm a pretty good developer, whose willing to dig through code, submit patches for bugs and I'm starting a project that won't be launched for at least a year. Would I be crazy to start that project in Cake3 right now?
Well, it depends on the app. For most things, I'd say it'd be a pretty big commitment, since right now a lot of basic things like pagination and session handling are still missing. A lot of that doesn't matter though, since with Cake's new structure, you can load in other classes and libraries fairly easily, eventually including things like using Doctrine in place of the default ORM. Also, a lot of the API should be pretty familiar to you if you're already a Cake developer, and much of that is unlikely to change.
If anyone has a really experimental app in the works and would like to contribute to the 3.0 branch, I'd be interesting in talking with them about contributing. The biggest thing that this new version has going for it is that the plugin architecture is already pretty well-developed, and plugins are handled in almost exactly the same way as an app, and even the core itself, so everything is very interchangeable. Another major architectural difference is that most class dependencies in the core can be swapped out for classes in a plugin or in your app.
What we're hoping to achieve with this is that once the core becomes more stabilized, all the interesting development can happen in plugins. This is really important, because the barrier to entry on contributing to a smaller project with a more constrained feature set is much lower. Development can happen in parallel, and features can be moved in and out of the core distribution with relatively little impact on application code.
What's going on with unit testing in Cake3? It looks like SimpleTest is being dropped and instead Cake3 will have it's own unit test tools.
Again, this is one of those decisions which was made for us previously, as SimpleTest was the only viable option for PHP4, short of writing our own test suite, which we've decided to bite the bullet on this time around. Several factors went into that decision, but mainly (a) that we wanted people to be able to run tests right out of the box, and (b) we wanted a testing infrastructure that was tailored to our needs and allowed us to measure things in a way that we wanted; things that would help people judge the quality of software distributions. Not just Cake itself, but plugins and applications. I'll be talking more about this later on.
However, we plan to keep our test suite fairly lightweight, and one thing that'll be revisited before a release is the API; specifically bringing it more in-line with PHPUnit, to streamline the upgrade process for those with more heavy-duty testing needs.
The filter system looks pretty sweet and has been talked about a bit. What Cake3 feature are you most excited about that hasn't received much attention?
At this point, I guess the biggest thing that I haven't talked very much about yet is the Media class. The Media class is interesting because it takes out a lot of the work that was previously required when serving or handling different content types. It sits between the controller and view layers, and allows you to attach different handlers for each content type, both input and output. This means that instead of having to create a view every time you want a controller method to render as JSON, you can just attach one handler, once, that tells all JSON responses to automatically assemble themselves from the variables you set in the controller. For HTML on the other hand, a view class is attached (by default) that works as normal, rendering templates from your views/ directory as normal; but even with in that there's an incredible amount of flexibility, and you now have one place to configure it, application-wide.
I'm still a little confused about how filters work. You tie a filter to a method, but don't have to specify if it's a "before" or "after" filter, right? If you want it to act as "before" you just run your code before calling return $chain->next(...). How would you do an after filter? Like this?
$ret = $chain->next($self, $params, $chain);
//my code
return $ret;
Yup, that's exactly right. You can think of writing a filter a lot like you'd think of overriding a method in a subclass, but instead of calling the parent method (i.e. $result = parent::methodName()), you're calling $chain->next(...). This has a lot of notable advantages over simple before and after filter methods, probably the biggest being that all related operations are kept together in the same scope. Not having to split things up between two methods means you don't have to worry about persisting things through parameters or object state (or worse, global state). Everything is neatly atomic and isolated. It also makes a lot more sense when you're browsing through code.
To Be Continued...
More from Nate tomorrow when we cover what music he codes to and much more. I bet you just can't wait for that.
CakePHP Digest #18 - The CakeFest Edition
CakeFest
Big News
The big news everyone is talking about from CakeFest is Cake3 - a completely overhauled version of CakePHP geared towards PHP5.3. Unfortunately I was stuck watching over little one (by that I mean my co-workers...I kid...you guys are the best) and didn't make it to Berlin. Plus, ustream.tv ate the keynote videos, so I probably have less details then anyone. Of course it didn't take much detective work to find the processed versions of the keynotes that will probably soon be seen on live.cakephp.org. In other news CakePHP2, a PHP5 version, was also announced, but was so overshadowed by Cake3 that it resorted to cutting itself for attention.
The Show
Nate Abele, Garrett Woodworth, and Jeff Loiselle did a podcast recently discussing what went down at CakeFest. Nothing too earth shattering was revealed, but it clocks in at a trim 27 mins, so it's worth a listen. Thankfully they didn't answer any questions from the IRC channel, so I didn't feel so bad that I didn't waste an hour figuring out how to use IRC.
Interviews
Also on live.cakephp.org are three interviews. I haven't had a chance to check any of these out yet, so I'll just throw out the links, with a description of what I think they are talking about based on the preview image:
Nate Abele and Jeff Loiselle discuss various leg crossing positions. Nate prefers the traditional over the top (The Orwellian), while Jeff tends towards the perpendicular tuck.
Gwoo and Jeff Loiselle don't actually talk in this one. They just flex for the camera for 13 mins.
Mariano Iglesias explains the dangers of hat head to Joël Perras
Recaps
Graham Weldon has recaps of each of the talks posted on CakeDC.com.
Cake Toppings has a short post, which includes the bit: "That saterday had a few interesting talks and also some not interesting ones." Unfortunately, no further details where given. DRAMA!
Kevin van Zonneveld has a pretty long post on some of the tips he picked up.
Felix Geisendörfer posted his summary on the newly re-designed debuggable.com.
@alkemann has a post covering some of the out of conference shenanigans, including Fork Master (co-created by gwoo), which is kind of like horseshoes but with less of a chance of breaking a toe and a greater risk of losing an eye.
Slides
A bunch of the slides for the talks are posted. Oddly the files are all exactly the same size (512.0 Byte). Really impressive that all the presenters could coordinate and pull that off.
Mind Map (whatever the heck that is)
Not really sure what the point of these things are...but here is one for CakeFest.
Random Video
I leave no stone unturned. No link unhyperlinked. Here is 49 seconds of dimly lit bowling that @pierremartin claims came from CakeFest, but could easily be a night at rock and bowl from three years ago.
Photos
There were a bunch of random single shots posted on twitter, but I'll stick to the galleries here.
A bunch of iPhone shots from @alkemann.
Graham Weldon also has a picasa gallery, which includes some moderately NSFW shots. Someone should do A/B testing on the NSFW tag. I bet click throughs jump like 100000% with it.
And finally @pierremartin has a picasa gallery as well.
That's It
Sorry if I missed your blog recap, photo set, drunken video, or whatever. Feel free to leave a link in the comments.
