I suck at screencasts; I know this. If I keep doing them, I’m bound to get better, right? Is it possible to get worse at something the more you do it? Anyway, I made a quick screencast showing off some CakePHP features with Komodo IDE. Leave a comment with your favorite CakePHP related IDE trick.

Screencast

Links and Snippets

The CakePHP Extension

http://community.activestate.com/node/2794

The bake script

Make sure to put %p in the “Start in” field. This tells Komodo to cd to the directory of the active project first. For this to work your project file needs to be in /app.
bake

The bake script

In addition to adding %p like above, you also need to add %b to the command. This will take the current file name, less the extension, and pass it as a parameter.
cake

Bookmark This Post

del.icio.us Digg FURL Yahoo! My Web 2.0 Reddit

There are a few new Bakery articles lately that use cURL for remote calls (see here and here), rather then Cake’s HttpSocket lib. This is probably because HttpSocket doesn’t have a mention in the CookBook (yet :) ).

Here’s a quick primer on using HttpSocket as an alternative. I’ll re-write the code from the TwitterMail article as an example.

First, their original code:

$curl_twitter = curl_init();
curl_setopt($curl_twitter, CURLOPT_URL, 'http://twitter.com/account/verify_credentials.json');
curl_setopt($curl_twitter, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl_twitter, CURLOPT_HEADER, false);
curl_setopt($curl_twitter, CURLOPT_USERPWD, $this->data[$this->name]['twitter_username']
                                            .":".$this->data[$this->name]['twitter_password']);
curl_setopt($curl_twitter, CURLOPT_POST, true);
curl_setopt($curl_twitter, CURLOPT_RETURNTRANSFER, true);
$curl_result = curl_exec($curl_twitter);
curl_close($curl_twitter);

Now using HttpSocket instead:

App::import('Core', 'HttpSocket');
$HttpSocket = new HttpSocket();
$request = array('auth' => array('user' => $this->data[$this->name]['twitter_username'],
                                 'pass' => $this->data[$this->name]['twitter_password'],
                                 'method' => 'Basic'),
                 'uri' => 'http://twitter.com/account/verify_credentials.json');
$result = $HttpSocket->request($request);

I explicitly set the auth method to “Basic” here. This is because the default auth method is “basic” – notice the lowercase “b”. Twitter doesn’t like this. This is fixed in the trunk version of Cake, but if you’re using the latest release (8004), you’ll need to set it manually.

There you go. Nine cURL lines becomes four lines of Cake code. In addition the dependency on the cURL lib is removed as HttpSocket uses PHP’s fsockopen. Cake’s HttpSocket doesn’t have all the features of cURL, but it’s certainly handles most web services with no problem.

Bookmark This Post

del.icio.us Digg FURL Yahoo! My Web 2.0 Reddit

I decided to cut short my giveaway of a copy of CakePHP Application Development. I’m not sure why I originally made the end date Feb 29th Feb 28th. I guess it seemed like a good ending point. In actuality, pretty much everyone who was interested entered in the first two days. There was no real point in dragging it out after that.

The winner is Nick, with comment #3366:

I like cakePHP and I can read; therefore, I’m a perfect candidate!

Congrats, Nick. I’ll be contacting you shortly via email to get the shipping info.

The winning comment was picked randomly. Here’s the query I used:

SELECT *
FROM wp_comments
WHERE `comment_post_ID` = 400
ORDER BY rand( )
LIMIT 1

Thanks to everyone who entered!

Bookmark This Post

del.icio.us Digg FURL Yahoo! My Web 2.0 Reddit

In the CakePHP digest I posted the other day I linked to Neil Crookes’ CakePHP datasource for using Yahoo! Search BOSS. BOSS stands for Build your Own Search Service and is a cool way to integrate search directly into your app.

I mention that Neil’s code would make a really cool plugin. This sparked a discussion as to whether this was possible with Cake’s current plugin architecture.

The issues where:
1) How to get the datasource configuration, which would normally go in /app/config/database.php
2) How to reference the datasource class itself.
3) How to handle the custom route.

I was able to knock off the first two. The third one isn’t possible without altering the base route file (/app/config/routes.php), but by renaming the controller and action I got the default route looking pretty good. Here are the changes I made to Neil’s code.

Made It Into A Plugin

I moved all of Neil’s code into /app/plugins/yahoo_boss. Then I created YahooBossAppModel and YahooBossAppController which are just empty classes, but are required for plugins if you want to access them from a URL. I then altered the controller and model to extend those classes.

Handling The Datasource And Config

Cake allows you to add datasources using ConnectionManager::create, so I figured I could use this from anywhere in the plugin to setup the datasource. First thing I needed was to load the config class. Since database.php already has a DATABASE_CONFIG class I would need to use a different name. I went with YAHOO_BOSS_CONFIG and put it in /app/plugins/yahoo_boss/config/yahoo_boss.php.

Now I needed to manually load this file so the class was accessible. I did an quick test with php’s include to make sure this would work, but then moved to Cake’s App::import.

App::import(array('type' => 'File', 'name' => 'YahooBoss.YAHOO_BOSS_CONFIG', 'file' => 'config'.DS.'yahoo_boss.php'));

I’m open to suggestions if there is a cleaner way to do this. I also needed to load the datasource itself from /app/plugins/yahoo_boss/models/datasources/yahoo_boss_source.php.

App::import(array('type' => 'File', 'name' => 'YahooBoss.YahooBossSource', 'file' => 'models'.DS.'datasources'.DS.'yahoo_boss_source.php'));

Then it was just a matter of creating an instance of YAHOO_BOSS_CONFIG and using that to add the datasource to the ConnectionManager.

$config =& new YAHOO_BOSS_CONFIG();
ConnectionManager::create('yahooBoss', $config->yahooBoss);

I put all this code in the constructor for the search model.

Dealing With The Routes

This issue isn’t fixable at the moment. There is no way to inject routes from a plugin. So instead I renamed the controller and action so that the default route was a bit more friendly. The user still has the option of changing the route by editing their routes config, but it isn’t really necessary.

First I renamed the controller from “searches” to “search”. Yea, it doesn’t really follow the Cake convention…oh well. Then I moved the results action to index. This allows the search to be accessed at “/yahoo_boss/search”. Not bad. I re-added the results action, which basically just points to the index action. So after a search the url will be “/yahoo_boss/search/results/term:whatever”. Again, not perfect, but pretty good.

Wrapping Up

Again all the original code is from Neil Crookes originally posted on his blog. This was mostly an exersize to see if it would be possible to move it to a self contained plugin. You can see it in action here or some results here. That demo is setup to search this blog. All the code is availabe in GitHub.

Bookmark This Post

del.icio.us Digg FURL Yahoo! My Web 2.0 Reddit

cakephp-application-development

This giveaway has ended. Here’s the winner.

I’m not sure if this is going to be frowned upon, but I’m giving away my review copy of CakePHP Application Development (reviewed here). I figure I don’t have much use for it, so maybe someone else will benefit.

Book is in A+++ condition, adult owned, read once. I’ll pay shipping. All you have to do is leave a comment on this post – although it would be cool if you signed up for my RSS feed or followed me on twitter. On Feb 28th, 2009 Feb 16th, 2009 I’ll run some fancy SQL and select one of the comments randomly.

If you already know Cake it probably isn’t worth entering as the book is geared towards beginners. I know some of the core devs spend so much time coding the framework they probably couldn’t code with the framework (you know who you are), but please refrain from entering.

Good luck!

Bookmark This Post

del.icio.us Digg FURL Yahoo! My Web 2.0 Reddit