Passing data between firing an event and handling the fired event
New to Vanilla, PHP, etc. and using it on Win7 localhost wamp server.
Is it possible to fire an event and include some data as part of the event context to be processed by the handler of the event?
For example ('hallucinatory code' in the plugin's default.php):
...
// When firing the event, include a string in the event firing context
$this->FireEvent('BeforeDiscussionRender', 'SomethingOrOther'));
...
// Handling the event before rendering ... act on the $EventContext
public function Base_Render_Before($Sender, $EventContext = '') {
if (isset($EventContext)) {// DoSomething} else {//DoSomethingElse};
}
Best Answers
-
Tim Vanilla Staff
When you fire an event, the handler always gets passed a reference to the firing object ($Sender). So you can set data on that object before firing, and read it off the $Sender in the handler.
$this->EventArguments['SomeKey'] = 'moo'; $this->FireEvent('ExampleEvent'); public function SomeObject_ExampleEvent_Handler($Sender) { if ($Sender->EventArguments['SomeKey'] == 'moo') echo "Cows say moo"; }
1 -
sahotataran ✭✭✭
i think it should be
DiscussionController_PopulateTitle_Handler($Sender) {
or DiscussionsController_PopulateTitle_Handler($Sender) {
rather than just Discussion_PopulateTitle_Handler($Sender) {
because you specify the ControllerName for which you are firing the event for
There was an error rendering this rich post.
0 -
Tim Vanilla Staff
@sahotataran is right. You specify the firing object's full class name as the first piece, then the event name itself, then Handler
1 -
Tim Vanilla Staff
Do yourself a favor.
At the place where you're trying to fire that event, put this:
var_dump(get_class($this)); die();
That class name is what you're firing on, and should be the prefixed controller name in your handler hook. I'm willing to bet it is not DiscussionController.
1 -
sahotataran ✭✭✭
basically if you check /applications/vanilla/views/discussion/index.php you will find
<?php $this->FireEvent('BeforeDiscussion'); ?>just an example. you will find same definitions through out Vanilla where EVENTS ARE DEFINED and their PLACE where they are to be fired.
still if you dont get it then you can download and install http://vanillaforums.org/addon/eventi-plugin and it will tell you all the events that are fired and where it is fired when the page is rendered.
hope that helps
There was an error rendering this rich post.
1 -
sahotataran ✭✭✭
if you just wanna change the TITLE of page then you can just use
Base_Render_Before($Sender){
$Sender -> Head -> Title('Your Title');
}There was an error rendering this rich post.
0 -
sahotataran ✭✭✭
did you check the eventi plugin???? i will tell you all events that are fired.
second how i would do is using any hook eg Base_Render_Before you can print_r($Sender)
this will show in browser all the detail of the $Sender - then in your browser you can look for TITLE i mean search for title it will show where it is in which array/object etc and then using a hook i would try to change the title dynamically as you are trying to do
There was an error rendering this rich post.
0 -
sahotataran ✭✭✭
i think all routing is done by bootstrap.php
There was an error rendering this rich post.
0 -
Tim Vanilla Staff
Tim said:
You specify the firing object's full class name as the first piece, then the event name itself, then HandlerThe reason your event handler before (ZoomitController_PopulateTitle_Handler) did not fire is because you arbitrarily added "Controller" to the name of your object. Read my quote. You specify the firing object's full class name as the first piece.
That means if
get_class($this)
returnsHamburger
, your event handler for events your fire off of that object will start withHamburger_
, notHamburgerController_
or any other word.So if, as you say, it returned
Zoomit
, then you would handle events thrown off of that object with a handler method starting withZoomit_
.
In your particular case, if you're doing $this->FireEvent('PopulateTitle'), you'd hook that event with a method calledZoomit_PopulateTitle_Handler($Sender)
3 -
Tim Vanilla Staff
As far as accessing the URL and its parameters, we have an object called Gdn_Request which does that. It has a ton of helper methods.
You can access this object with the helper method
Gdn::Request()
. In your case, to get the value of the passed-in URL parameter 'Type', you'd do something like:echo Gdn::Request()->GetValue('Type')
2
Answers
When you fire an event, the handler always gets passed a reference to the firing object ($Sender). So you can set data on that object before firing, and read it off the $Sender in the handler.
Vanilla Forums COO [GitHub, Twitter, About.me]
Thanks Tim!
I tried that and the event doesn't get handled (or so it seems).
In my case:
...
$this->EventArguments['Title'] = 'Discussion Title Of Sorts';
$this->FireEvent('PopulateTitle'); // Pre-populate discussion title
$this->Redirect("post/discussion/" . $CategoryID); // Display new discussion
...
public function Discussion_PopulateTitle_Handler($Sender) {
die($Sender->EventArguments);
}
...
No funeral observed - New Discussion page is happily displayed.
What am i doing wrong?
i think it should be
DiscussionController_PopulateTitle_Handler($Sender) {
or DiscussionsController_PopulateTitle_Handler($Sender) {
rather than just Discussion_PopulateTitle_Handler($Sender) {
because you specify the ControllerName for which you are firing the event for
There was an error rendering this rich post.
@sahotataran is right. You specify the firing object's full class name as the first piece, then the event name itself, then Handler
Vanilla Forums COO [GitHub, Twitter, About.me]
Thanks.
I tried both ways (and then some) with the same results (that is, i noticed my error after posting and before getting your response, then modified the script to reflect DiscussionController object).
The interesting thing is that i DO get a handling if i use something like:
public function PostController_BeforeDiscussionRender_Handler { yadda, yadda, yadda
also
public function Base_Render_Before {
(and, yes, i did notice Todd's empty can of coke flying by...)
However, in these cases, the sender's EventArguments is an empty array (I "var_dump" it).
I forgot to mention that the function that my plugin 'rides on' is
SearchController_Render_Before
It is there that the script intercepts & interpret search criteria then implements the fire event and redirection. Should that make a difference? I wouldn't think so.
Is there a way for me to attach the default.php i wrote for the plugin?
Do yourself a favor.
At the place where you're trying to fire that event, put this:
var_dump(get_class($this)); die();
That class name is what you're firing on, and should be the prefixed controller name in your handler hook. I'm willing to bet it is not DiscussionController.
Vanilla Forums COO [GitHub, Twitter, About.me]
Thanks - I get the name of my plugin (in my case 'Zoomit').
So, if i am not mistaken, the function in the defaul.php of my plugin where i hope to be able to see the EventArguments should be:
public function ZoomitController_PopulateTitle_Handler($Sender) {
ver_dump($Sender->EventArguments); die(); // This does not get executed..
}
It doesn't get executed either. Am I setting something incorrectly?
well did you define FireEvent('PopulateTitle') in your ZoomitController????????
in your view or anywhere in your Zoomit Plugin??????
There was an error rendering this rich post.
basically if you check /applications/vanilla/views/discussion/index.php you will find
<?php $this->FireEvent('BeforeDiscussion'); ?>just an example. you will find same definitions through out Vanilla where EVENTS ARE DEFINED and their PLACE where they are to be fired.
still if you dont get it then you can download and install http://vanillaforums.org/addon/eventi-plugin and it will tell you all the events that are fired and where it is fired when the page is rendered.
hope that helps
There was an error rendering this rich post.
if you just wanna change the TITLE of page then you can just use
Base_Render_Before($Sender){
$Sender -> Head -> Title('Your Title');
}
There was an error rendering this rich post.
I think the main hurdle is my ignorance (of Vanilla, PHP, MVC, etc.)
Let me explain what i am trying to do and where things go awry.
I am trying to intercept the initial page load, the URL of which contains two strings.
The first string identifies a category name (that i assume exists - if not nothing happens) - and the second is a part of discussion name supposedly within that category.
I had a hard time implementing this on the DiscussionsControllers_Render_Before because I could not find the parts of my URL (I still don't know where to find the initial URL - where is it?).
The URL i was trying to work with is:
http://localhost/vanilla/index.php?p=discussions&Type=Order&ID=12345
I was unable to find my parameters. So...
The solution i came up with is to use the SearchController because there, i COULD find what i needed and it is working fine. The URL I am using is:
http://localhost/vanilla/index.php?p=/search&Type=Order&ID=12345
Note: The URL above is not shown correctly after the "?p=" in here (it should be "?p={percentsign}Fsearch{ampersand}Type=Order{ampersand}ID=12345.)
The way it supposed to work (and it does for the main part) is to display a given discussion that exists and/or display a new discussion in the specified category if it does not exist yet. This is working great.
Then, all I wanted was to pre-populate the discussion title (Name field) with the category (say Order) and the ID (12345) so the discussion title (not the page title) shows 'Order 12345' in the new discussion page - the case where the discussion does not exist yet. Simple, no?
This is where things stopped working and i posted the question to which you and Tim responded and tried to accomplish it with the FireEvent mechanism that was suggested by Tim.
All of the code is in two functions in the default.php of this plugin.
The initial interception logic is implemented on SearchController_Render_Before from where i (successfully) redirect either to a particular discussion or to the post/discussion/{CategoryID}.
The second function I am unable to get to work after using the FireEvent as either it does not get executed or the EventArguments array is empty.
did you check the eventi plugin???? i will tell you all events that are fired.
second how i would do is using any hook eg Base_Render_Before you can print_r($Sender)
this will show in browser all the detail of the $Sender - then in your browser you can look for TITLE i mean search for title it will show where it is in which array/object etc and then using a hook i would try to change the title dynamically as you are trying to do
There was an error rendering this rich post.
First, lots of thanks.
I know how to change the field i need to change but i need to have something like the EventArguments to pass it in (but the EventArguments array is empty when i DO get my code to get executed).
Instead of print_r, i am using var_dump - shows me everything i need to see (I think) - this is how i figured out where to get the parameters in the SearchController...
I will now try to download the eventi plugin and, again, thanks so much.
Still, where does one find the initial URL? I did not see it in the session or anywhere else. Still a mystery to me where that thing is tucked away...
i think all routing is done by bootstrap.php
There was an error rendering this rich post.
The reason your event handler before (ZoomitController_PopulateTitle_Handler) did not fire is because you arbitrarily added "Controller" to the name of your object. Read my quote. You specify the firing object's full class name as the first piece.
That means if
get_class($this)
returnsHamburger
, your event handler for events your fire off of that object will start withHamburger_
, notHamburgerController_
or any other word.So if, as you say, it returned
Zoomit
, then you would handle events thrown off of that object with a handler method starting withZoomit_
.In your particular case, if you're doing $this->FireEvent('PopulateTitle'), you'd hook that event with a method called
Zoomit_PopulateTitle_Handler($Sender)
Vanilla Forums COO [GitHub, Twitter, About.me]
As far as accessing the URL and its parameters, we have an object called Gdn_Request which does that. It has a ton of helper methods.
You can access this object with the helper method
Gdn::Request()
. In your case, to get the value of the passed-in URL parameter 'Type', you'd do something like:echo Gdn::Request()->GetValue('Type')
Vanilla Forums COO [GitHub, Twitter, About.me]
Gdn_Request has many other parameters and methods though, so to get an idea of everything it stores, do a quick
var_dump(Gdn::Request()); die();
somewhere and have a look. Then inspect/library/core/class.request.php
Vanilla Forums COO [GitHub, Twitter, About.me]
Pile of thanks to both of you guys.
The (new) bottom line is that i got my mini/pet project to work by using
Gdn::Request()->GetValue(...);
As well, I DID get into my plugin Event Handler but two things prevented me from using this apporach.
First, the EventArguments array was empty, Second, there is no $Sender->Form where i can do SetFormValue.
So... My approach was to introduce a parameter (a string that is the title i need) to the url I redirect to and then use Base_Render_Before code as the function where i reclaim what i need from the second instance of Gdn::Request()->GetValue(...);
Not perfect - but working...
I now have more time to reflect and see whether i can avoid Base_Render_Before.
My next and last challenge is this mini project is to figure out how to disable the new discussion's title input field so the user cannot change it. If you have any ideas i am all eEars.
Regardless, your tenacious help and patience are noticed and appreciated.
Bey