Yahoo Search BOSS as a CakePHP Plugin

Posted by Matt on Tue, Feb 10 2009

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.

Posted in GitHub

8 Comments

Neil Crookes said on Feb 11, 2009
Great stuff Matt, nice one.
Kjell said on Feb 20, 2009
weee.. took me 2 minutes to get this running. so awesome! :)

Thank you
Brendon Kozlowski said on Jan 14, 2010
I love you for the instructions here. I can use it to incorporate my datasource in to a plugin. Thanks, Matt!

...if you can be bothered, you might want to update the links to your Git repos in your blog entries though. ;)
Brendon Kozlowski said on Jan 28, 2010
I've found that the code provided in the constructor of the model seems to not be needed (as of v1.2.5)? It caused errors on my plugin when working from a shell - and it seemed to have completely skipped it when not running from a shell (no idea why, I didn't debug that part thoroughly). However, after removing it, it seems to work OK on a standard setup. I'm about to test it on the production server which has the APP folder below the webroot.
Brendon Kozlowski said on Jan 28, 2010
Yeah, it worked just fine after I commented out the __construct() method in the plugin's model class. This is with my own plugin though, I have not tested it specifically with the Yahoo BOSS plugin here, though I'd imagine the same functionality would occur.
Matt said on Feb 01, 2010
Awesome. Thanks for posting. I'll check it out with this plugin and update the instructions.
Brendon Kozlowski said on Feb 19, 2010
I now know why it worked without a problem: I had remnants of the code prior to it being wrapped in to a plugin still in the app path. Once these files were removed, I am now experiencing DataSource and missing models errors like you wouldn't believe. I'm obviously missing something - even after adding the __construct() method back. Sorry to incorrectly inform you, Matt.
Angel S. Moreno said on Jul 08, 2010
Hey matt, I ran into a bit of a snag. I followed your instructions and I get this:

Fatal Error (256): ConnectionManager::getDataSource - Non-existent data source default

I tried defining a var default in the config file but I've had no luck.

Add new comment