php evaluation sequence of if-statements - php

I'm having trouble with sanitizing user input, where I don't know, if POST-Data has been sent or not. When I just do this to check:
if ($_POST["somedata"] == 2)
DoSomething();
I will get an error notice with error_reporint = E_ALL, that $_POST["somedata"] may not be defined (e.g. when the page is loaded without the form).
So I do this check now:
if (isset($_POST["somedata"]) && $_POST["somedata"] == 2)
DoSomething();
This doesn't output an error but it looks very unstable to me. I'm not sure if I just have luck with my PHP-Version or the simplicity of the statement. Is it also safe to use, when the if-statement is more complex, as long as the order of these two items are the same? Is it safe to use with all PHP-Versions?

Using isset in combination with a lazy-and (&&) is relatively correct (it prevents strictness warnings). A more advanced way would be to have automatic input checking against a schema or model.
You could have:
$schema = array(
"somedata" => "number"
);
Using the schema approach requires a little bit of architecture but it removes the instability that you might be worried about.
One thing worth mentioning is that there is a difference between validating input on a syntax level (did I get all the required inputs) and input validation on a semantic level. Let's say you have a service called GetItem and you pass id = 3 the syntax checker will check for the presence of the id property and that it is a number. Then you need to check whether 3 actually exists.
So rather than returning invalid request (bad input) you might want to return no such item.

Your approach is functionally correct, as the && is short-circuited if the first term evaluates to false. Regarding stability, as you suspected, there is a small concern, related especially to code duplication, mainly you need to always pay care that both keys match the same string (it is appropriate to say this is a matter of code duplication).
One approach to this would be to define a function that does the check and returns the contents at the desired key if exist, like for example:
function arr(array $array, $key, $defaultValue=false) {
return isset($arrray[$key]) ? $array[$key] : $defaultValue
}
You pay a small performance penalty for calling a function (you can reduce it by removing the type hinting for the $array parameter), however you have a more stable code.
Usage example in your case:
if(arr($_POST, 'somedata') === 2)) {
// do your stuff
}

We've been using this at work for some time now, going back years in code. It's fine to use since it first checks it the variable is actually there, and only then checks if it has a value.

Your code snippet is correct.
if (isset($_POST["somedata"]) && $_POST["somedata"] == 2)
DoSomething();
I would highly encourage you to use the triple equals for your quality check. Check out How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ? for more info on equality checks.
The triple equal means it needs to be an integer and not just a string, good practice to get into doing this.

Related

PHP if statement not functioning correctly

I am trying to run an if statment then checks if a cell in database holds a certain value then it sets a variable, if it does not contain that value then it sets a different value
I have tried the following code
case "Chemistry":
$type_tarin_text = ' Exp in ';
if($user_playerdata_tab['profile_type']='Drug Runner') {
$treining_value =$sp_value*11;
} else {
$treining_value =$sp_value*10;
}
$this->AddSubValueByUserID($player_id,'PlayerData','CHEMISTRY_EXP',$treining_value);
break;
It is currently setting the $treining_value as $sp_value*11 regardless of wether profile_type is 'Drug Runner' or not.
Please use == or strict === since you're expecting a string.
You're now assigning a variable which is likely not what you are trying to do.
As others have helpfully pointed out, the issue is here:
$user_playerdata_tab['profile_type']='Drug Runner'
The single = means assignment. What you were intending to do was to test whether the two were equal.
That means using == - or, to be more strict, use === (make that your go-to equality check in the future - you'll thank us later)
Your other assignments are fine, though I would recommend a single space both sides of your = signs for readability

Exclamation mark before integer variable php

function test_function (int $a){
if(!$a>0){
echo "in";
}else{
echo "out"
}
}
test_function(0);//output: in
test_function(2);//output: out
test_function(4);//output: out
I understand PHP's own operator precedence kicks in and "!" exclamation mark does the first calculation, prior to the "greater than" operator. That's okay.
I wish PHP would throw an error here saying "a boolean operation cannot be done on an integer". But in any case, the easy solution is to use parantheses:
if(!($a>0))
This takes care of precedence.
But in a large code base, do you have any additional suggestions to prevent mishaps?
The !-operator is the not operator from boolean algebra.
PHP tries hard to allow dynamic variable instantiation.
In your case !$a>0 would result in "(not $a) > 0".
The second one would be !($a>0) would negotiate the outcome of $a>0.
Either ways are technically fine (and might make more sense than the other). If you really want to avoid to not negotiate non-integers, just check what you got:
if (is_int($a) && !($a > 0)) {
You just need a very good modeling. As others pointed, the person in charge for defining that IF just need to be good at PHP. Depending on what logic needs implementation there, it is up to the coder find wheter or not it needs separete logic, as $variable>number will always return "true" or "false", look at the implementation of Michail Hirschler, it is a very good one.

Comparison order in PHP IF

I'm pretty sure that there is no difference between this
if ($value === true)
and this
if (true === $value)
For me it always seems confusing. I used to think that it's a 'bad unconventional style of new developers'. Furthermore, my boss told me never to do such a thing.
But today I was looking through Slim's source code, written by the guy who created PHP: The Right Way, and saw this (line 341).
if (true === $value) {
$c['settings'] = array_merge_recursive($c['settings'], $name);
}
I'm sure a guy like Josh Lockhart wouldn't do something like this if it was considered a bad practice. So what's with this order? Is it some kind of an old tradition?
This is colloquially referred to as 'Yoda Conditions'. The reasoning behind their usage is because sometimes people make mistakes. In the context of an if statement, this is one such mistake that is sometimes made:
if($value = 42)
Notice there is no double equals sign (==). This is a valid statement and is not a syntax error. It is possible that it would cause huge disruptions with the code that follows it, and it is very hard to identify quickly. Yoda conditions get around this by reversing the conditional expression:
if(42 = $value)
This is not a valid statement and is a syntax error, and those are generally reported with a line number included, so they're pretty easy to find.
"Syntax error you have. Line 73 do something else you must." -- Yoda's compiler, probably
Whether or not you actually think they're good or bad is up to personal preference and style. In some cases of popular frameworks (such as Wordpress), Yoda conditions are actually part of the official coding standards. The major critique against them is that, to some, they decrease readability of the code without providing any real major benefit.
As #MonkeyZeus pointed out in a comment to the question, sometimes people do actually mean to only use a single equals sign inside of an if condition:
if($iMustHaveAValue = functionCallThatCanFail()) {
// Rest assured, $iMustHaveAValue has a truthy value.
}
Since the value of an assignment operation is the value assigned, the value that is evaluated by the if condition in this case (and in the original case which was unintended) is whatever value happened to be assigned.

identity conditional "===" , performance, and conversion

I've always came away from stackoverflow answers and any reading I've done that "===" is superior to "==" because uses a more strict comparison, and you do not waste resources converting value types in order to check for a match.
I may be coming at this with the wrong assumption, so I assume part of this question is, "is my assumption true?"
Secondly,
I'm dealing specifically with a situation where I'm getting data from a database in the form of a string "100".
The code I am comparing is this...
if ($this->the_user->group == 100) //admin
{
Response::redirect('admin/home');
}
else // other
{
Response::redirect('user/home');
}
vs.
if ( (int) $this->the_user->group === 100) //admin
{
Response::redirect('admin/home');
}
else // other
{
Response::redirect('user/home');
}
or even
if (intval($this->the_user->group) === 100) //admin
{
Response::redirect('admin/home');
}
else // other
{
Response::redirect('user/home');
}
is any integrity (or performance) gained by manually casting or converting simply so you can use the identity ('===') comparison?
In your particular case == is the better option. As you (as can be seen in your code) have probably already found out many database functions will always return strings, even if you fetch an integer. So type strict comparison really only bloats your code.
Furthermore you are adding a potential (let's call it theoretic) security risk. E.g. (int) '100AB2' would yield 100. In your case this probably can't happen, but in others it may.
So: Don't overuse strict comparison, it's not always good. You mainly need it only in ambiguous cases, like the return value of strpos.
There is a performance difference between == and === - latter will be even twice as fast, see Equal vs identical comparison operator.
The difference, however is too small to be bothered with - unless the code is executed millions of times.
That's a really tiny optimization you're doing there. Personally, I don't think it's really worth it.
Any boost you gain from not casting the value when using === is lost when you explicitly cast the value. In your case, since the type is not important to you, you should just do == and be done with it.
My recommendation would be to keep === for when you need to check type as well - e.g. 0 evaluating to false and so on.
Any performance gains will be microscopically small, unless you're performing literally billions and trillions of these comparisons for days/months/years on-end. The strict comparison does have its uses, but it also is somewhat of anomally in PHP. PHP's a weakly typed language, and (usually) does the right thing for auto-converting/casting values to be the right thing. Most times, it's not necessary to do a strict comparison, as PHP will do the right thing.
But there are cases, such as when using strpos, where the auto-conversion will fail. strpos will return '0' if the needle you're searching is right at the start of the haystack, which would get treated as FALSE, which is wrong. The only way to handle this is via the strict comparison.
PHP has some WTF loose comparisons that return TRUE like:
array() == NULL
0 == 'Non-numeric string'
Always use strict comparison between a variable and a string
$var === 'string'

Why isset() is more efficient to test than '==='?

Summarized, I made a loop with a few iterations to check the efficiency of each test:
$iterations = 99999999;
$var = null;
isset comparasion
if ( isset( $var ) )
{
}
'===' comparasion
if ( $var === null )
{
}
And i have this log, in microseconds:
'isset()': 1.4792940616608
'===': 1.9428749084473
For me, this is a little curious. Why isset() function is faster than one comparison operator as ===?
The === comparison is a strict check, meaning that the two objects you're comparing have to be of the same type. When you break it down in plain English, it's actually not that weird that === needs some more time. Consider the parser to do this:
if (isset($var)) {
// Do I have something called $var stored in memory?
// Why yes, I do.. good, return true!
}
if ($var === null) {
// Do I have something called $var stored in memory?
// Why yes, I do.. good! But is it a NULL type?
// Yes, it is! Good, return true!
}
As you can see, the === operator needs to do an additional check before it can determine if the variable matches the condition, so it's not that strange that it is a little bit slower.
Isset is not a function: it is a language built-in. Using isset is faster than using a function.
The other thing is that isset is used all over the place, so it makes sense that it's been profiled to death, whereas === maybe hasn't received as much love.
Other than that, you'd have to dig in the PHP source with a profiler to see exactly what's going on.
I'm not sure I would call 100 million "a few iterations". You appear to have accumulated about a half-second difference, divide that by 100 million and you get a whopping 5 nanosecond difference per iteration if my math is correct. With the difference being so small it may simply come down to the fact that isset only has one operand in this context and === has two.
It's impossible to even discuss the Zend engine's implementation details of the two examples without specifying a specific PHP version; source code is a moving target. Even minute changes to the implementations are going to effect the results over that many passes. I would not be surprised if you found the opposite to be the case on some versions of PHP and/or in a different context.
isset itself is covered by three different op-codes in the VM depending upon the context:
"Simple" Compiled Variables like your example: ZEND_ISSET_ISEMPTY_VAR
Arrays: ZEND_ISSET_ISEMPTY_DIM_OBJ (requires 2 operands, the var and the index)
Object properties: ZEND_ISSET_ISEMPTY_PROP_OBJ (also 2 operands, var and prop name)
It's an interesting question for curiosity's sake but we're in hair splitting territory and it's probably not a real-world optimization strategy.

Categories