CakePHP: Watch Out for the compact() Function
Okay, so maybe this caveat isn’t specific to CakePHP since the function is a native PHP function, but I just spent the past hour trying to figure out why variables that I clearly set in my controller weren’t available to my view. I’ll never get that hour back, but maybe I can keep someone else from losing it. As far as I’ve been able to tell, this particular behavior isn’t documented, but I haven’t done any kind of exhaustive search.
The compact() function exists as a shorthand function to create an array of variables. The PHP documentation does a nice job of detailing the function and providing a few simple examples, so I won’t belabor that point. Within CakePHP, it’s a handy shortcut for passing variables from a controller to a view. In my case, I have a vendor application form with a few variances that I need to manage. Without using compact(), a snippet from the action method of my VendorsController would look like this:
public function index() {
…
$vendor_type = ‘Food’;
$application_type = ‘Commercial’;
$states = $this->Vendor->Address->State->find (
‘list’,
array ( ‘order’ => ‘State.title’ )
);
$this->set ( ‘vendor_type’, $vendor_type );
$this->set ( ‘application_type’, $application_type );
$this->set ( ‘states’, $states );
…
}
That’s not an intolerably verbose example, but it’s easy to see how it could become so. Being the laconic kind of guy that I am, though, I decided to use the compact() function to cut down on the verbiage. Now my action code looks like this:
public function index() {
…
$vendor_type = ‘Food’;
$application_type = ‘Commercial’;
$states = $this->Vendor->Address->State->find (
‘list’,
array ( ‘order’ => ‘State.title’ )
);
$this->set ( compact ( ‘vendor_type’, ‘application_type’, ‘states’ ) );
…
}
That’s a little better, but there’s a caveat.
Using this example, I went to my view code and tried to access my $vendor_type variable only to get an undefined variable error. After working my way through various debugging techniques, I pulled out the big gun. In my view, I dumped the output of PHP’s get_defined_vars() function and found that my $vendor_type variable had been renamed to $vendorType. I don’t know if the change was made by CakePHP or by PHP itself, but I didn’t expect it (nor do I have any reason to believe that I should have expected it) and the difference is as fatal to an application as it is obvious.