The error is in your condition.
When using the empty
, which may give rise to unexpected results because empty(false)
returns true, entering the if
, but empty(true)
returns false;
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;
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?
If 0, the condition
$valor != 1
is true and enters theif
. If 1, the condition$valor != 0
is true and enters theif
. Can you understand the problem?– Woss
Then I would have to work with $value != "1" that way?
– olifreitas
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
– Victor Pereira
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.
– olifreitas