Wedge
Public area => The Pub => Plugins => Topic started by: Nao on April 5th, 2013, 09:55 AM
-
I'm stumped, Pete...
I tested some pass-by-ref stuff on my plugin, and it looks like it's doing exactly the reverse of what you said:
call_hook('receiving', array(&$var)) associated with either receiving($var) or receiving(&$var) WORK.
call_hook('receiving', array($var)) associated with either receiving($var) or receiving(&$var) DO NOT WORK.
You said that technically, the second solution is the right one, as long as &$var is used in receiving().
My concern stems from the fact that the call_hook function sends an ARRAY of variables, i.e. their VALUES. From the moment you send an array, the call_hook function can no longer access the array values as references, so it can't pass them as refs either...
It makes no sense to me.
Heck, I think we can also easily do away with the arrays.
Anyone knows anything about these? This is the first time I'm looking into plugins, really, and never used call_hook before for any reason whatsoever... ;)
-
The second solution does not work on PHP/5.3.x or below.
-
So... Here are my findings on this.
I spent an hour trying to work it around -- it was possible to do call_hook('hook_name', &$val, &$val1, &$val2...) in PHP 4.x, but not in PHP 5.x, because of the dreaded 'call-time by reference deprecated', which is fine by me... So, what about removing the ampersands? Fine. In call_hook, func_get_args() will return the proper list of variables... But a copy of them, not references to them. So, after the variables are modified by the actual hooks, there is no way to return these values to their actual owners.
Another solution was to do debug_backtrace(), and accessing the argument list from that object, because 'args' would hold references to the actual variables, rather than their values. Well, I naively implemented that (it makes call_hook about 50% slower (not counting the execution time of the hooks themselves), which is alright considered it's not called a lot and it's super fast anyway), and unfortunately it looks like this is not the case in PHP 5... No references. I read somewhere that you need to pass an ampersand explicitly in the call anyway, so it's a PHP4-only trick, eh... I guess?
At any rate, variable arguments lose references in PHP 5. That's something we'll have to accept...
So, with the current implementation in Wedge, i.e. call_hook('hook_name', array(&$byref)), removing the ampersand is NOT A CONVENIENCE. I repeat, it DOES NOT HELP AT ALL. The array() call is there to remove PHP's deprecation warning -- so that we can freely choose whether to pass a reference or a copy. If you do not add an ampersand to every variable, the hooks will not be able to modify them, regardless of whether they add ampersands in THEIR own function declaration.
Again: if Wedge called the hooks directly without going through call_hook(), it WOULD be possible to modify the variables directly. But because we have to go through an intermediate, and said intermediate can't explicitly require references, it's not possible.
So: http://wedge.org/do/thoughts/?in=7837#t7842 <--- this, is wrong in our particular case.
We *have* to use ampersands in our call_hook() calls, if we intend to provide for the ability to modify a variable. Which we don't always want, anyway...!
:edit: Just saw your post, John.
-
What version of PHP are you testing this with?
-
Well..it sort of makes sense. call_hook is a normal PHP function and passing array of values will automatically pass a copy and not the original reference. Perhaps passing objects will help with this but I don't know.
-
Huh, I was convinced that we didn't have to use & if the receiver did so. Learn something every day.
@Dragooon, yes, that makes sense but it seems illogical to pass an array of references as a copy.
I can't help but wonder why they've done this.
-
Who did what? The PHP team or SMF team..?
It just seems like the SMF team went through this pain and found the better solution, and I've been trying to reinvent the wheel... I probably should have used that time on something more constructive ;)
Anyway -- now we now what to expect: if we want to give a hook the ability to modify a variable, we have to add the ampersand. Otherwise, call_hook will make only provide a copy of it. Good to know for future hooks, eh..?
-
The PHP team.
The SMF team implemented a solution likely unaware of what was going on. Back in 2010 when they made this, the changes to PHP hadn't been announced at that point.Anyway -- now we now what to expect: if we want to give a hook the ability to modify a variable, we have to add the ampersand. Otherwise, call_hook will make only provide a copy of it. Good to know for future hooks, eh..?
That's very good, it means we can be selective about what we expose.