Need help on Triggering and Consuming Event from Controller / Trait


#1

My project has 2 routing prefixes apart from default route:

  1. Admin - all urls are accessed via project.com/admin/xxx
  2. Manager - all urls are accessed via project.com/manager/xxx

Since both “sections” of the app have user login (login and logout methods in UsersController) - I’m attempting to isolate these functions into a trait named LoginTrait and include the trait in UsersController under Admin and Manager.

LoginTrait

namespace App\Traits\Controller;

use Cake\Event\Event;

trait LoginTrait {

    /**
     * Login method
     *
     * @return \Cake\Http\Response|null
     */
    public function login() {

        $user = $this->Users->newEntity();

        if( $this->request->is( 'post' ) ) {

            try {

                $userDetails = $this->Users->find()
                    ->where( [ 'Users.username' => $this->request->getData( 'username' ) ] )
                    ->first();

                if( !$userDetails )
                    throw new Exception( __( 'Invalid username or password.' ) );

                switch( $userDetails->auth ) {
                    // Database Authentication
                    case 'db':
                        $user = $this->Auth->identify();
                        if( $user ) {
                            $this->Auth->setUser( $user );

                            // Login success
                            $event = new Event( 'Controller.Users.afterLogin', $this, [
                                'status' => 'success'
                            ] );
                            $this->eventManager()->dispatch( $event );

                            return $this->redirect( $this->Auth->redirectUrl() );
                        } else
                            throw new Exception( __( 'Incorrect username or password.' ) );
                        break;

                    // AD Authentication
                    case 'ldap':
                        $authenticated = $this->Users->adAuthenticate( $this->request->getData() );

                        if( $authenticated ) {
                            $this->Auth->setUser( $userDetails );

                            // Login success
                            $event = new Event( 'Controller.Users.afterLogin', $this, [
                                'status' => 'success'
                            ] );
                            $this->eventManager()->dispatch( $event );

                            return $this->redirect( $this->Auth->redirectUrl() );
                        } else
                            throw new Exception( __( 'Incorrect username or password.' ) );
                        break;

                }

            } catch( Exception $ex ) {
                $this->log( $ex->getMessage(), 'debug' );
                $this->Flash->error( $ex->getMessage() );
            }
        }

        // Set default layout
        $this->viewBuilder()->setLayout( 'ui_login' );
    }

    /**
     * Logout method
     */
    public function logout() {
        $this->Flash->success( __( 'Good-Bye' ) );
        $this->redirect( $this->Auth->logout() );
    }

}

Admin\UsersController

namespace App\Controller\Admin;

use App\Traits\Controller\LoginTrait;

/**
 * Users Controller
 *
 * @property \App\Model\Table\UsersTable $Users
 *
 * @method \App\Model\Entity\User[] paginate( $object = null, array $settings = [] )
 */
class UsersController extends AppController {

	use LoginTrait;

    public function initialize() {
        parent::initialize();
    }

}

Manager\UsersController

namespace App\Controller\Manager;

use App\Traits\Controller\LoginTrait;

/**
 * Users Controller
 *
 * @property \App\Model\Table\UsersTable $Users
 *
 * @method \App\Model\Entity\User[] paginate( $object = null, array $settings = [] )
 */
class UsersController extends AppController {

	use LoginTrait;

    public function initialize() {
        parent::initialize();
    }
	
	// WHAT DO I DO HERE TO CONSUME THE EVENT???

}

The login process under Manager involves a couple of extra steps (e.g. writing some additional info. as Session variables. My idea is:

  1. Dispatch an event (e.g. Controller.Users.afterLogin) from the Trait following successful login.
  2. Consume the event only in UsersController under Manager and execute the additional code.

I’m totally new to events and looking for some guidance here on how to go about it.

Thanks.