Does Anyone Want A Tutorial On Observableactions?

[size="3"]Tutorial on ObservableActions?[/size]

In the course of building a RESTful API for a client, I’ve made extensive use of events to make actions reusable and flexible. Since event-handling in actions isn’t widely discussed, I thought I’d make a tutorial covering:

  • Creating a base action class with an init() method and some predefined events (e.g. onAfterConstruct(), onAfterInit())

  • Show how to create custom action events and attach handlers in your controller

  • Build an example GetRecordAction

  • Use event handlers to deal with 403/404/410 situations without cluttering the action code itself

I’m wondering if the community would benefit from a tutorial on this, if this is already a well-known pattern, or if there’s simply a better way to do this.

[size="3"]Principles - Actions should be DRY/SRP[/size]

DRY = Don’t Repeat Yourself

SRP = Single Responsibility Principle

We want classes that are powerful, loosely-coupled, and re-usable. Yii makes it easy to do this, but the documentation/existing tutorials don’t make it obvious how to do this with respect to Actions.

[size="3"]Example Code[/size]

Below is an example of how the GetRecordAction class would be configured in your controller. Note that I’m using anonymous functions in the example. This is just for transparency; in real life you might want to create classes that encapsulate those checks, if only to make them easily re-usable elsewhere in your application.




// In a "BooksController" class...

public function actions()

{

	return array(

		// Retrieve a book from the database

		'getRecord' =>array(

			'class' =>'api.components.actions.GetRecordAction',

			'modelClass' =>'Book',

			'scenario' =>'api.get',

			'onBeforeLoad' =>function($event)

			{

				$accessGranted = Yii::app()->authManager->checkAccess(

					'Books.get.record',

					Yii::app()->user->id,

					array('bookId' =>$event->params['recordPk'])

				);

				if (!$accessGranted)

					throw new CHttpException(403, "EW GETTTOUT");

			},

			'onAfterLoad' =>function($event)

			{

				if ($event->params['record']===null)

				{

					throw new CHttpException(404, "The requested book was not found");

				} else if ($event->params['record']->status==3)

				{

					throw new CHttpException(410, "That book was deleted and is no longer available");

				}

			},

		),

	);

}