确定字符串是否是serialize()函数的结果/输出的最佳方法是什么?
答案 0 :(得分:181)
我会说,尝试unserialize
它; - )
引用手册:
如果传递的字符串不是 unserializeable,返回FALSE 发布了E_NOTICE。
因此,您必须检查返回值是false
还是(使用===
或!==
,以确保{{1}没有任何问题}}或0
或等于null
的任何内容,我会说)。
请注意通知:您可能需要/需要使用@ operator。
例如:
false
会得到你:
$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
echo "ok";
} else {
echo "not ok";
}
编辑:哦,就像@Peter说的那样(感谢他!),如果你试图反序列化布尔值false的表示,你可能会遇到麻烦: - (
因此,检查序列化字符串是否不等于“not ok
”可能也会有所帮助;我认为这样的事情应该可以解决问题:
b:0;
在尝试反序列化之前测试该特殊情况将是一种优化 - 但如果您通常没有错误的序列化值,则可能没那么有用。
答案 1 :(得分:51)
我没有写这段代码,实际上是来自WordPress。以为我会把它包含在任何感兴趣的人中,它可能有点矫枉过正但它有效:)
<?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;
}
答案 2 :(得分:16)
优化Pascal MARTIN的回应
/**
* Check if a string is serialized
* @param string $string
*/
public static function is_serial($string) {
return (@unserialize($string) !== false);
}
答案 3 :(得分:14)
如果 $ string 是序列化的false
值,即$string = 'b:0;'
SoN9ne 的函数返回false
,这是错误的
所以函数将是
/**
* Check if a string is serialized
* @param string $string
*/
public static function is_serial($string) {
return (@unserialize($string) !== false || $string == 'b:0;');
}
答案 4 :(得分:13)
尽管Pascal MARTIN的答案非常好,但我很好奇你是否可以采用另一种方法,所以我这样做只是为了一次心理练习
<?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 works的注册错误处理程序,它可能会中断。
答案 5 :(得分:9)
$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
echo 'ok';
else
echo "not ok";
正确处理serialize(false)
的情况。 :)
答案 6 :(得分:3)
内置函数
function isSerialized($value)
{
return preg_match('^([adObis]:|N;)^', $value);
}
答案 7 :(得分:2)
/**
* 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;
}
}
答案 8 :(得分:2)
有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;
}
答案 9 :(得分:1)
这对我来说很好用
<?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));
}
?>
答案 10 :(得分:0)
请参见wordpress函数is_serialized
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;
}
答案 11 :(得分:0)
我只会尝试反序列化它。这就是我要解决的方式
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;
}
答案 12 :(得分:0)
提到的 WordPress function 并没有真正检测到数组(a:1:{42}
被认为是序列化的)并且在转义字符串如 true
上错误地返回 a:1:{s:3:\"foo\";s:3:\"bar\";}
(尽管 { {1}} 不起作用)
如果您在另一侧使用 unserialize
方式,例如 WordPress 会在使用 @unserialize
时在后端顶部添加一个难看的边距
define('WP_DEBUG', true);
答案 13 :(得分:-1)
我更喜欢这样做:
if (is_array(unserialize($serialized_string))):