Extending CakePHP’s core components

Published on and tagged with cakephp  component

In a recent comment David Cournoyer shared a tip about extending CakePHP’s core components and I think it could also be useful for others.

Let’s say we want to add a method to the request handler component. And so we create a new class which inherits from the request handler component:

// app/controllers/components/my_request_handler.php
App::import('Component', 'RequestHandler');
class MyRequestHandlerComponent extends RequestHandlerComponent {
    public function example() {
        // do something
    }
}

To use this component, we have to add it to the $components array of our controller:

// app/app_controller.php
class AppController extends Controller {
    public $components = array('MyRequestHandler');	
}

Nothing new so far. However, a disadvantage of this approach is that you have to use the component in the following way:

$this->MyRequestHandler->isAjax();
$this->MyRequestHandler->example();

Wouldn’t it be nice if we could use it in the usual way?

$this->RequestHandler->isAjax();
$this->RequestHandler->example();

And yes, it is possible. For this purpose we have to override Controller::constructClasses():

// app/app_controller.php
class AppController extends Controller {
    public $components = array('MyRequestHandler');
	
    public function constructClasses() {
        parent::constructClasses();
        $this->RequestHandler = $this->MyRequestHandler;
    }
}

Happy baking!

12 comments baked

  • John

    That is so cool… there are so many possibilities. But the best part – like you say – is you can just use it in the normal way.

  • cakebaker

    @John: Thanks for your comment and I’m glad to hear it is useful for you!

  • Nik Chankov

    I was searched for such functionality recently, but for some reason I’ve discontinued the research. One of the possible additions is to extend the html class so it could handle links depending from permissions. Let’s say if user has right to access Edit window the link to be visible, if not just disable it, or completely hide.

    Thanks for the hint Daniel.

  • cakebaker

    @Nik: Thanks for your comment!

    Well, this approach doesn’t work for helpers, because they are created later… However, in an earlier article I described a possible idea for how you can “hack” core helpers.

    Hope that helps!

  • Teh Treag

    Since AD7six pointed it out to me, I prefer to handle it in the class, instead of in the controller.

    // app/controllers/components/my_request_handler.php
    function initialize(&$Controller, $config = array()) {
        $this->settings = array_merge($this->settings, $config);
        $this->Controller =& $Controller;
        $Controller->RequestHandler =& $this;
    }
  • cakebaker

    @Teh Treag: Thanks for sharing this alternative approach!

    Personally, I prefer to handle it in the controller, as I think a component shouldn’t care about the name under which it will be available in a controller. That’s the responsibility of the controller. But in the end it is probably just a matter of taste.

  • daniel

    Hm this isn’t working for me. When i call a method by the old name, I get an error:

    Fatal error: Call to undefined method stdClass::send()

  • cakebaker

    @daniel: Can you post the relevant code? And which CakePHP version do you use?

  • Rebuild Project Notes #2 @ Robot Minds of Robot Slaves

    [...] Info: How to extend the CakePHP AuthComponent. More on extending AuthComponent I found the Joomla boilerplate over here. no comments yet.« Rebuild Project Notes #1 [...]

  • Rebuild Project Notes #5 @ Robot Minds of Robot Slaves

    [...] is an interesting article on how you can extend core CakePHP components. I am going to be using that author’s recommendations in my effort. The gist of his advice is [...]

  • Darmowa Strona Internetowa

    I view something genuinely special in this web site.

  • ionas

    while still useful (for understanding) simply go with

    $components = [
    ‘Paginator’ => ['className' => 'IonasPaginator'],
    ]; // now

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License