Cách tốt nhất để xác định xem một chuỗi có phải là kết quả của serialize()
hàm không?
Cách tốt nhất để xác định xem một chuỗi có phải là kết quả của serialize()
hàm không?
Câu trả lời:
Tôi muốn nói, hãy thử unserialize
nó ;-)
Trích dẫn hướng dẫn sử dụng:
Trong trường hợp chuỗi đã truyền không thể truy cập được, FALSE được trả về và E_NOTICE được cấp.
Vì vậy, bạn phải kiểm tra xem giá trị trả về có false
hay không (với ===
hoặc !==
, để chắc chắn không có bất kỳ vấn đề nào với 0
hoặc null
hoặc bất cứ điều gì tương đương với false
, tôi sẽ nói) .
Chỉ cần lưu ý thông báo: bạn có thể muốn / cần sử dụng toán tử @ .
Ví dụ :
$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
echo "ok";
} else {
echo "not ok";
}
Sẽ có em :
not ok
EDIT: Ồ, và như @Peter đã nói (cảm ơn anh ấy!), Bạn có thể gặp rắc rối nếu bạn đang cố gắng hủy xác nhận đại diện của một boolean false :-(
Vì vậy, kiểm tra xem chuỗi nối tiếp của bạn không bằng " b:0;
" cũng có thể hữu ích; một cái gì đó như thế này nên thực hiện các mẹo, tôi cho rằng:
$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
echo "ok";
} else {
echo "not ok";
}
kiểm tra trường hợp đặc biệt đó trước khi cố gắng hủy kích hoạt sẽ là một tối ưu hóa - nhưng có lẽ không hữu ích, nếu bạn thường không có giá trị nối tiếp sai.
Tôi đã không viết mã này, nó thực sự từ WordPress. Nghĩ rằng tôi bao gồm nó cho bất cứ ai quan tâm, nó có thể là quá mức cần thiết nhưng nó hoạt động :)
<?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;)
Nếu chuỗi $ là một false
giá trị được tuần tự hóa , tức là $string = 'b:0;'
hàm của SoN9ne trả về false
, thì nó đã sai
vì vậy chức năng sẽ là
/**
* 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.
Chúng ta không thể bắt lỗi E_NOTICE vì nó không phải là một ngoại lệ ném.
Mặc dù câu trả lời tuyệt vời của Pascal MARTIN, tôi tò mò liệu bạn có thể tiếp cận theo cách này không, vì vậy tôi đã làm điều này giống như một bài tập tinh thần
<?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 );
}
Và nó thực sự hoạt động. Nhắc nhở duy nhất là nó có thể sẽ bị hỏng nếu bạn có trình xử lý lỗi đã đăng ký vì cách $ php_errormsg hoạt động .
$a
và khử lưu huỳnh $b
, đó không phải là thiết kế ứng dụng thực tế.
$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
echo 'ok';
else
echo "not ok";
Xử lý chính xác các trường hợp serialize(false)
. :)
xây dựng thành một chức năng
function isSerialized($value)
{
return preg_match('^([adObis]:|N;)^', $value);
}
a:
(hoặc b:
vv) có mặt ở đâu đó bên trong $ value, không phải lúc đầu. Và ^
ở đây không có nghĩa là bắt đầu một chuỗi. Nó hoàn toàn sai lệch.
Có giải pháp WordPress: (chi tiết tại đây)
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;
}
}
Cái này làm việc tốt cho tôi
<?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));
}
?>
Tôi thích làm theo cách đó:
if (is_array(unserialize($serialized_string))):