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?