Validation function gets number 0 or 1

Asked

Viewed 521 times

-1

I made a validation function to accept only 1 or 0, but either 1 or 0 are being interpreted as INVALID. Any suggestions as to what the mistake would be?

function valida_variavel_zero_um($valor){
     if((empty($valor)) OR (strlen($valor) != 1)
      OR ($valor !=1 || $valor !=0)){
        return "INVALIDO";
     }else{
        return $valor;
     }

}
  • If 0, the condition $valor != 1 is true and enters the if. If 1, the condition $valor != 0 is true and enters the if. Can you understand the problem?

  • Then I would have to work with $value != "1" that way?

  • 1

    do not know where is coming the variable $value, but check if it is really an int, da a parseint, before the if, rethink your if, this redundant, any of the operations that gives true he will enter in the if, for example the 'Empty($value)', if it has value, will fall inside the if

  • I get it. I’m passing the $value directly. I just want to create a validation function so that the field is not empty, and only accept 1 or 0. For when other users are going to use the application there is an error if any of these requirements are not met.

2 answers

2


The error is in your condition.

  1. When using the empty, which may give rise to unexpected results because empty(false) returns true, entering the if, but empty(true) returns false;

  2. When using strlen != 1, as it is also susceptible to unexpected results, since strlen(false) returns 0, which is different from 1, entering the if, but strlen(true) returns 1;

  3. In part ($valor !=1 || $valor !=0), for if $valor is equal to 0, the condition $valor != 1 will be true, causing the program to enter the if and invalid return; the same happens when $valor is equal to 1 as the $valor != 0 becomes true, also entering the if. Fixing the problem is all about changing the operator || for &&;

To show how strange the results could be, just take the test:

function valida_variavel_zero_um($valor){
     if((empty($valor)) OR (strlen($valor) != 1) OR ($valor != 1 && $valor != 0)){
        return "INVALIDO";
     }else{
        return $valor;
     }
}

$tests = [0, 1, false, true, "0", "1", [], "", 0.0, -0.0, 1.0];

foreach ($tests as $test)
{
    var_dump( valida_variavel_zero_um($test) );
}

See working on Ideone | Repl.it

Getting the result:

string(8) "INVALIDO"    // $valor = 0
int(1)                  // $valor = 1
string(8) "INVALIDO"    // $valor = false
bool(true)              // $valor = true
string(8) "INVALIDO"    // $valor = "0"
string(1) "1"           // $valor = "1"
string(8) "INVALIDO"    // $valor = []
string(8) "INVALIDO"    // $valor = ""
string(8) "INVALIDO"    // $valor = 0.0
string(8) "INVALIDO"    // $valor = -0.0
float(1)                // $valor = 1.0

Do you realize how strange these results are? Some pairs of similar values produce different results: 0 is invalid, but 1 is valid; false is invalid, but true is valid; 0.0 is invalid, but 1.0 is valid.

It doesn’t make much sense, so I propose another solution:

Solution 1

The solution I propose has a very simple condition:

function valida_variavel_zero_um($valor)
{
    if ($valor !== 0 && $valor !== 1)
    {
        return "inválido";
    }

    return $valor;
}

When using the operator !==, you will check both value and type. By doing some brief tests:

$tests = [0, 1, false, true, "0", "1", [], "", 0.0, -0.0, 1.0];

foreach ($tests as $test)
{
    var_dump( valida_variavel_zero_um($test) );
}

We’ll have the exit:

int(0)                  // $valor = 0
int(1)                  // $valor = 1
string(9) "inválido"    // $valor = false
string(9) "inválido"    // $valor = true
string(9) "inválido"    // $valor = "0"
string(9) "inválido"    // $valor = "1"
string(9) "inválido"    // $valor = []
string(9) "inválido"    // $valor = ""
string(9) "inválido"    // $valor = 0.0
string(9) "inválido"    // $valor = -0.0
string(9) "inválido"    // $valor = 1.0

See working on Ideone | Repl.it

Solution 2

Another way to implement the function would be to clarify the type by defining it in the function’s list of arguments:

function valida_variavel_zero_um(int $valor)
{
    if ($valor != 0 && $valor != 1)
    {
        return "inválido";
    }

    return $valor;
}

See working on Ideone | Repl.it

However, when calling the function with non-integer values, PHP will try to convert them to the type int before passing them as parameter. That is, calling the function valida_variavel_zero_um(false) would return 0 and valida_variavel_zero_um(true) would return 1, because false and true, when analyzed as integers, are 0 and 1 respectively. This can cause problems in the application if this return is not expected for these parameters.

The output of the tests for this solution is:

int(0)   // $valor = 0
int(1)   // $valor = 1
int(0)   // $valor = false
int(1)   // $valor = true
int(0)   // $valor = "0"
int(1)   // $valor = "1"
Argument 1 passed to valida_variavel_zero_um() must be of the type integer, array given, called in /home/tzgjpG/prog.php on line 18
Argument 1 passed to valida_variavel_zero_um() must be of the type integer, string given, called in /home/tzgjpG/prog.php on line 18
int(0)   // $valor = 0.0
int(0)   // $valor = -0.0
int(1)   // $valor = 1.0

Solution 3

Another way, even cited by Victor in the comments, would be to try to analyze the value of the parameter with the function intval, however, the problem of solution 2 persists in this solution, because the same type conversion that PHP implicitly does when the type is set in the parameter list it will do with the function intval:

function valida_variavel_zero_um($valor)
{
    $valor = intval($valor);

    if ($valor != 0 && $valor != 1)
    {
        return "inválido";
    }

    return $valor;
}

See working on Ideone | Repl.it

The test result for this solution is:

int(0)   // $valor = 0
int(1)   // $valor = 1
int(0)   // $valor = false
int(1)   // $valor = true
int(0)   // $valor = "0"
int(1)   // $valor = "1"
int(0)   // $valor = []
int(0)   // $valor = ""
int(0)   // $valor = 0.0
int(0)   // $valor = -0.0
int(1)   // $valor = 1.0

That is, even passing booleans, strings, arrays and floating point numbers as parameter, the function will always return a valid value according to the value passed. Again, this solution can bring problems to application by bringing possibly unexpected results.

The three solutions are valid and will depend only on your need. For semantic reasons, I prefer solution 1, which only returns valid values when the input is 0 or 1, integers, which is apparently what is asked in the question.

Must-read

What’s a loose comparison?

1

As already stated in the other answer, the use of if is getting confused in the Ors:

if((empty($valor)) OR (strlen($valor) != 1)
  OR ($valor !=1 || $valor !=0)){

I believe that if accepted values are only 0 and 1 you can use one more check strict that in addition to making the code simpler it will avoid certain redundancies of checking.

Operators === and !== different from the != and == check both "value" and "type" in PHP, more details on Comparison Operators

So if the accepted values are only 0 and 1, being integer or string you can easily simplify like this:

function valida_variavel_zero_um($valor)
{
    if ($valor === 0 || $valor === "0" || $valor === 1 || $valor === "1") {
        return $valor;
    }

    return "INVALIDO";
}

Example in jsfiddle

There is also a function called in_array which supports strict checking as well:

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

Which can make it a lot easier to write to if, being like this:

function valida_variavel_zero_um($valor)
{
    if (in_array($valor, array(0, 1, '0', '1'), true)) {
        return $valor;
    }

    return "INVALIDO";
}

Example in jsfiddle


Values float

But of course the suggestions is if there are no possibly broken values, if there is this possibility in your code personally I find the Solution 3 of the most ideal Anderson, now if there is no possibility of such values float I believe strict checking will solve everything smoothly

Browser other questions tagged

You are not signed in. Login or sign up in order to post.