Yahoo Search BOSS as a CakePHP Plugin
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.

8 Comments
Thank you
...if you can be bothered, you might want to update the links to your Git repos in your blog entries though. ;)
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