CakePHP 3 comes packaged with an awesome Events System which follows what had already been done in version 2 of this framework. It is a hidden gem that many developers are not aware of, but when found and used can be both helpful and beautiful.

This guide will provide a few step by step examples that allows you to take advantage of it and use in your application. To fully learn of all the ins and outs of the Events System, you can visit the CakePHP Cookbook - Events System section.

Scenario: You have an application that allows users to register and login. You would like to receive an email everytime a user creates an account. In addition, you want to create an entry in your log file when a user removes his/her account.

Step 1:

In your UsersController.php find the method you use to register new accounts. For the sake of this example, we will assume the following register() method. The following code (in between // ######) will allow your the other parts of your application to be informed when a user creates an account.


// src/Controller/UsersController.php
namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\Event;

class UsersController extends AppController
{
    // ....
    public function register()
    {
        $user = $this->Users->newEntity();
        if ($this->request->is('post')) {
            $user = $this->Users->patchEntity($user, $this->request->getData());
            if ($this->Users->save($user)) {         
      
                // #####################################################
                $event = new Event('Model.Users.afterRegister', $this, ['user' => $user]);
                $this->eventManager()->dispatch($event);
                // #####################################################

                $this->Flash->success(__('The user has been saved.'));
                return $this->redirect(['action' => 'add']);
            }
            $this->Flash->error(__('Unable to add the user.'));
        }
        $this->set('user', $user);
    }

    public function delete($id = null)
    {
        $this->request->allowMethod(['post', 'delete']); 
        $user = $this->Users->get($id); 
        if ($this->Users->delete($user)) { 

          // ##################################################### 
            $event = new Event('Model.Users.afterRemove', $this, ['user' => $user]); 
            $this->eventManager()->dispatch($event); 
            // #####################################################

            $this->Flash->success(__('The user has been deleted.')); 
        } else { 
            $this->Flash->error(__('The user could not be deleted. Please, try again.')); 
        } 
        return $this->redirect(['action' => 'index']); 
  }
}

Step 2:

Next step is to register the callback for the event you just created on Step 1. This can be done several ways, but the preferred way would be using Listeners.


// src/Event/UserListener.php
use Cake\Event\EventListenerInterface;
use Cake\Log\Log; 
use Cake\Mailer\Email; 

class UserListener implements EventListenerInterface
{
    public function implementedEvents()
    {
        return [
            'Model.Users.afterRegister' => 'afterRegister',
            'Model.Users.afterRemove' => 'afterRemove',
        ];
    }

    public function afterRegister($event, $user)
    {
        $email = new Email('default');
        $email->setFrom(['support@example.com' => 'Example Site'])
              ->setTo('admin@example.com')
              ->setSubject('New User Registration - ' . $user['email'])
              ->send('User has registered in your application');
    }

    public function afterRemove($event, $user)
    {
        Log::write('debug', $user['name'] . ' has deleted his/her account.');
  }
}

Step 3:

The last step in this process is to attach the UserListener object to EventManager. This can be done anywhere, but in this example we are going to place it in the `bootstrap.php` file


// config/bootstrap.php
use App\Event\UserListener;
// .....
$userListener = new UserListener();
EventManager::instance()->attach($userListener );

 

That is pretty much all you have to do to use Events in your application. You can as fancy as you want by creating other events and use the Listener you just setup to monitor those events or other events that are setup by default within CakePHP.