Eventos en CakePHP

La versión 2.1 de CakePHP incorporó una de las grandes cosas que le venía faltando a este gran framework de desarrollo de aplicaciones: gestión de eventos, para que la aplicación trabaje siguiendo el patrón Observer. La documentación de CakePHP, completa en montones de temas, es deliberadamente oscura o ambigua en algunos temas de implementación, cosas que no quedan del todo claras. Les transmito mi experiencia en este sentido, que a algunos les puede servir. Y de paso me cuenten si hay alguna manera mejor de hacer lo que yo estoy planteando, jajaja.

Escenario

Estamos trabajando con una aplicación de gestión de un instituto de inglés, que genera cuotas para los estudiantes, y cuando se genera una cuota hay que mandar una notificación por e-mail.

n

Piezas necesarias

La generación y captura de eventos requiere de lo siguiente:

  • Una clase que genere el evento en cuestión, (“Subject”). En este caso, Inscripcion.
  • Una clase que capture el evento, que tiene que implementar la interfaz CakeEventListener (“Observer”).
  • Un lugar donde se cargue la relación entre Subject y Observer. En esto la documentación de CakePHP es oscura y ofrece alternativas sin explicar demasiado cómo se implementan. Decidí usar AppController, la clase padre de los controllers, y el método donde tengo cargada la relación.

Esta es la clase que captura el evento:

class CobrosComponent extends Component implements CakeEventListener
{
	public $components=array('Notificacion');

	public function initialize(&$controller, $settings = array())
	{
		//load required for component models
		if (
$this->uses !== false) {
			foreach($this->uses as $modelClass)
			{
				$controller->loadModel($modelClass);
				$this->$modelClass = $controller->$modelClass;
			}
		}
	}
	public function implementedEvents()
	{
		return array('Model.Inscripcion.cuotas_cobradas'=>'cuotas_cargadas');
	}
	/**
	 * Notifica cuando se cargan cuotas en el sistema.
	 * @param CakeEvent $evento
	 */
	public function cuotas_cargadas($evento)
	{
		// Tengo que mandar la notificacion. Evento->data tiene un arreglo de cuotas.
		$cuotas=$evento->data['cuotas'];
		foreach($cuotas as &$cuota)
		{
				// bla bla bla, hago cosas.
		}
		$parametros=array(
				'cuotas'=>$cuotas
				);
		$this->Notificacion->notificar('PagosController','cuotas_creadas',$parametros);
	}
}
?>

Aquí se puede observar lo siguiente: El CakePHP requiere que la clase implemente el método
ImplementedEvents, que devuelva un array de strings que tenga la lista de eventos que esta clase captura. Este array tiene el nombre del evento, y el nombre del método que será invocado cuando este evento se lance. El método recibe un parámetro llamado events, este es un array que contiene los datos del evento y una clave data donde yo puedo mandar datos propios de la aplicación desde el disparador del evento a quien lo captura.

De este modo yo disparo el evento:

$this->getEventManager()->dispatch(new CakeEvent('Model.Inscripcion.cuotas_cobradas', $this, array(
	'cuotas' => $array_cuotas
)));

Aquí se observa la llamada al disparador de eventos del CakePHP, al que le paso un nuevo evento que acabo de generar, con su nombre, quien lo dispara, y los datos que quiero enviar. Aquí envío un array con las cuotas generadas, por ejemplo.

Y aquí
donde todo se une:

class AppController extends Controller 
{
	public function beforeFilter() 
	{
		parent::beforeFilter();
		$this->Inscripcion->getEventManager()->attach($this->Cobros, 'Model.Inscripcion.cuotas_cobradas');
	}
}

Be the first to comment

Leave a Reply

Your email address will not be published.


*