Validation function receives number 0 or 1

0

I made a validation function to accept only 1 or 0, but either 1 or 0 is interpreted as INVALID. Any suggestions on what the error 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;
     }

}
    
asked by anonymous 26.10.2017 / 19:34

2 answers

2

The error is in your condition.

  • When using empty , which can generate unexpected results, because empty(false) returns true, entering if , but empty(true) returns false;

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

  • In the ($valor !=1 || $valor !=0) part, because if $valor equals 0, the $valor != 1 condition is true, causing the program to enter if and return invalid; the same happens when $valor equals 1, because the condition $valor != 0 becomes true, also entering if . The correction of the problem boils down to changing the operator || to && ;

  • To show how strange the results might 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 at 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
    

    Notice 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 does not 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 you use the !== operator, you will check both the value and the type. When 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 will have the output:

    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 at Ideone | Repl.it

    Solution 2

    Another way to implement the function would be to explicitly type it by defining it in the function's argument list:

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

    See working at Ideone | Repl.it

    However, when calling the function with non-integer values, PHP will attempt to convert them to type int before passing them as a 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 mentioned by Victor in the comments, would be to try to parse the value of the parameter with the intval function, however, the problem of solution 2 persists in this solution, since the same type conversion that PHP does implicitly when the type is defined 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 at 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 if you pass booleans, strings, arrays, and floating-point numbers as a parameter, the function always returns a value that is valid according to the passed value. Again, this solution can lead to application issues by bringing possibly unexpected results.

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

    Required reading

    What is a loose comparison?

        
    27.10.2017 / 02:58
    1

    As already stated in the other answer, the use of if is confusing in the ORs:

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

    I believe that if the accepted values are only 0 and 1 you can use a strict check that not only makes the code simpler, it will still avoid certain check redundancies.

    The operators === and !== other than != 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 that supports strict check also:

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

    This can make it much easier to write if , thus:

    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 are if there are possibly broken values, if there is such a possibility in your code I personally find < strong> Solution 3 of Anderson the most ideal, now if there is no possibility of values of type float I believe that strict checking will solve everything without problems

        
    27.10.2017 / 04:05