I’m getting myself very confused with events! and really hoping someone can help. Firstly, I’m not a programmer (I’m sysadmin by trade) so while I generally understand it, I think I might be missing some of the subtlety. Anyway…
I have a module called authenticate that has a user tracking script in (this logs when a user accesses the site), I am trying to call the function from the base SiteController. So I’ve got this so far…
class AuthenticateModule extends CWebModule
{
public function init()
{
//$this->Usertrack(); (my original calling, but only works within the module)
}
public function onUsertrack($event) {
$this->raiseEvent("onUsertrack", $event);
}
static function Usertrack() {
$tracker = new UserTracking;
$tracker->updatelastonline(1);
}
}
in my site controller, I have tried all manner of ways to make it work! this is my current attempt.
class SiteController extends Controller
{
public function init() {
Yii::app()->user->onUsertrack = array(new AuthenticateModule, "Usertrack");
$e = new CEvent($this, array("user" => 1));
Yii::app()->user->onUsertrack($e);
}
I’m wondering if there is a scope problem, and SiteController doesn’t know where AuthenticateModule is, but it doesn’t give any errors unless I try calling AuthenticateModule directly.
I think my problem is probably that I’m just missing something about how events work! Hopefully you can help out.
Note: code written from top of head, so not checked for typos.
I’m not entirely sure what your overall objective is, but it seems like you ultimately just want to call a function in the AuthenticateModule class? If so, you can do this fairly easily without getting caught up in events (which I haven’t really used yet myself, so my answer may be too simplistic).
First of all, make sure the Authenticate module is enabled in the configuration. Open the protected/config/main.php file, and find the ‘modules’ key of the array. It’s the one where by default the ‘gii’ array is an item of. Add the Authenticate module to it if not available yet:
Suppose the Authenticate module has a trackTheUser() method like this:
class AuthenticateModule extends CWebModule
{
public function trackTheUser($userId)
{
// code to do whatever tracking you want
echo 'Tracking user with ID: ' . $userId;
}
}
To call this method, you can use this code from (almost) anywhere, like in the init() function of your controller like you do now:
class SiteController extends Controller
{
public function init() {
$userId = 1; // User ID usually retrieved from database or whatever, but 1 for demo.
// $module holds an instance of the AuthenticateModule class.
$module = Yii::app()->getModule('authenticate');
$module->trackTheUser($userId);
// Alternative short version: Yii::app()->getModule('authenticate')->trackTheUser($userId);
}
Part of the reason for trying to get it working with events was simply to understand how events work, 'cause I’m sure they’ll come in handy when I understand how the hell they work.
I spent a good amount of time studying Yii events before I finally grokked it. These are my notes.
Search "function on" in Yii framework to discover included event handlers
Workflow
Declare an event by implementing a method beginning with ‘on’
The method used to declare an event becomes the default event handler
public function onClick($event)
{
$this->raiseEvent('onClick', $event); // onClick is event name
}
Attach 1 or more event handlers (several ways to do this)
$component->onClick = 'handleOnClickEvent'; // Using component property, local method
$component->onClick->add('handleOnClickEvent'); // Using component property, local method
$component->getEventHandlers('onClick')->add('handleOnClickEvent'); // Local method
$component->attachEventHandler('onClick', 'handleOnClickEvent'); // Local method
$component->attachEventHandler('onClick', 'global_function'); // Global function
$component->attachEventHandler('onClick', array('ClassName', 'staticMethodName'); // Class method
$component->attachEventHandler('onClick', array($object, 'objectMethod')); // Object Method
$component->attachEventHandler('onClick', function($event){echo 'Click!';}); // Anonymous function
Event handlers are added to end of handlers list but more granular control is available
$component->getEventHandlers('onClick')->insertAt(0, 'handleOnClickEvent'); // Add new handler at top of list
$component->detachEventHandler('onClick', 'handleOnClickEvent'); // Remove handler from onClick event list
Event handler signature
function handleOnClickEvent($event)
{
...
// $event->handled = true; // ...to stop processing remaining unexecuted handlers
parent::handleOnClickEvent($event); // If parent implements handleOnClickEvent()
// return false; // ...to prevent event from happening, in onBefore... event handlers only
}
Set $event->handled to true to prevent remaining unexecuted handlers from being invoked
Call the parent’s same event handler (if implemented) just before the end of the method
Return false in a before event handler to prevent the event from happening altogether
Trigger the event in a controller
$event = new CEvent($this); // $this is sender of the event
$component->onClick($event);
Can optionally pass additional parameters
$event = new CEvent($this, array('user'=>$user)); // Passing one additional parameter
$component->onClick($event);
All subscribed handlers are called automatically, unless and until a handler sets $event->handled, which will then halt further execution of handlers