web-dev-qa-db-ja.com

文字列がシリアル化されているかどうかを確認しますか?

文字列がserialize()関数の結果/出力であるかどうかを判断する最良の方法は何ですか?

127
Dang

unserialize it ;-)にしてみてください

マニュアルの引用:

渡された文字列がシリアライズ可能でない場合、FALSEが返され、E_NOTICEが発行されます。

したがって、戻り値がfalseであるかどうかを確認する必要があります===または!==で、0またはnull、またはfalseに等しいものに問題がないことを確認するために、 d say).

通知に注意してください: @ operator を使用する必要がある場合があります。

例えば ​​:

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

あなたを取得します:

not ok


[。

したがって、シリアル化された文字列が「b:0;」と等しくないことを確認することも役立ちます。このような何かがトリックを行うはずです、私は思う:

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

シリアル化を解除する前にその特殊なケースをテストすることは最適化になりますが、誤ったシリアル化された値が頻繁にない場合は、おそらくそれほど有用ではありません。

182
Pascal MARTIN

私はこのコードを書きませんでした。実際は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;
}
53

Pascal MARTINの応答の最適化

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

$ stringがシリアル化されたfalse値、つまり$string = 'b:0;'SoN9neの関数が返す場合false、間違っています

そのため、関数は

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

パスカル・マーティンの優れた答えにもかかわらず、この別の方法でアプローチできるかどうか興味があったので、メンタルエクササイズとしてこれを行いました

<?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が機能する の方法が原因で、登録済みのエラーハンドラーがあると壊れる可能性があることです。

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

serialize(false)のケースを正しく処理します。 :)

10
chaos

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;
    }
3
ingenious

関数に組み込む

function isSerialized($value)
{
   return preg_match('^([adObis]:|N;)^', $value);
}
3
RossW
/**
 * 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;
}

}
2
Björn3

これは私のためにうまくいきます

<?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));
    }

?>
1