tags:

views:

133

answers:

6

I'm trying to learn to build a login sequence. In one part, I wanted to determine if the user left any of the 3 required fields blank:

foreach ( $_POST as $key => $value )
   {
      if ( $key = "school_code" ||
           $key = "user_name"   ||
           $key = "password" )
         {
            if ( $value == "" )
               {
                  $a_blank[] = $key ;
               }  
         }  
   }

if( @sizeof( $a_blank ) > 0 )
   {
      echo '<pre>';
      print_r( $a_blank );
      echo '</pre>';
   }

If the user does not enter anything for school_code or user_name, but DOES enter a password and then clicks submit, the result is:

Array
(
    [0] => 1
    [1] => 1
)

Why isn't the array result like this (i.e., the values of $key)?

Array
(
    [0] => school_code
    [1] => user_name
)

Thanks!

+7  A: 

Comparison is with ==, not =.

$key = "school_code" || $key = "user_name" || $key = "password"

Should be with == instead. You could write this in a slightly less-verbose way too:

$options = array("school_code","user_name","password");
if (in_array($key, $options) && empty($value)) {
    $a_blank[] = $key;
}
Jonathan Sampson
Still, shouldn't it be printing `[0] => school_code`?
Nirmal
Nirmal, I don't know. I'd have to see the HTML form.
Jonathan Sampson
No it should not, because or-operator has higher precedence than the assignment operator: http://php.net/manual/en/language.operators.precedence.php. The result of the or-operator is assigned to the $key-variable i.e. $key = (boolean) 'school_code' || ...
Aleksi
Aleksi, you're assuming the form has the correct attributes and name elements to produce those results. This is precisely what we need to see. If the form is GET, rather than POST, the user won't get his/her desired results. If they have default values, they won't get their desired results...etc.
Jonathan Sampson
I'm sorry, I might have been a bit unclear as I didn't include @Nirmal. Your solution is right on the money but the issue I tried to answer is why the original code returned [0] => 1 instead of [0] => school_code. In fact the original code will return [n] => 1 for each parameter name whatever the the name. This is because of the aforementioned operator precedence between or- and assignment-operators. I'm sorry for any inconvinience caused by my poor communication.
Aleksi
+2  A: 

When you're doing a comparison, remember to use two equal signs (==) instead of just one (=). A single equal sign is assignment, two is comparison.

Take this as an example:

$val = false;
if ($val = true)
    foo();

If you use = in the if statement, foo() will be called. What you're actually doing is setting the value of $val to true right inside the if statement. In that case, it will always be true. That's not what you want.

$val = false;
if ($val == true)
    foo();

This is what you want. Here, foo() will not get called.

For more info see the PHP docs.

musicfreak
+1  A: 

Two problems with this code.

The

$key = "school_code" || $key = "user_name" || $key = "password" 

Will assign to $key the result of the logical or which will always be true (== 1).

The other problem is that depending on the browser "empty" form values are not always returned so if say the user left password blank it might not appear in the $_POST array.

You would be much better doing a plain old explicit "if"s rather than the fancy array tricks for this.

$missing = array();
foreach (array('school_code','user_name','password') as $nm
if ( !isset($_POST[$nm] length($_POST[$nm]) == 0 ) {
        $missing[] = $nm;
}
James Anderson
As far as I know, empty text boxes are always returned. Only checkboxes and radio buttons which are empty are not returned by the browsers.
Nirmal
A: 

I've tried out this code (using the == as comparison of course) and it works fine.

This is the result I got:

Array
(
    [0] => school_code
    [1] => password
)

But when run with the original (mistakenly using the = sign) it returns:

Array
(
    [0] => 1
    [1] => 1
)

The problem is that the asker is using = to compare instead of ==. So the solution is to use == and it will work.

Can anyone explain this?

Chaim Chaikin
It seems that the or-operator || has higher precedence than the set operator =. With parenthesis the code would look like $key = ("school_code" || $key = ("user_name" || $key = "password"))). And in php "school_code" equals 1 as a boolean flag.Manual for operator precedence confirms this: http://php.net/manual/en/language.operators.precedence.php
Aleksi
So correcting the = to == should fix the problem. Maybe brackets should be used also to avoid confusion. Or since the comparison (==) operators have higher precedence than || it shouldn't really make a difference.
Chaim Chaikin
A: 

Thanks for all the help with my question! I'm frustrated that the "==" vs "=" has tripped me up yet once again. Wish I could set my IDE so that every time I typed an equal sign, a little popup would ask me, "ARE YOU SURE?"

FWIW, here is the HTML:

<?php
session_start() ;
$_SESSION["form_token"] = md5( rand( time(), true ) ) ;
?>

<!-- Display login form -->
<div id="login">
<p>Please supply your username, 3-digit school code, and password.</p>

<form action = "<?php echo $_SERVER['PHP_SELF']; ?>"
      method = "post">

<Input type = "hidden"
       name = "form_token"
      value = "<?php echo $_SESSION['form_token']; ?>" />

<dl>
<dt><strong>Username</strong></dt>
<dd><input type = "text"
           name = "user_name" /></dd><br/>

<dt><strong>School code</strong></dt>
<dd><input type = "text"
           name = "school_code" /></dd><br/>

<dt><strong>Password</strong></dt>
<dd><input type = "password"
           name = "password" /></dd> <br/>

<dd><input type = "submit"
           name = "action"
           value = "Login" /></dd>
</dl>
</form>
dave
A: 

when you are using such comapring if ( $key == "school_code" || .. )

you may have such bug if you wrongly type "=" instead "=="

nice trick is use it that way : if ("school_code" == $key || ... and you'll never has this bug because another way it would be error

sorry for bad english.

Fivell