CaelanStewart Posted January 7, 2016 Share Posted January 7, 2016 Hi All, Just a quick one, not a big issue. To access API variables from inside a function with ProcessWire, I believe is a tad tedious. Having to do this, just to access a few variables is a bit annoying, and frankly repetitive: $page = Wire('page'); $sanitizer = Wire('sanitizer'); $user = Wire('user'); $users = Wire('users'); $input = Wire('input'); When it'd be much easier (and faster, and less typo prone) to do this: global $page, $sanitizer, $user, $users, $input; I've seen the possibility of confusion mentioned before as a reason against this. But let's be realistic, if somebody is writing templates and making use of the ProcessWire API, they are going to know off the top of their head exactly which API variables they need. In fact, I purposefully avoid declaring variables that have the same name as PWs API variables when I'm writing PW templates. So my question really is: Why not? Link to comment Share on other sites More sharing options...
Mike Rockett Posted January 7, 2016 Share Posted January 7, 2016 I could be completely wrong here, but doesn't PW follow the IoC principal? So accessing wire(something) and $this->something (from a module) is calling the exact same thing? If that is the case, instantiating $pages is not necessary anyway. Link to comment Share on other sites More sharing options...
LostKobrakai Posted January 7, 2016 Share Posted January 7, 2016 Because it breaks as soon as you're using any external code that uses these variable names anywhere. The WirePDF module for example does use mpdf as pdf rendering library. If this library is using $page as variable somewhere it's break your website. @Mike It's using the same object but it's still repetitive to use this snippet in each function or rewrite code from using variables to wire("var") when it's abstracted into a function. 1 Link to comment Share on other sites More sharing options...
CaelanStewart Posted January 7, 2016 Author Share Posted January 7, 2016 Because it breaks as soon as you're using any external code that uses these variable names anywhere. The WirePDF module for example does use mpdf as pdf rendering library. If this library is using $page as variable somewhere it's break your website. @Mike It's using the same object but it's still repetitive to use this snippet in each function or rewrite code from using variables to wire("var") when it's abstracted into a function. I somewhat disagree. The library may well try and define a class called 'Page' for instance, or a function called 'Wire' as much as it would the $page variable. And plus, consider the following code: <?php global $hello; $hello = "hello"; function goodbye() { $hello = "goodbye"; } echo $hello; goodbye(); echo $hello; The output is not "hellogoodbye" but is in fact "hellohello" as the '$hello' variable was never instantiated with the 'global' keyword inside the function. So unless this library sets the variable in the root scope, or also uses a global named '$hello' or '$page', then there will be no problem. Yes, all said ways are repetitive, but I find the cleanness and brevity of the 'global' keyword approach preferable. Link to comment Share on other sites More sharing options...
Wanze Posted January 7, 2016 Share Posted January 7, 2016 Global variables are against the principle of object oriented programming. LostKobrakai made a good point. One could always write something like this: $_GLOBALS['page'] = "I'm a string page"; and your code breaks... If you're in a class derived from wire, the cleanest way to get the API variables is like this: $this->wire('page'); $this->wire('sanitizer'); // They could also be accessed directly, but then you're not 100% sure if the member is overwritten with something else $this->page $this->sanitizer The global wire function is there to access the API variables in (global) functions, or static methods when you're in a class. You don't even need to reassign them to local scoped variables, just use them like so: echo wire('page')->id; ... or if you really want local variables with a one liner, write a little wrapper like this: function getApiVars() { return array( wire('page'), wire('pages'), wire('sanitizer'), ); } // And then list($page, $pages, $sanitizer) = getApiVars(); Or another possibility would be to inject them into your class/method, if you don't subclass Wire. Cheers 8 Link to comment Share on other sites More sharing options...
LostKobrakai Posted January 7, 2016 Share Posted January 7, 2016 It's true that class collisions can happen, but pw 3.0 is moving to using namespaces for that reason. In turn variables are not namespaced. They are always bound to the scope or global. Wanze's helper method is probably a better way to go, kinda like extending Wire to get access to api variables in classes. 2 Link to comment Share on other sites More sharing options...
CaelanStewart Posted January 7, 2016 Author Share Posted January 7, 2016 Global variables are against the principle of object oriented programming. LostKobrakai made a good point. One could always write something like this: $_GLOBALS['page'] = "I'm a string page"; and your code breaks... If you're in a class derived from wire, the cleanest way to get the API variables is like this: $this->wire('page'); $this->wire('sanitizer'); // They could also be accessed directly, but then you're not 100% sure if the member is overwritten with something else $this->page $this->sanitizer The global wire function is there to access the API variables in (global) functions, or static methods when you're in a class. You don't even need to reassign them to local scoped variables, just use them like so: echo wire('page')->id; ... or if you really want local variables with a one liner, write a little wrapper like this: function getApiVars() { return array( wire('page'), wire('pages'), wire('sanitizer'), ); } // And then list($page, $pages, $sanitizer) = getApiVars(); Or another possibility would be to inject them into your class/method, if you don't subclass Wire. Cheers Thank your for taking the time to clear that up. I have been enlightened! 1 Link to comment Share on other sites More sharing options...
CaelanStewart Posted January 7, 2016 Author Share Posted January 7, 2016 it also occurred to me I can do this, which is still shorter, but not so tidy: foreach(['pages', 'input', 'sanitizer'] as $w) $$w = Wire($w); 2 Link to comment Share on other sites More sharing options...
WillyC Posted January 7, 2016 Share Posted January 7, 2016 u can.do theis too function starwar() { extract(wire('all')->getArray()); echo "may.the be force.wit u $user->name and alsos.wit $page->path"; } 10 Link to comment Share on other sites More sharing options...
hellomoto Posted April 9 Share Posted April 9 I just realized and then this was already in the Google SERP open from searching "wire in wire function processwire" regarding something else (wire('config') in a function was not a function because the namespace wasn't present): wire() in the init method of a module which extends ProcessPageAdd in a different PW instance that is instantiated in ready.php is initialized also in the instance instantiating the other instance. For example: wire()->addHookBefore("ProcessPageAdd::execute", $this, 'hookPageAdd'); resulted in an error adding a page of the same template name in the instance instantiating the other one. Prepending with $this-> disables the cross-site functionality. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now