unexpected cast to boolean? - php

Given this input: http://example.com/item.php?room=248&supply_id=18823, the following 2 blocks ought to produce the same result. Why don't they? What am I missing other than coffee?
This block gives the expected values:
if (isset($_GET['supply_id']) && isset($_GET['room'])) {
$id=validkey($_GET['supply_id']); //18823
$room=validkey($_GET['room']); //248
$arr=array('s'=>$id,'r'=>$room); //s=>18823, r=>248
}
But if I do the check and the assignment in one step, $id ends up equal to 1 instead of 18823. Why?
if (isset($_GET['supply_id']) && isset($_GET['room'])) {
if($id=validkey($_GET['supply_id']) && $room=validkey($_GET['room']))
$arr=array('s'=>$id",'r'=>$room); //s=>1, r=>248
}
This is the function I'm using:
function validkey($value){
if(is_scalar($value)){
$value=(int)$value;
return ($value>0) ? $value : false;
}
return false;
}

You should use parentheses:
if(($id=validkey($_GET['supply_id'])) && ($room=validkey($_GET['room'])))
Otherwise the result of validkey($_GET['supply_id']) && $room=validkey($_GET['room']) is assigned to $id variable because && operator has higher precedence than =

The && operator binds stronger than the = operator.
So your code basically becomes if ($id = (validkey($_GET['supply_id']) && $room = validkey($_GET['room'])))
--> Add parenthesis around the $foo = $bar expressions in your IF statement.

You seem to have a small error in your second example - a stray doubble quote after $id. Also, your second approach is generally frowned upon (assigning variables in an if construct) as it makes code considerably harder to follow. Clearer would be the following:
if (isset($_GET['supply_id']) && isset($_GET['room'])) {
$id=validkey($_GET['supply_id']); //18823
$room=validkey($_GET['room']); //248
if($id && $room) {
$arr=array('s'=>$id,'r'=>$room); //s=>18823, r=>248
}
}

Related

how to use the operators AND, OR in the IF statement in PHP

I tried to use the operators AND, OR in an IF statement in a PHP script like this:
if($user[id]=='1' AND (($_GET['f']=='f-ppas') || ($_GET['f']=='f-kua'))){
.....
}
But the result is wrong. Can anyone help me?
Change AND to &&
if($user['id']=='1' && (($_GET['f']=='f-ppas') || ($_GET['f']=='f-kua'))){
.....
}
The AND operator has some precedence problems.
$this = true;
$that = false;
$truthiness = $this and $that;
$truthiness above has the value true. Why? = has a higher precedence than and. The addition of parentheses to show the implicit order makes this clearer:
($truthiness = $this) and $that
If you used && instead of and in the first code example, it would work as expected and be false.
Reference: 'AND' vs '&&' as operator

PHP if status and !isset or !isset

I'm trying to match a condition where if the user status is 10 and ANY POST variables are not set it triggers an error:
if ($_SESSION['status']=='10' && !isset($_POST['a']) || !isset($_POST['B'])) {}
I can not use && conditions for any !isset as one variable may be set though another might not. I only want the condition to match if one or more variables are not set AND the status==10.
When testing if a $_POST variable !isset, I remove an input element from the page via a browser web tool (e.g. Firebug). When the form is submitted with the variable missing it's still passing validation incorrectly.
I am also seeking a PHP if grouping condition.
If you are looking for absolutely any PHP variables, I'd recommend this:
if (($_SESSION['status'] == 10) && (count($_POST) > 0)) {
You can then get the list of _POST var keys using array_keys($_POST).
If you are looking for a specific:
if (($_SESSION['status'] == 10) && (isset($_POST['A']) || isset($_POST['b']))) {
The order of the brackets is important. You can separate groups of logical statements with brackets.
Is that was what you were looking for?
$status = $_SESSION['status'];
if($status == '10'){
if(!isset($_POST['a']) or !isset($_POST['B'])){
//Triggers error.
}else{
//Another
}
}
Try making it a function:
function checkAllVars($dataVars, $requestVars) {
foreach($dataVars as $varname) {
if(!isset($requestVars[$varname])) {
return false;
}
}
return true;
}
$dataVars = array (
"varName1",
"varName2",
"varName3",
"varName4",
);
$allVarsSet = checkAllVars($dataVars, $_REQUEST);
you might be looking for
if($_SESSION['status']=='10' && (!isset($_POST['a']) || !isset($_POST['B']))){}
^ ^
which means if status = 10 and (if not set 'a' or not set 'B' or they can be both not set) do something
or you might be looking for
if(($_SESSION['status']=='10' && !isset($_POST['a'])) || ($_SESSION['status']=='10' && !isset($_POST['B']))){}

Check if numeric and compare value in conditional with &&?

In PHP, if there is a conditional like this:
if ( is_numeric($my_var) && $my_var == 1 ) {
}
If the first part of the if is false, does the second part ($my_var == 1) get ever executed?
Thanks!
In your example the $my_var == 1 will not be executed (if it's not numeric). PHP will determinate that the first part evaluated to false and so there is no benefit in executing the second part because you are using the && AND operator.
An example:
if(isset($_GET['something']) && $_GET['something'] == '1')
{
}
If the querystring variable something is missing then it doesn't check if it equals 1. If it did then it could produce an Undefined index notice.
You can also verify this behavior with something like:
$test = '2';
if($test == '1' && die('dead'))
{
}
echo 'execution continues....';
Set $test = '2' and the die() will not stop execution. Set it to 1 and the die will execute and stop, thus you won't see Execution continues...
Edit: there is some general information here (not PHP specific).
If the first condition is false second one will not be executed if you use &&. You can try it yourself:
function a(){
echo 'a';
return true;
}
function b(){
echo 'b';
return true;
}
if (a() && b())
{
//do something
}
This will output: ab.
function a(){
echo 'a';
return false;
}
function b(){
echo 'b';
return true;
}
if (a() && b())
{
//do something
}
Outputs a.
I gave you this example because I couldn't find anything in docs but the first comment in this section
This is called a call-by-need or lazy evaluation.
Note: In some cases it's useful or necessary that the second function is executed despite of the state of first condition. In that cases you can use & operator. With bitwise operators you work with numbers, not with booleans. Because php interpretator should know both value before and after & operator it will execute both functions (a() & b()) and true, false are evaluated as 1 and 0, respectively, 1 & 0 => 0 that will be evaluated as false in if statement.
You can use like
if ( is_numeric($my_var)) {
if($my_var == 1)
{
// your code
}
}

Should I use elseif or multiple if clauses

I have this simple if code:
Which is better, doing it with esleif or doing two separate ifs?
if(is_home() && $currentpage == ''){
$catname = 'cars';
} elseif(is_home() && $currentpage != '' && is_page_template('models.php')){
$catname = 'newcars';
}
Two separete if clauses:
if(is_home() && $currentpage == ''){
$catname = 'cars';
}
if(is_home() && $currentpage != '' && is_page_template('models.php')){
$catname = 'newcars';
}
Does the order of if matters? could I place the second if before first?
The question should have been how php treats conditions from more particular to more general?
Should you always start with the more particular ones and work your way up to general?
Or php can sort them through?
The second version would be easier for me since I have allot of if's:)
This depends what behaviour you want:
If you use elseif, only the first matching block will execute.
$foo = $bar = true;
if($foo) { /* executed */ }
elseif($bar) { /* not executed */ }
When using separate if claused, all matching blocks will execute:
$foo = $bar = true;
if($foo) { /* executed */ }
if($bar) { /* also executed */ }
If the conditions are distinct, i.e. only one is ever true it doesn't really matter. However, by using elseif you avoid useless checks since as soon as one condition evaluates to true no further conditions need to be checked.
For the sake of script optimization, I would recommend elseifs as to avoid running extra unnecessary conditionals.
If possible, I would recommend the use of switch/case statements (where you can check the value of a single variable). They're cleaner and easier to maintain from a reduce clutter point of view.
One problem with multiple if statements (instead of elseif statements) is it makes debugging issues more complicated. How are you to know that the second statement isn't overriding the first statement or that your conditional logic is correct for every statement? Using multiple ifs increases the likelihood that one conditional overrides the function of another. Start adding multiple variables inside these if statements and it'll start to hurt your brain.
if (is_home()) {
if ($currentpage == '') {
$catname = 'cars';
}
else if (is_page_template('models.php')) {
$catname = 'newcars';
}
}
i would go with,
if(is_home()) {
if($currentpage == '') {
$catname = 'cars';
}
elseif(is_page_template('models.php')) {
$catname = 'newcars';
}
}

PHP: return a part of an if () { }

Let's say I have this code:
if (md5($_POST[$foo['bar']]) == $somemd5) {
doSomethingWith(md5($_POST[$foo['bar']]);
}
I could shorten that down by doing:
$value = md5($_POST[$foo['bar']];
if ($value == $somemd5) {
doSomethingWith($value);
}
But is there any pre-set variable that contains the first or second condition of the current if? Like for instance:
if (md5($_POST[$foo['bar']]) == $somemd5) {
doSomethingWith($if1);
}
May be a unnecessary way of doing it, but I'm just wondering.
No, but since the assignment itself is an expression, you can use the assignment as the conditional expression for the if statement.
if (($value = md5(..)) == $somemd5) { ... }
In general, though, you'll want to avoid embedding assignments into conditional expressions:
The code is denser and therefore harder to read, with more nested parentheses.
Mixing = and == in the same expression is just asking for them to get mixed up.
Since the if is just using the result of an expression, you can't access parts of it.
Just store the results of the functions in a variable, like you wrote in your second snippet.
IMHO your 2nd example (quoting below in case someone edits the question) is just ok. You can obscure the code with some tricks, but for me this is the best. In more complicated cases this advise may not apply.
$value = md5($_POST[foo['bar']];
if ($value) == $somemd5) {
doSomethingWith($value);
}

Categories