CakePHP Expandable Behaviour Tip

When YYZtech was being updated to use the VSS (Venue Storage System) from the previous system, it became clear that VSS needed to be updated as well. One of the original goals of VSS was that it could be a directory system for different kinds of things as long as they where physical venues of some kind and so they had certain properties like an actual address, hours they open to the public, etc.

As part of that, a way of storing “meta” information was needed, that is information that was unique to a venue or type of venue that not all would have, much like WordPress lets additional information about a post be stored in a separate table which makes, say, adding an ISBN number field to book reviews easy.

After rolling our own for several projects, Felix Geisendörfer’s Expandable behaviour was chosen because it was simple to set-up and use and it just worked. Hopefully CakePHP at some point includes a similar functionality as an “official” add on much like virtual fields was added in CakePHP 1.3

Which leads to a “gotcha”….
One issue combining virtual fields and the Expandable behaviour is that virtual fields can end up being interpreted as new fields by Expandable and Expandable then saving them. What’s worse, is that when the table entry is loaded, the virtual field and field from Expandable are combined with one overwriting the other.

This particular behaviour happened when we added a way of cloning venues, removing and replacing certain information along the way. The reason for this would be adding a chain store location; the address and phone number would change but the description or products sold probably wouldn’t. Now the table that stored the venues had a virtual field, full_name, that contained the name and sub-name of a venue (e.g. “Joe’s Bar”, “and Delicatessen” as “Joe’s Bar and Delicatessen”) which Expandable saw as a new field and saved the virtual field to its table and led to about 20 minutes trying to figure out if there was some kind of weird caching issue going on.

Anyways, the fix was to turn off the virtual fields like so:
$this->Venue->virtualFields = false;

…and that was the end of that problem.

CakePHP database config quick-tip

Most CakePHP programmers have seen this simple way of storing the development and production database settings in one file:

  1. class DATABASE_CONFIG {
  2.     var $prod = array(
  3.        
  4.         'database' => 'live_mysite'
  5.     );
  6.  
  7.     var $test = array(
  8.        
  9.         'database' => 'local_mysite'
  10.     );
  11.  
  12.    // the construct function is called automatically, and chooses prod or dev.
  13.     function __construct() {
  14.         //check to see if server name is set (thanks Frank)
  15.         if(isset($_SERVER['SERVER_NAME'])){
  16.             switch($_SERVER['SERVER_NAME']){
  17.                 case '127.0.0.1':
  18.                     $this->default = $this->test;
  19.                     break;
  20.                 default:
  21.                     $this->default = $this->prod;
  22.                     break;
  23.             }
  24.         } else { // we are likely baking, use our local db
  25.             $this->default = $this->test;
  26.         }
  27.     }

If you haven’t, check out Edward A. Webb’s original post from 1998 2008.

This same technique can be used in the bootstrap.php file for other settings that change based on the server, for instance GoogleMap keys:

  1. if ( strpos( $_SERVER['HTTP_HOST'],'MySite.com') !== false)
  2.     Configure::write('GMAP_KEY', 'ABQIAA…qcPrtZgKHQ');
  3. else
  4.     Configure::write('GMAP_KEY', 'ABQIAB…e6qfWeeY8Q');

However, when baking a model, the database file only defines two types: prog and test so you pick one and end up with a model file with a line like:

  1. var $useDbConfig = 'test';

in your baked model that doesn’t cause any problems right up until upload it to your live server late one night and start getting errors about being unable to make a connection- guess who did that?

The solution is simple: just define a default

  1. var $default;

somewhere in the file, now when you bake cake will give you the option of using the default connection which won’t add any problem-causing $useDbConfig to your model.

Hope this saves someone 20 minutes :)

Adding robots meta-tag to a CakePHP view

Here’s a little how-to I discovered a few months ago while I was working on SimcoeDining.com and realized that Google was indexing a whole lot of mostly blank pages.

To solve this, I figured I’d better put a no-index on those pages fast; after mucking around with CakePHP’s html->meta handler (because I wanted the meta tag in the header where it belonged) and not finding anything, I came up with:

  1. $html->meta('robots', null, array('name' => 'robots', 'content' => 'noindex') ,false);

BTW: The pages where empty at the time because there wasn’t a lot of data in the system, so a lot of searches where coming up empty- that’s been “fixed” now too.

Hopefully this saves someone else 20 minutes :)