CakePHP Digest #19 - The Holy Shit Do I Have A Ton Of Links Edition
Seriously, could you guys please stop posting so many interesting blog posts and useful code? I'm having trouble keeping up.
News
CakePHP 1.2.4.8284 and CakePHP 1.3-dev Released
The Cake Team launched two new versions last week at some point prior to me getting around to publishing this. The first is a bug fix release for the 1.2 edition, which closed over 70 issues. Also the first development release of 1.3 was announced. There is a migration guide if you want to port a 1.2 app over.
One of the changes for 1.3 states:
DboSource::query() now throws warnings for un-handled model methods, instead of trying to run them as queries. This means, people starting transactions improperly via the $this->Model->begin() syntax will need to update their code so that it accesses the model's DataSource object directly.
I'm guilty of this, but mostly because I thought there actually were begin/commit/rollback methods. Here's a quick tip to fix this for 1.2 and 1.3 apps. In your AppModel:
function begin() {
return $this->getDataSource()->begin($this);
}
function commit() {
return $this->getDataSource()->commit($this);
}
function rollback() {
return $this->getDataSource()->rollback($this);
}
Nate Gets Around
Lots of interviews with Nate Abele, Lead Dev of CakePHP (well 2, but one of them was 2 parts so it was really more like 2.5 interviews). The first was with Felix and is posted on debuggable.com. The second was with me and is posted on this site in two parts.
CakeMatsuri Tokyo
If your in Japan on October 30 to the 31 check out CakeMatsuri - a two day conference/workshop. Note that the workshops are "friendly", which means you means you can leave your weaponry at home. You will need your guns for...
Start Cleaning Your Pistola
@ZendCon announced that the closing keynote for ZendCon would be a framework shootout. Participating will be Matthew Weier O'Phinney, David Zülke, Fabien Potencier, Edward Finkler, and Nate Abele. Here's the description from their site:
Representatives from five major frameworks will form a panel on the stage and discuss the various pros and cons of their frameworks. Discussions will be moderated by Eli White from Zend and will include some history of why each framework has made various decisions over time. Audience participation will be encouraged and questions will be taken. Frameworks represented will be: Zend Framework, Symfony, Cake, CodeIgnitor, and Agavi
Bake Updates For Cake 1.3
Mark Story has a great post covering all the new updates and features for Bake in 1.3. Be sure to check it out. My favorite part: "Test cases also generate skeleton test methods for every non-inherited public method in your classes". Cool.
Another Free CakePHP E-book
Although he took some heat in the Google Group for not releasing the book in English, I applaud Azril Nazli on his free CakePHP E-book, Ebook Panduan Bina Blog Guna CakePHP versi 0.1. Here's my review: I can't understand a word, but damn does it look pretty. I'm like 75% jealous of how much better his looks then mine.
CakePHP Session at the Next PHPMelb Meeting
If you're live around Melbourne, Aus you should check out the next PHPMelb meeting: "Baking with CakePHP and Beginners Series Planning Session". It takes place on Monday, Aug 17, which may already be past...Aus is like a week ahead of the US in timezones, right? note to self: time based jokes only work if you can get the post out on time.
Anti-CakePHP Tweet of the Week
This is a new feature, where I pick out my favorite anti-CakePHP tweets(s). This one comes from @sjmadsen:
If the CakePHP and SimpleTest web sites/documentation were indicative of all PHP developers, it'd be safe to say they're illiterate.
Tickets and Commits
This is probably the last time I'll be linking to tickets over at the trac with the move to code.cakephp.org. And it could be the last time I link to tickets at all, unless code.cakephp.org adds a ticket RSS feed. I know, I know the code is open source - I should just add the feature and see if the Cake Team will include it TheChaw/code.cakephp.org isn't open sourced...not sure why I thought it was. See the comment below from Mark Story on using the timeline feed.
Convenience Functions
I thought this one was interesting. It covers removing the convenience functions (like e(), ife(), am()...) in basics.php from the core. Don't worry, though, it looks like they'll still be available, for the 1.2-1.3 branches at least.
Id...That is all
In The Groups
Remove PHP 5.3 Deprecation Warnings
If you're trying to run the 1.2 branch on PHP 5.3 you may get a bunch of deprecation warnings. Here's a quick tip (which involves a core hack) to get rid of them.
In The Blogs
Teknoid has a post of how to build CakePHP shells.
Nate comes out of blogging retirement to post some secrets on admin routing.
Miles J has a post on plurals w/ Cake's l10n and i18n.
Ronny Vindenes posts a tutorial on how to integrate SlickMap CSS into your Cake app to get pretty sitemaps.
Code
From Miles J: a Feed Aggregator Component
From @markgandolfo: a Cycle CSS helper to alternate table row colors similar to how Rails does it.
@savant is converting all his CakePHP code to plugins including his GitHub plugin plugin, which provides an easy way to install plugins from GitHub.
From @utoxin: a behavior to automatically encrypt and decrypt a DB field.
From Nick Baker: A PayPal IPN plugin
From pointlessjon: an awesome fixturize plugin. I use this one and highly recommend.
From Graham Weldon: An automatic JavaScript includer helper
In The Wild
Just a ton of new sites since the last digest...
From @d4z0: feelv4.com - a Euro Honda site.
From @smalltowneye: smalltowneyes.com - a community site that integrated the "eye" part of the domain name just a tad too much into the design.
From Nik Chankov: linxspy.com - a service to make sure that any link exchanges are maintained. The service is free, for a small fee you can have Nik visit the homes of people who pull your links and remind them not to fuck with your page rank.
From @gerhardsletten: www.gersh.no - a new homepage.
From @gaslamp: adamwes.com - a math and science tutoring site. You know how ads for escort services always show really hot dudes/chicks, but when the person arrives they have 300 pounds stuffed into an outfit for a 125 pound person? Uhh...at least that's what I've heard from people... Anyway, all the "tutors" in the slideshow on the homepage are attractive and fit (you could say model-esq), but your tutor is probably caring a bucket of wings when they arrive. Who would have thought that escort services and math/science tutors services would have something in common?
Via email - SimcoeDining.com - a food/fun site fort the Barrie and the Simcoe-County area. If you read the URL fast it looks like sim coed ining.
I'm Out!
And on that note don't forget to subscribe to my feed or follow me on twitter.
As always if you think I missed something leave a comment. Or if you do something interesting and want it included in the next digest, send me an email.
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.
