Checking a variable for existance without isset(), empty(), or any other function |
[eluser]BrianDHall[/eluser]
Just ran into this today, and wondering if there is anything 'wrong' with my solution. Consider this: Code: if ($real_array[$potential_element]) The problem - if $potential_element is not a valid index of the array, it'll throw a PHP notice. I don't want to do that, so normally I'd wrap it in a call to isset() or !empty(), etc. But is there anything wrong with just doing this: Code: if (@$real_array[$potential_element]) ??? Just a simple @ to shut PHP up, explicitly stating that "I know this might not be initialized - I understand, and I don't care". This seems such a simpler and more readable solution to wrapping up something so simple in an unnecessary function call. So, is ok (it works without error on my machines), or is there something I'm missing?
[eluser]BrianDHall[/eluser]
[quote author="Developer13" date="1258768021"]isset() exists for a reason.[/quote] ...yes...to see if a variable is set. But what if you don't care if it is set, you only want to know if it is true? My reasoning is that isset() determines if a variable is set, empty() determines if something is set to a non-empty value (0 is not empty, but a zero-length character string is empty)...but what what if you want to check to see if something is set AND true - in the simplest way possible? if($var) seems to me to be the simplest way to do this - the function of if() is to test for truth, so if is only 'truth' that matters why wrap it in another test? It is perfectly reasonable for PHP to raise a warning for uninitialized values (in fact this helped me fix 3 bugs when working on this), so therefore if(@$var) becomes the simplest way to a) test for truth and b) explicitly state your understanding as a programmer as to the pitfalls of uninitialized variables. What I'm wondering is if the use of @ still generates an internal PHP notice that it simply discards, and if so does isset() do the same thing? My primary concern is that performance implication of generating notices, errors, or warnings and then discarding them, because this will be performed inside a loop that may execute multiple thousands of times per page view in this particular application - and I don't know how to check to see if PHP is doing this.
[eluser]John_Betong[/eluser]
Your question certtainly is food for thought From my limited experience I endeavour to write code without any errors because the application seems to be much more nippier if there are no errors. Using isset(...) I think is a KLUDGE because one is relying on PHP to trot off and search to see if the variable has been set is in the boolean, numeric, string, array, etc list of variables. After eliminating all possible options isset(...) will return your query. This must take processing time. I would be tempted to ensure your $potential_element has a default value and therefore eliminate the search. Is it possible set a default value and run tests with and without the default variable? edit: spelling.
[eluser]Colin Williams[/eluser]
First, like John_Betong alluded to, sometimes you want to provide default values to avoid isset() calls. But other times you do want the isset() call because the mere existence of a variable, even if empty, might have ramifications elsewhere in the application. Second, don't confuse the wise goal of writing the least amount of code necessary with the not-so-wise goal of using the least amount of characters of code possible.
[eluser]Chad Fulton[/eluser]
The answer to your question is yes, the way PHP internals works is that the @ symbol calls the error_reporting function twice, once before your function runs to set it to 0, and once afterwards to restore it to the original value, so it's the worst possible choice. Now, I wrote up the following benchmark test, with these results: Isset: 0.023620843887329 Array Key Exists: 0.079711198806763 Neither: 0.11602878570557 Neither w/ @: 0.13448619842529 So, you'll notice that even with error reporting disabled, if(isset($tmp[$i]) && $tmp[$i]) is faster than simply if($tmp[$i]), assuming (as I did in the benchmarking) that half of the time your variable will be initialized and half of the time it won't. Depending on the true distribution, YMMV. The Neither w/ @ takes the most time, although in this case not too much more than Neither, since I assumed you'd be running with errors off by default. Code: <?php
[eluser]BrianDHall[/eluser]
@chad Fulton, thanks so much for your performance test and insight. I tried a slightly expanded and modified version: Code: $num =100000; Note: All results are shown as a floating point in seconds. Localhost WAMP: Quote:Isset: 0.088625907897949 Live LAMP server: Quote:Isset: 0.0335500240326 Wow, those last two I added are calling to a non-existent variable $temp instead of $tmp. Indeed, it is clear the performance effect of errors (here adding as much as 1-2 seconds of run time on a single page access just to deal internally with the generated errors, or even just chance of errors). Now add that to a slightly busy site on a slightly busy server, and the fact that this is a basic coding convention that might be done dozens of times in any given function, with dozens of function calls, etc etc - that could add up DAMN quick, especially when dealing with arrays of increasing size and complexity! As much as I like the perl-like single character use instead of a function call, here the performance is too big for even me to ignore - going back to empty() and isset() ![]() Indeed, it appears even asking if() to evaluate anything other than a boolean has a significant performance impact when looping through an array - even if you KNOW the variable is initialized!
[eluser]BrianDHall[/eluser]
[quote author="Colin Williams" date="1259068309"]Second, don't confuse the wise goal of writing the least amount of code necessary with the not-so-wise goal of using the least amount of characters of code possible.[/quote] This is true - one must limit the worthy goal of laziness and keep it from becoming complete and utter sloth ![]()
[eluser]BrianDHall[/eluser]
[quote author="John_Betong" date="1259062666"] Your question certtainly is food for thought From my limited experience I endeavour to write code without any errors because the application seems to be much more nippier if there are no errors. Using isset(...) I think is a KLUDGE because one is relying on PHP to trot off and search to see if the variable has been set is in the boolean, numeric, string, array, etc list of variables. After eliminating all possible options isset(...) will return your query. This must take processing time. I would be tempted to ensure your $potential_element has a default value and therefore eliminate the search. Is it possible set a default value and run tests with and without the default variable? edit: spelling.[/quote] The performance test does seem to strongly support that less errors automatically equals a faster program, so it isn't a question of imagination. Now, I had thought isset() would require considerably less work than it seems to, but you point out perhaps precisely why - it might very well run multiple type checks before returning. I'm just surprised empty() doesn't require even more work, but go figure. Well, the problem with default value is in this particular instance it is loading arrays not only with files from the file system, but then parsing out bits of the filename into an array, which is then formed into an associative array. Its meant to be a very easy to use, slightly magical, banner ad system. Its complicated by the fact that the program needs to know about the contents of the file before ever opening it due to its interaction with another far larger array (200-1000+ multi-dimensional arrays itself) - but ultimately I have no idea what could be in any of the elements before the application is run. That's rather why I'd never really considered this before - never really had a need to blindly walk through a significant sized array, but this extreme example helped to expose some underlying assumptions. |
Welcome Guest, Not a member yet? Register Sign In |