Quelle est la meilleure façon de déterminer si une chaîne de caractères est ou non le résultat de l'exécution de la fonction serialize()
fonction ?
Mais que se passe-t-il si la valeur non sérialisée est un booléen avec la valeur FALSE ?
Quelle est la meilleure façon de déterminer si une chaîne de caractères est ou non le résultat de l'exécution de la fonction serialize()
fonction ?
Je dirais, essayez de unserialize
elle ;-)
Citation du manuel :
Dans le cas où la chaîne passée n'est pas unserializeable, FALSE est retourné et E_NOTICE est émis.
Donc, vous devez vérifier si la valeur de retour est false
ou non (avec ===
o !==
pour être sûr de ne pas avoir de problème avec 0
o null
ou tout ce qui est égal à false
je dirais) .
Attention à l'avertissement : vous pourriez avoir envie/besoin d'utiliser l'option @ opérateur .
Par exemple :
$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
echo "ok";
} else {
echo "not ok";
}
Vous obtiendrez :
not ok
EDIT : Oh, et comme @Peter l'a dit (merci à lui !), vous pourriez rencontrer des problèmes si vous essayez de désérialiser la représentation d'un booléen faux :-(
Ainsi, vérifier que votre chaîne sérialisée n'est pas égale à " b:0;
"Quelque chose comme ça devrait faire l'affaire, je suppose :
$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
echo "ok";
} else {
echo "not ok";
}
Tester ce cas spécial avant d'essayer de désérialiser serait une optimisation -- mais probablement pas si utile, si vous n'avez pas souvent une fausse valeur sérialisée.
@Peter : excellente remarque ; j'ai édité ma réponse avec une proposition pour traiter ce cas ; merci !
Merci. :) J'ai supposé que ce serait probablement la réponse Il me semble juste qu'il devrait y avoir un moyen de savoir s'il est sérialisé avant de forcer l'analyseur à tenter de le traiter.
De WordPress fonctions essentielles :
<?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;
}
J'avais essentiellement besoin d'une regex pour faire une détection de base, j'ai fini par l'utiliser : ^([adObis]:|N;)
La version actuelle de WordPress est un peu plus sophistiquée : codex.wordpress.org/Function_Reference/
+1 pour l'attribution des crédits. Je ne savais pas que WordPress avait cette fonction intégrée. Merci pour cette idée - je vais maintenant créer une archive des fonctions utiles du noyau de WordPress.
Malgré l'excellente réponse de Pascal MARTIN, j'étais curieux de savoir si vous pouviez aborder la question d'une autre manière, et j'ai donc fait cet exercice mental.
<?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 );
}
Et ça marche vraiment. Le seul problème est qu'il y aura probablement une rupture si vous avez un gestionnaire d'erreurs enregistré, en raison de la façon dont le programme $php_errormsg fonctionne .
+1 : Celui-ci est amusant, je dois l'admettre - je n'y aurais pas pensé ! Et je ne trouve pas de moyen de le faire échouer, aussi ^^ Beau travail ! Et merci pour le commentaire sur ma réponse : sans lui, je n'aurais probablement pas vu cette réponse.
$a = 'bla' ; $b = 'b:0;' ; Essayez de désérialiser $a puis $b avec ceci, les deux échoueront alors que $b ne devrait pas.
Pas s'il y a eu un échec juste avant. Parce que $php_errormsg contiendra toujours l'erreur de sérialisation d'avant et une fois que vous désérialisez faux alors il échouera.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.