Saturday, May 28, 2011

Overriding Helpers in CakePHP 1.3

CakePHP 2.0 will sport an exciting new feature where you can change the alias of your helpers to something else.  For example, you've extended the FormHelper to automatically include JQuery UI classes for relevant widgets.  Instead of having to rename $this->Form in all your views to $this->JQueryUIForm, you can specify an alias that the helper should be loaded as, and override the default $this->Form.  Awesome!

But I can't wait for CakePHP 2.0 to be released.  I want to do it in CakePHP 1.3, and here's how.

First, if you extend an existing Helper, you'll need to make sure the original class is loaded before your extended class is.  For this, I've taken the lazy road, and have loaded Form, before my JQueryUIForm in the AppController.  If you wanted to be a bit neater, you could put a requires_once at the top of your extended helper file, just to make sure the definition is there.  I don't think you'll be able to get away with an App::import() for ClassRegistry::init(), because the base class will need to be loaded at compile time, not run time.

Next, add a beforeRender() to your extended helper. Grab the view for the context the helper is running in, and override the alias with a reference to your own helper. Job done!

class JQueryUIFormHelper extends FormHelper {
 
 function beforeRender() {
  $view =& ClassRegistry::getObject('view');
  $view->Form = &$this;
 }
   
 function text($fieldName, $options = array()) {
  $options = $this->addClass($options, 'ui-widget');
   
  return parent::text($fieldName, $options);
 }
  
}


I'm not sure that you'll be able to override the plain variable reference to the helper (i.e. $form->text()) with this method. Might have to have until CakePHP 2.0 for that feature.

5 comments:

  1. Do you have an email i can contact you on?

    I have a but of side CakePhp work. You should be able to look me up.

    ReplyDelete
  2. Hi A.

    I'm gainfully employed at the moment, but thanks for the offer.

    R.

    ReplyDelete
  3. You can use the standard "Form" variable and methods by removing the "&" in front of $this on line 5. Not sure how PHP4 will like this, but PHP5 works just fine. I also called parent::beforeRender() for good measure.

    ReplyDelete
  4. @thril: Indeed. $this is a reference, by definition, and assigning it to another variable will assign the reference. +1 to you!

    ReplyDelete
  5. Worked great, thanks stranger :P

    ReplyDelete