确定字符串是否是 serialize()函数的结果的最佳方法是什么?
serialize()
Https://www.php.net/manual/en/function.serialize
我会说,尝试 unserialize它; -)
unserialize
引用手册:
如果传递的字符串不是 不可序列化,则返回 FALSE 并且 电子通知书已发出。
因此,必须检查返回值是否为 false。
false
注意: 您可能需要使用 @ 运营商。
例如:
$str = 'hjkl'; $data = @unserialize($str); if ($data !== false) { echo "ok"; } else { echo "not ok"; }
会让你:
not ok
编辑: 哦,就像@Peter 说的(多亏了他!)如果您试图反序列化一个布尔错误的表示,您可能会遇到麻烦:-(
因此,检查您的序列化字符串是否等于“ b:0;”也可能是有帮助的; 我认为类似于下面这样的方法应该可以解决这个问题:
b:0;
$data = @unserialize($str); if ($str === 'b:0;' || $data !== false) { echo "ok"; } else { echo "not ok"; }
在尝试反序列化之前测试这个特殊情况将是一种优化——但是如果您不经常有一个错误的序列化值,那么可能没有那么有用。
$data = @unserialize($str); if($data !== false || $str === 'b:0;') echo 'ok'; else echo "not ok";
正确处理 serialize(false)的情况。 :)
serialize(false)
尽管帕斯卡 · 马丁的回答很棒,我还是很好奇你们是否可以用另一种方式来处理这个问题,所以我这样做只是作为一种心理练习
<?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 ); }
而且真的有用。唯一需要注意的是,如果您有一个已注册的错误处理程序,那么它可能会中断,因为 $php _ errormsg 工作。
优化帕斯卡 · 马丁的回答
/** * Check if a string is serialized * @param string $string */ public static function is_serial($string) { return (@unserialize($string) !== false); }
来自 WordPress 核心职能:
<?php 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; }
/** * 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; } }
如果 $字符串是序列化的 false值,即 $string = 'b:0;' SoN9ne 的函数返回 false,这是错误的
$string = 'b:0;'
所以函数应该是
/** * Check if a string is serialized * * @param string $string * * @return bool */ function is_serialized_string($string) { return ($string == 'b:0;' || @unserialize($string) !== false); }
这对我来说没问题
<?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)); } ?>
嵌入到函数中
function isSerialized($value) { return preg_match('^([adObis]:|N;)^', $value); }
有 WordPress 解决方案: (详情在这里)
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; }
查看 wordpress 函数 被连载
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;
}
我会试着解开序列号,这就是我解决问题的方法
public static function is_serialized($string) { try { unserialize($string); } catch (\Exception $e) { return false; } return true; }
或者更像是助手函数
function is_serialized($string) { try { unserialize($string); } catch (\Exception $e) { return false; } return true; }
上面提到的 WordPress 功能并不真正检测数组(a:1:{42}被认为是序列化的) ,并且对转义字符串(如 a:1:{s:3:\"foo\";s:3:\"bar\";})错误地返回 true(尽管 unserialize不工作)
a:1:{42}
a:1:{s:3:\"foo\";s:3:\"bar\";}
true
例如,如果你在另一边使用 @unserialize的方式,在使用 define('WP_DEBUG', true);的时候,WordPress 在后端的顶部增加了一个难看的边距
@unserialize
define('WP_DEBUG', true);
function __is_serialized($var) { if (!is_string($var) || $var == '') { return false; } set_error_handler(function ($errno, $errstr) {}); $unserialized = unserialize($var); restore_error_handler(); if ($var !== 'b:0;' && $unserialized === false) { return false; } return true; }