Category: Controllers

Q: Cakephp call component method from another component

When a user trigger an event (page view)I have two components:

MailerComponent.php: To handle outgoing emails

LoggerComponent.php: To log and trace user behaviour data

I used to call components separately, for example:

Scenario: When a user trigger an event (page view)

Steps (e.g. /hot-to-contact-us)Function to be called
system log user action into db$this->Logger->pageView($user_id, $page);
system send a welcome email to user$this->Mailer->sendWelcomeEmail($user_id);
returns $email_id
finally, log email send/receive status into db$this->Logger->email($email_id, $user_id);

The point is I have to return an email_id in order to pass to LoggerComponent, and I want to make the code cleaner by calling $this->logger->email() directly from MailerComponent. Is this possible?


3 Answers

Version: 3

user
Kake

3

The following cheat sheet shows how components can be loaded in CakePHP.

MethodsIn ControllerIn Component
via $this->loadComponent();YesNo
via property declaration in classYesYes
via instantiationYesYes

The loadComponent() Method

// In your controller.
// from official documentation
public function initialize()
{
    parent::initialize();
    $this->loadComponent('Math', [
        'precision' => 2,
        'randomGenerator' => 'srand'
    ]);
    $this->loadComponent('Csrf');
}

Property Declaration in Class

You may include other component via:

namespace App\Controller\Component;

use Cake\Controller\Component;

class MailerComponent extends Component
{
    // The other component your component uses
    public $components = ['Logger'];

    public function sendWelcomeEmail($user_id)
    {
        
        //send email; get email_id
        //...

        //log email status to db
        $this->Logger->email($email_id, $user_id);
    }
}

check this: Using Other Components in your Component

Instantiation

You can also instantiate logger component manually by yourself.

use Cake\Controller\Component; 
use Cake\Controller\ComponentRegistry ; 
use App\Controller\Component\{your class name};

then

$this->Logger = new LoggerComponent(new ComponentRegistry(), [{array of options}]);

Good question, this is my code:

class YourComponent extends Component 
{

    private $Controller = null;

    public function initialize(array $config) 
    {
        parent::initialize($config);
        $this->Controller = $this->_registry->getController();

        //load another component
        $this->Controller->loadComponent('Another');
    }

    public function setController($controller) 
    {
        $this->Controller = $controller;
    }
}
achao
achao

9

You can import a component in another like this:

class SecondComponent extends Component
{
    public $components = ['First'];
}
Luke
Luke

3