Comparación de cadenas usando '==' vs. 'strcmp ()'

334

Parece que el ===operador de PHP distingue entre mayúsculas y minúsculas. Entonces, ¿hay alguna razón para usar strcmp()?

¿Es seguro hacer algo como lo siguiente?

if ($password === $password2) { ... }
Jiew Meng
fuente
10
¿Qué tiene que ver la mayúsculas y minúsculas strcmp?
kennytm
1
@KennyTM: distingue entre strcmpmayúsculas y minúsculas. En algunos idiomas, como VB, la comparación de cadenas puede no ser, y por lo tanto devolvería un resultado diferente. Sin embargo, este no es el caso en PHP.
cHao
13
@jie: es posible que desee utilizar en ===lugar de ==porque '0XAB' == '0xab'es cierto.
kennytm
17
usar === en lugar de == es importante, porque comparar cualquier cadena a 0 con == devolverá verdadero, lo que obviamente es falso ...
Karl Adler
44
@Kenny También '0xAB' == '171'
Antimonio

Respuestas:

329

La razón para usarlo es porque strcmp

devuelve <0 si str1 es menor que str2; > 0 si str1 es mayor que str2, y 0 si son iguales.

===solo regresa trueo falseno le dice cuál es la cadena "mayor".

difunto
fuente
99
icic tho en mi caso actual, no necesito saber qué cadena es mayor :)
Jiew Meng
155
strcmp con cadenas coincidentes tomó 0.207852 segundos strcmp con cadenas no coincidentes tomó 0.215276 segundos === con cadenas coincidentes tomó 0.067122 segundos === con cadenas no coincidentes tomó 0.057305 segundos snipplr.com/view/758
3
El otro uso para strcmp muestra la ordenación. Para ser más claro sobre la clasificación. strcmp () devuelve <0 si string1 se ordena antes de string2,> 0 si string2 se ordena antes de string1 o 0 si son iguales. Por ejemplo $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); devolverá más de cero, ya que aaao está ordenando antes que aabo.
HTML Man
20
¿Por qué esta respuesta recibe la mayor cantidad de votos? Estoy votando porque aunque es la respuesta que merece esta pregunta, pero no la respuesta "correcta". La respuesta correcta debería ser 'Usar ===' como mucha gente ya dijo en otras respuestas.
onur güngör
2
@onur güngör En realidad, esto hace respuestas a la pregunta de la OP, que es So is there any reason to use strcmp() ?, mientras que la respuesta de Postfuturist no lo hace. Oh, demonios ... hay una respuesta parecía compilar a la vez el uso de strcmp(), la actuación de ===, y la mala fiabilidad de ==las comparaciones de cadenas ... por lo que añade la mina a la lista.
Balmipour
222

Nunca debe usar ==para la comparación de cadenas. ===esta bien

$something = 0;
echo ('password123' == $something) ? 'true' : 'false';

Simplemente ejecute el código anterior y verá por qué.

$something = 0;
echo ('password123' === $something) ? 'true' : 'false';

Ahora, eso está un poco mejor.

postfuturista
fuente
19
== no es solo un problema para diferentes tipos. A veces dará resultados inesperados incluso si ambos lados son una cadena. Pruebe '1e3' == '1000'
Antimonio
3
¿Cómo 0 == 'contraseña123'?
Andy Lobel
24
@AndyLobel PHP coacciona 'contraseña123' a un número usando sus reglas de comparación sueltas, ya que el otro operando es un número, esa cadena, como la mayoría, coacciona al número 0, y PHP devuelve verdadero para la comparación.
postfuturista
8
Un var_dump rápido ((int) 'contraseña123'); me ayudó a entender completamente por qué sucedió esto ... ** avergonzado ** ... Realmente me gusta el operador ===
Carlton el
3
esto se debe a que usa '==' si uno de los dos operandos se puede convertir en número, php convierte ambos operandos en números y más, si una cadena no numérica se convierte en número, toma el valor cero, lo que resulta igual a cero, así que el resultado de la comparación con '==' simple puede ser algo no deseado
Luca C.
98

No lo uses ==en PHP. No hará lo que esperas. Incluso si está comparando cadenas con cadenas, PHP las convertirá implícitamente en flotantes y hará una comparación numérica si aparecen numéricas.

Por ejemplo, '1e3' == '1000'devuelve verdadero. Deberías usar ===en su lugar.

Antimonio
fuente
16
Pero puedes simplemente ===.
Roman Newaza
11
@Roman sí, pero muchos programadores PHP no saben que tienen que hacer eso. De ahí la advertencia.
Antimonio el
55
@Antimony Entonces, ¿por qué no decirles qué deben hacer en su respuesta?
Tim
43

Bueno ... según este informe de error de php , incluso puedes obtener 0wned.

<?php 
    $pass = isset($_GET['pass']) ? $_GET['pass'] : '';
    // Query /?pass[]= will authorize user
    //strcmp and strcasecmp both are prone to this hack
    if ( strcasecmp( $pass, '123456' ) == 0 ){
      echo 'You successfully logged in.';
    }
 ?>

Te da una advertencia, pero aún así evita la comparación.
Deberías estar haciendo lo ===que sugirió @postfuturist.

Ajith
fuente
55
Wow +1. Cita del enlace: "Es un comportamiento establecido para la función que recibe el tipo incorrecto de argumento (s) para devolver nulo". Es sorprendente teniendo en cuenta que el manual solo dice esto: "Devuelve <0 si str1 es menor que str2;> 0 si str1 es mayor que str2 y 0 si son iguales". Nulo no se menciona como una posibilidad, sin embargo, en páginas como la página del manual substr se menciona. suspiro
Gerry
¿Pero sucede lo mismo cuando el método de formulario es post ...?
3lokh
@NikhilGeorge Sí, la función en cuestión aquí es strcmp. No importa con qué entradas se comparan.
Ajith
Si bien el informe de error dice que estaba bien devolver nulo, esto es incorrecto. Todas las versiones oficiales de PHP de PHP 4.3 a PHP 7.3 no devuelven valores nulos de estas funciones. Sospecho que puede haber sido una versión alfa o beta, e independientemente de que el error que se cierra no sea válido, se solucionó. Consulte 3v4l.org/Zq8tM para obtener detalles, que muestran que sí afecta a HHVM 3.11 - 3.19.
Timo Tijhof
33

Siempre recuerde, cuando compare cadenas, debe usar ===operador (comparación estricta) y no == operador (comparación suelta).

DataPriest
fuente
8
En realidad, creo que es seguro decir que debes usarlo ===al comparar cualquier cosa .
rink.attendant.6
22

Resumiendo todas las respuestas:

  • ==Es una mala idea para las comparaciones de cadenas.
    Le dará resultados "sorprendentes" en muchos casos. No te fíes de eso.

  • === está bien y te dará el mejor rendimiento.

  • strcmp() debe usarse si necesita determinar qué cadena es "mayor", generalmente para las operaciones de clasificación.

Balmipour
fuente
20

Usar ==puede ser peligroso.

Tenga en cuenta que convertiría la variable a otro tipo de datos si los dos difieren.

Ejemplos:

  • echo (1 == '1') ? 'true' : 'false';
  • echo (1 == true) ? 'true' : 'false';

Como puede ver, estos dos son de diferentes tipos, pero el resultado es trueque podría no ser lo que su código esperará.

El uso ===, sin embargo, se recomienda como prueba muestra que es un poco más rápido que strcmp()y su alternativa entre mayúsculas y minúsculas strcasecmp().

Google rápido grita esta comparación de velocidad: http://snipplr.com/view/758/

Nikola Petkanski
fuente
1
A veces los arroja a un tipo diferente, incluso si ya tienen el mismo tipo.
Antimonio
incluso cuando se comparan dos cadenas que representan un número entero como "012" == "12"php, se cambia el tipo de ambas cadenas a entero 12 == 12y luego se devuelve true.
GoTo
6

¡strcmp devolverá diferentes valores según el entorno en el que se esté ejecutando (Linux / Windows)!

La razón es que tiene un error ya que el informe de error dice https://bugs.php.net/bug.php?id=53999

Por favor maneje con cuidado !! Gracias.

kta
fuente
Sin embargo, siempre devolverá 0 si las cadenas son iguales. +1 por tener cuidado al preocuparse por cualquier otro valor que no sea 0.
contrato del Prof. Falken incumplió el
4

Puede usarlo strcmp()si desea ordenar / comparar cadenas lexicográficamente . Si solo desea verificar la igualdad, entonces ==está bien.

Daniel Egeberg
fuente
1
Como en usort . De hecho, está prácticamente hecho para clasificar.
Charles
@Charles Gracias. Wikipedia hizo que mis ojos se pusieran vidriosos.
cbednarski
1
Para ser más claro sobre la clasificación. strcmp () devuelve <0 si string1 se ordena antes de string2,> 0 si string2 se ordena antes de string1 o 0 si son iguales. Por ejemplo $ string_first = "aabo"; $ string_second = "aaao"; echo $ n = strcmp ($ string_first, $ string_second); devolverá más de cero, ya que aaao está ordenando antes que aabo.
HTML Man
@postfuturist Estoy seguro de que es un error tipográfico y querían decir ===.
ceniza
4

Además, la función puede ayudar en la clasificación. Para ser más claro sobre la clasificación. strcmp () devuelve menos de 0 si string1 se ordena antes de string2, mayor que 0 si string2 se ordena antes de string1 o 0 si son iguales. Por ejemplo

$first_string = "aabo";
$second_string = "aaao";
echo $n = strcmp($first_string,$second_string);

La función devolverá más de cero, ya que aaao está ordenando antes que aabo.

HTML Man
fuente
0

PHP En lugar de usar la ordenación alfabética, use el valor ASCII del carácter para hacer la comparación. Las letras minúsculas tienen un valor ASCII más alto que las mayúsculas. Es mejor usar el operador de identidad === para hacer este tipo de comparación. strcmp () es una función para realizar comparaciones de cadenas seguras binarias. Toma dos cadenas como argumentos y devuelve <0 si str1 es menor que str2; > 0 si str1 es mayor que str2, y 0 si son iguales. También hay una versión que no distingue entre mayúsculas y minúsculas llamada strcasecmp () que primero convierte las cadenas en minúsculas y luego las compara.

Alireza Rahmani Khalili
fuente
0

if ($password === $password2) { ... }No es algo seguro cuando se comparan contraseñas o hashes de contraseña donde una de las entradas es controlada por el usuario.
En ese caso, crea un oráculo de tiempo que permite a un atacante derivar el hash de contraseña real a partir de las diferencias de tiempo de ejecución.
Use en su if (hash_equals($password, $password2)) { ... }lugar, porque hash_equals realiza una "comparación segura de cadenas de ataque de tiempo"

Ali
fuente