online - urlencode php
¿Por qué PHP considera que 0 es igual a una cadena? (7)
Debería usar ===
lugar de ==
, porque el operador ordinario no compara los tipos. En su lugar, intentará encasillar los elementos.
Mientras tanto, el ===
tiene en cuenta el tipo de elementos.
-
===
significa "igual", -
==
significa "eeeeh .. un poco parece"
Tengo el siguiente fragmento de código:
$item[''price''] = 0;
/*code to get item information goes in here*/
if($item[''price''] == ''e'') {
$item[''price''] = -1;
}
Está destinado a inicializar el precio del artículo a 0 y luego obtener información al respecto. Si el precio se informa como ''e'', significa un intercambio en lugar de una venta, que se indica con un valor negativo porque debe almacenarse en una base de datos que requiere un valor numérico.
También existe la posibilidad de dejar el precio en 0, ya sea porque el artículo es una bonificación o porque el precio se establecerá en un momento posterior.
Pero, siempre cuando el precio no está establecido, lo que lo deja con el valor inicial de 0, el ciclo if indicado arriba se evalúa como verdadero y el precio se establece en -1. Es decir, considera 0 como igual a ''e''.
¿Cómo se puede explicar esto?
Editar: cuando el precio se proporciona como 0 (después de la inicialización), el comportamiento es errático: a veces el if se evalúa como verdadero, a veces se evalúa como falso.
El operador == intentará hacer coincidir valores incluso si son de tipos diferentes. Por ejemplo:
''0'' == 0 will be true
Si también necesita una comparación de tipos, use el operador ===:
''0'' === 0 will be false
Esto se debe a cómo PHP realiza la operación de comparación que denota el ==
operador de comparación :
Si compara un número con una cadena o la comparación implica cadenas numéricas, cada cadena se convierte en un número y la comparación se realiza numéricamente. [...] La conversión de tipo no tiene lugar cuando la comparación es
===
o!==
ya que esto implica comparar el tipo y el valor.
Como el primer operando es un número ( 0
) y el segundo es una cadena ( ''e''
), la cadena también se convierte en un número (véase también la tabla Comparación con varios tipos ). La página de manual en el tipo de datos de cadena definió cómo se realiza la conversión de cadena a número :
Cuando se evalúa una cadena en un contexto numérico, el valor y el tipo de letra resultante se determinan de la siguiente manera.
Si la cadena no contiene ninguno de los caracteres ''
.
'',''e
''o''E
''y el valor numérico se ajusta a los límites de tipo entero (como se define enPHP_INT_MAX
), la cadena se evaluará como un número entero. En todos los demás casos se evaluará como un flotador.
En este caso, la cadena es ''e''
y, por lo tanto, se evaluará como un flotante:
El valor viene dado por la porción inicial de la cadena. Si la cadena comienza con datos numéricos válidos, este será el valor utilizado. De lo contrario, el valor será
0
(cero). Los datos numéricos válidos son un signo opcional, seguido de uno o más dígitos (que contienen opcionalmente un punto decimal), seguidos por un exponente opcional. El exponente es una ''e
'' o ''E
'' seguidas por uno o más dígitos.
Como ''e''
no comienza con datos numéricos válidos, se evalúa como float 0
.
Hay un método bastante útil en PHP para validar una mezcla de "0", "falso", "apagado" como == falso y "1", "on", "verdadero" como == verdadero que a menudo se pasa por alto. Es particularmente útil para analizar argumentos GET / POST:
filter_var( $item[''price''], FILTER_VALIDATE_BOOLEAN );
No es relevante para este caso de uso, pero dadas las similitudes y el hecho de que este es el resultado que la búsqueda tiende a encontrar al hacer la pregunta de validar (cadena) "0" como falsa, pensé que ayudaría a otros.
Su problema es el operador de doble igualdad, que encasillará el miembro correcto al tipo de la izquierda. Use estricto si lo prefiere.
if($item[''price''] == ''e'') {
$item[''price''] = -1;
}
Regresemos a su código (copiado arriba). En este caso, en la mayoría de los casos, $ item [''price''] es un entero (excepto cuando es igual a e, obviamente). Como tal, según las leyes de PHP, PHP convertirá "e"
a entero, lo que arroja int(0)
. (No me crea? <?php $i="e"; echo (int)$i; ?>
).
Para alejarse fácilmente de esto, use el operador de igualdad triple (comparación exacta), que verificará el tipo y no encasillará implícitamente.
PD: un hecho divertido de PHP: a == b
no implica que b == a
. Tome su ejemplo e inviértalo: if ("e" == $item[''price''])
nunca se cumplirá realmente siempre que $ item [''price''] siempre sea un entero.
usted está haciendo ==
que clasifica los tipos para usted.
0
es un int, por lo que en este caso va a convertir ''e''
a un int. Que no es analizable como uno, y se convertirá en 0
. ¡Una cadena ''0e''
se convertiría en 0
y coincidiría!
usar ===
"ABC" == 0
evalúa true
porque "ABC"
se convierte a entero y se convierte en 0
luego se compara con 0
.
Este es un comportamiento extraño del lenguaje PHP: normalmente uno esperaría que 0
se promoviera a la cadena "0"
y luego se comparara con "ABC"
con un resultado false
. Quizás eso es lo que sucede en otros lenguajes como JavaScript, donde la comparación débil "ABC" == 0
evalúa false
.
Hacer una comparación estricta resuelve el problema:
"ABC" === 0
evalúa false
.
Pero, ¿qué sucede si necesito comparar números como cadenas con números?
"123" === 123
evalúa false
porque los términos izquierdo y derecho son de diferente tipo.
Lo que realmente se necesita es una comparación débil sin las trampas de los malabares tipo PHP.
La solución es promocionar explícitamente los términos a cadena y luego hacer una comparación (estricto o débil ya no importa).
(string)"123" === (string)123
es
true
mientras
(string)"123" === (string)0
es
false
Aplicado al código original:
$item[''price''] = 0;
/*code to get item information goes in here*/
if((string)$item[''price''] == ''e'') {
$item[''price''] = -1;
}