确定字符串是否为serialize()
函数结果的最佳方法是什么?
确定字符串是否为serialize()
函数结果的最佳方法是什么?
Answers:
我会说,尝试unserialize
一下;-)
引用手册:
如果传递的字符串不是不可序列化的,则返回FALSE并发出E_NOTICE。
所以,你必须检查返回值是false
或不是(有===
或!==
,以确保不会有任何问题0
或null
或任何等于false
,我会说)。
只是当心通知:您可能希望/需要使用@运算符。
例如 :
$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
echo "ok";
} else {
echo "not ok";
}
会给你:
not ok
编辑:哦,就像@Peter说的(感谢他!),如果您试图反序列化布尔型false的表示,则可能会遇到麻烦:-(
因此,检查您的序列化字符串不等于“ b:0;
”也可能会有所帮助;我想像这样的东西应该可以解决问题:
$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
echo "ok";
} else {
echo "not ok";
}
在尝试反序列化之前测试该特殊情况将是一种优化-但是,如果您经常没有错误的序列化值,那么可能就没那么有用了。
我没有编写此代码,实际上是来自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;
}
^([adObis]:|N;)
如果$ string是一个序列化false
值,即$string = 'b:0;'
SoN9ne的函数返回false
,那就错了
所以功能是
/**
* Check if a string is serialized
*
* @param string $string
*
* @return bool
*/
function is_serialized_string($string)
{
return ($string == 'b:0;' || @unserialize($string) !== false);
}
In case the passed string is not unserializeable, FALSE is returned and E_NOTICE is issued.
我们无法捕获E_NOTICE错误,因为它不是引发的异常。
尽管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的工作方式,如果您已经注册了错误处理程序,它可能会中断。
$a
和反序列化之间进行错误检查$b
,这不是实际的应用程序设计。
内置功能
function isSerialized($value)
{
return preg_match('^([adObis]:|N;)^', $value);
}
a:
(或b:
等)出现在$ 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;
}
/**
* 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;
}
}