2009-09-02 19 views

Respuesta

169

diría yo, tratar de unserialize ello ;-)

Citando el manual:

En caso de que la cadena pasada no es revertir la seriación, se devuelve FALSE y se emite E_NOTICE.

Por lo tanto, usted tiene que comprobar si el valor de retorno es false o no (con === o !==, para asegurarse de no tener ningún problema con 0 o null o cualquier cosa que es igual a false, diría).

Sólo tenga en cuenta el aviso: es posible que desee/necesite utilizar el @ operator.

Por ejemplo:

$str = 'hjkl'; 
$data = @unserialize($str); 
if ($data !== false) { 
    echo "ok"; 
} else { 
    echo "not ok"; 
} 

le conseguirá:

not ok 


EDIT: Ah, y como dijo @Peter (gracias a él!), Usted podría encontrarse con problemas si están intentando deserializar la representación de un valor booleano falso :-(

Por lo tanto, verificando que su cadena serializada no sea igual a "b:0; "podría ser útil también; algo como esto debe hacer el truco, supongo:

$data = @unserialize($str); 
if ($str === 'b:0;' || $data !== false) { 
    echo "ok"; 
} else { 
    echo "not ok"; 
} 

probar ese caso especial antes de tratar de unserialize sería una optimización - pero probablemente no tan útiles, si no tienen a menudo un valor serializado falsa.

+16

Pero, ¿y si el valor no serializado es un valor booleano con un valor FALSO? – Peter

+1

@Peter - es una cadena –

+1

@Peter: excelente observación; He editado mi respuesta con una propuesta para tratar ese caso; Gracias ! –

9
$data = @unserialize($str); 
if($data !== false || $str === 'b:0;') 
    echo 'ok'; 
else 
    echo "not ok"; 

Maneja correctamente la caja de serialize(false). :)

12

A pesar de una excelente respuesta de Pascal MARTIN, tenía curiosidad si pudiera acercarse a esto de otra manera, así que hice esto sólo como un ejercicio mental

<?php 

ini_set('display_errors', 1); 
ini_set('track_errors', 1); 
error_reporting(E_ALL); 

$valueToUnserialize = serialize(false); 
//$valueToUnserialize = "a"; # uncomment this for another test 

$unserialized = @unserialize($valueToUnserialize); 

if (FALSE === $unserialized && isset($php_errormsg) && strpos($php_errormsg, 'unserialize') !== FALSE) 
{ 
    echo 'Value could not be unserialized<br>'; 
    echo $valueToUnserialize; 
} else { 
    echo 'Value was unserialized!<br>'; 
    var_dump($unserialized); 
} 

Y realmente funciona. La única advertencia es que probablemente se rompa si tiene un controlador de error registrado debido a cómo $php_errormsg works.

+1

+1: ¡Esto es divertido, tengo que admitirlo, no lo hubiera pensado! Y tampoco encuentro una manera de hacerlo fallar ^^ ¡Buen trabajo! Y gracias por el comentario sobre mi respuesta: sin ella, probablemente no habría visto esta respuesta. –

+0

$ a = 'bla'; $ b = 'b: 0;'; Trate de deserializar $ a luego $ b con esto, ambos fallarán, mientras que $ b no debería. – bardiir

+0

@bardiir Funciona muy bien con una entrada literal de ''b: 0;' ' –

15

Optimización de la respuesta de Pascal MARTIN

/** 
* Check if a string is serialized 
* @param string $string 
*/ 
public static function is_serial($string) { 
    return (@unserialize($string) !== false); 
} 
45

No escribí este código, que es de WordPress realidad.Pensé que había incluyo para cualquier persona interesada, podría ser una exageración, pero funciona :)

<?php 
function is_serialized($data) { 
    // if it isn't a string, it isn't serialized 
    if (!is_string($data)) 
     return false; 
    $data = trim($data); 
    if ('N;' == $data) 
     return true; 
    if (!preg_match('/^([adObis]):/', $data, $badions)) 
     return false; 
    switch ($badions[1]) { 
     case 'a' : 
     case 'O' : 
     case 's' : 
      if (preg_match("/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data)) 
       return true; 
      break; 
     case 'b' : 
     case 'i' : 
     case 'd' : 
      if (preg_match("/^{$badions[1]}:[0-9.E-]+;\$/", $data)) 
       return true; 
      break; 
    } 
    return false; 
} 
+1

Básicamente necesitaba una expresión regular para hacer una detección básica, terminé usando: '^ ([adObis]: | N;)' – farinspace

+1

alternativa segura es esta función: https://gist.github.com/1415653 – bueltge

+5

actual La versión de WordPress es algo más sofisticada: http://codex.wordpress.org/Function_Reference/is_serialized#Source_File – ChrisV

0
/** 
* some people will look down on this little puppy 
*/ 
function isSerialized($s){ 
if(
    stristr($s, '{') != false && 
    stristr($s, '}') != false && 
    stristr($s, ';') != false && 
    stristr($s, ':') != false 
    ){ 
    return true; 
}else{ 
    return false; 
} 

} 
+4

bueno, esto sería válido para muchas cadenas JSON también, ¿no? Por lo tanto, no es confiable determinar si la cadena puede ser unificada/serializada. – Gordon

+0

Puede ser cierto, pero si la alternativa se serializa, o simplemente texto sin formato, como lo fue para mí, funciona como un encanto. –

+0

@ Björn3 "Bueno, esto funciona para mí en este caso específico" es una mentalidad muy mala a la hora de codificar. Hay muchos desarrolladores que son perezosos o que no tienen una visión de futuro como esta y hacen una pesadilla más adelante cuando otros desarrolladores tienen que trabajar con su código o intentar cambiar algo y de repente ya nada funciona correctamente. – BadHorsie

12

Si el $ string es un valor serializado false, es decir, la función $string = 'b:0;' SoN9ne 's devuelve false, está mal

lo que la función sería

/** 
* Check if a string is serialized 
* @param string $string 
*/ 
public static function is_serial($string) { 
    return (@unserialize($string) !== false || $string == 'b:0;'); 
} 
1

Esto funciona muy bien para mí

<?php 

function is_serialized($data){ 
    return (is_string($data) && preg_match("#^((N;)|((a|O|s):[0-9]+:.*[;}])|((b|i|d):[0-9.E-]+;))$#um", $data)); 
    } 

?> 
+0

Tenga en cuenta que comprueba si la cadena dada tiene una cadena de aspecto serializado; en realidad, no verificará la validez de esa cadena. – eithed

-2

Yo prefiero hacerlo de esa manera:

if (is_array(unserialize($serialized_string))): 
1

acumulación a una función

function isSerialized($value) 
{ 
    return preg_match('^([adObis]:|N;)^', $value); 
} 
0

Hay solución de WordPress: (detail is here)

function is_serialized($data, $strict = true) 
    { 
     // if it isn't a string, it isn't serialized. 
     if (!is_string($data)) { 
      return false; 
     } 
     $data = trim($data); 
     if ('N;' == $data) { 
      return true; 
     } 
     if (strlen($data) < 4) { 
      return false; 
     } 
     if (':' !== $data[1]) { 
      return false; 
     } 
     if ($strict) { 
      $lastc = substr($data, -1); 
      if (';' !== $lastc && '}' !== $lastc) { 
       return false; 
      } 
     } else { 
      $semicolon = strpos($data, ';'); 
      $brace = strpos($data, '}'); 
      // Either ; or } must exist. 
      if (false === $semicolon && false === $brace) 
       return false; 
      // But neither must be in the first X characters. 
      if (false !== $semicolon && $semicolon < 3) 
       return false; 
      if (false !== $brace && $brace < 4) 
       return false; 
     } 
     $token = $data[0]; 
     switch ($token) { 
      case 's' : 
       if ($strict) { 
        if ('"' !== substr($data, -2, 1)) { 
         return false; 
        } 
       } elseif (false === strpos($data, '"')) { 
        return false; 
       } 
      // or else fall through 
      case 'a' : 
      case 'O' : 
       return (bool)preg_match("/^{$token}:[0-9]+:/s", $data); 
      case 'b' : 
      case 'i' : 
      case 'd' : 
       $end = $strict ? '$' : ''; 
       return (bool)preg_match("/^{$token}:[0-9.E-]+;$end/", $data); 
     } 
     return false; 
    } 
Cuestiones relacionadas