从msql数据库中提取序列化数据并反序列化并使用php中的各个字段

时间:2016-08-10 19:40:17

标签: php mysql wordpress

我正在使用wordpress测验插件,我想直接从数据库表中提取问题和答案,并使用它来创建pdf文档。问题存储为一个易于提取的简单字符串,但答案(多选答案)存储在数据库列中,如下所示:

a:4:{i:0;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option1";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:1;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:1;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option2";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:2;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option3";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:3;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option4";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}}

这里有四个选项是' Option1',' Option2',' Option3'和'选项4'。如何将它们作为四个字符串或字符串数​​组提取?

EDIT ------------------------------------

如我所知,我使用了unserialize函数,如下所示:

$ser ='a:4:{i:0;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option1";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:1;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:1;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option2";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:2;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option3";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:3;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option4";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}}';

$un = unserialize($ser);
if(!is_array($un)){
    echo $un;
}else{
    foreach($un as $value){
    echo $value."\n";
    }
}

我收到以下错误:

PHP Notice:  unserialize(): Error at offset 63 of 822 bytes in <path> on line 5

我该如何解决这个问题?

EDIT2 ---------------------------

使用str_replace()代码时,我设置变量$ ser自己从mysql表中复制值。 现在当我通过php代码提取它时,变量$ ser不再是一个字符串。我不能把它强制转换成字符串。所以str_replace()不起作用。所以我尝试了正则表达式函数preg_replace(),但它无法替换&#39; * _&#39;一起来。所以我更换了&#39; *&#39;。 这是代码:

$host="<>"; // Host name 
$username="<>"; // Mysql username 
$password="<>"; // Mysql password 

    mysql_connect("$host", "$username", "$password")or die("cannot connect"); 
    mysql_select_db("<>")or die("cannot select DB");

    $sql="<the query>";

    $result = mysql_query($sql);
    $row=mysql_fetch_array($result);


    $ser = $row['answer_data'];
    echo $ser.'<br/><br/>';

    $pattern = '/\*/';
    $replace = '_00';
    $ser = preg_replace($pattern, $replace, $ser);
    echo $ser.'<br/><br/>';


    $un = unserialize($ser);
    $un = json_decode(json_encode($un));
    foreach($un as $obj){
        echo $obj->_00_answer;
    }



    mysql_close();

这是输出:

a:4:{i:0;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option1";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:1;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:1;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option2";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:2;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option3";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}i:3;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"*_answer";s:7:"Option4";s:8:"*_html";b:0;s:10:"*_points";i:1;s:11:"*_correct";b:0;s:14:"*_sortString";s:0:"";s:18:"*_sortStringHtml";b:0;s:10:"*_mapper";N;}}

a:4:{i:0;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"_00_answer";s:7:"Option1";s:8:"_00_html";b:0;s:10:"_00_points";i:1;s:11:"_00_correct";b:1;s:14:"_00_sortString";s:0:"";s:18:"_00_sortStringHtml";b:0;s:10:"_00_mapper";N;}i:1;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"_00_answer";s:7:"Option2";s:8:"_00_html";b:0;s:10:"_00_points";i:1;s:11:"_00_correct";b:0;s:14:"_00_sortString";s:0:"";s:18:"_00_sortStringHtml";b:0;s:10:"_00_mapper";N;}i:2;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"_00_answer";s:7:"Option3";s:8:"_00_html";b:0;s:10:"_00_points";i:1;s:11:"_00_correct";b:0;s:14:"_00_sortString";s:0:"";s:18:"_00_sortStringHtml";b:0;s:10:"_00_mapper";N;}i:3;O:27:"WpProQuiz_Model_AnswerTypes":7:{s:10:"_00_answer";s:7:"Option4";s:8:"_00_html";b:0;s:10:"_00_points";i:1;s:11:"_00_correct";b:0;s:14:"_00_sortString";s:0:"";s:18:"_00_sortStringHtml";b:0;s:10:"_00_mapper";N;}}

这是日志文件记录:

[11-Aug-2016 04:01:42 Etc/GMT] PHP Notice:  unserialize(): Error at offset 63 of 934 bytes in <path> on line 24
[11-Aug-2016 04:01:42 Etc/GMT] PHP Warning:  Invalid argument supplied for foreach() in <path> on line 26

EDIT3 -------------------

从数据库中提取时输出echo json_encode($ser);

"a:4:{i:0;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"\u0000*\u0000_answer\";s:7:\"Option1\";s:8:\"\u0000*\u0000_html\";b:0;s:10:\"\u0000*\u0000_points\";i:1;s:11:\"\u0000*\u0000_correct\";b:1;s:14:\"\u0000*\u0000_sortString\";s:0:\"\";s:18:\"\u0000*\u0000_sortStringHtml\";b:0;s:10:\"\u0000*\u0000_mapper\";N;}i:1;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"\u0000*\u0000_answer\";s:7:\"Option2\";s:8:\"\u0000*\u0000_html\";b:0;s:10:\"\u0000*\u0000_points\";i:1;s:11:\"\u0000*\u0000_correct\";b:0;s:14:\"\u0000*\u0000_sortString\";s:0:\"\";s:18:\"\u0000*\u0000_sortStringHtml\";b:0;s:10:\"\u0000*\u0000_mapper\";N;}i:2;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"\u0000*\u0000_answer\";s:7:\"Option3\";s:8:\"\u0000*\u0000_html\";b:0;s:10:\"\u0000*\u0000_points\";i:1;s:11:\"\u0000*\u0000_correct\";b:0;s:14:\"\u0000*\u0000_sortString\";s:0:\"\";s:18:\"\u0000*\u0000_sortStringHtml\";b:0;s:10:\"\u0000*\u0000_mapper\";N;}i:3;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"\u0000*\u0000_answer\";s:7:\"Option4\";s:8:\"\u0000*\u0000_html\";b:0;s:10:\"\u0000*\u0000_points\";i:1;s:11:\"\u0000*\u0000_correct\";b:0;s:14:\"\u0000*\u0000_sortString\";s:0:\"\";s:18:\"\u0000*\u0000_sortStringHtml\";b:0;s:10:\"\u0000*\u0000_mapper\";N;}}"

先前输出echo json_encode($ser);,即从phpmyadmin复制粘贴值:

"a:4:{i:0;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"*_answer\";s:7:\"Option1\";s:8:\"*_html\";b:0;s:10:\"*_points\";i:1;s:11:\"*_correct\";b:1;s:14:\"*_sortString\";s:0:\"\";s:18:\"*_sortStringHtml\";b:0;s:10:\"*_mapper\";N;}i:1;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"*_answer\";s:7:\"Option2\";s:8:\"*_html\";b:0;s:10:\"*_points\";i:1;s:11:\"*_correct\";b:0;s:14:\"*_sortString\";s:0:\"\";s:18:\"*_sortStringHtml\";b:0;s:10:\"*_mapper\";N;}i:2;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"*_answer\";s:7:\"Option3\";s:8:\"*_html\";b:0;s:10:\"*_points\";i:1;s:11:\"*_correct\";b:0;s:14:\"*_sortString\";s:0:\"\";s:18:\"*_sortStringHtml\";b:0;s:10:\"*_mapper\";N;}i:3;O:27:\"WpProQuiz_Model_AnswerTypes\":7:{s:10:\"*_answer\";s:7:\"Option4\";s:8:\"*_html\";b:0;s:10:\"*_points\";i:1;s:11:\"*_correct\";b:0;s:14:\"*_sortString\";s:0:\"\";s:18:\"*_sortStringHtml\";b:0;s:10:\"*_mapper\";N;}}"

所以现在确实有额外的角色。数据库中的排序规则是“utf8_general_c&#39;

1 个答案:

答案 0 :(得分:1)

序列化字符串在许多属性名称中都有空字节。当您echo时,这些不会显示。你会看到这样的:

*_answer

...实际上原始字符串(不是echo-ed)有这个(其中<NUL>代表一个空字节):

<NUL>*<NUL>_answer

这些空字节表示这些属性受到保护,如PHP documentation on serialize

中所述
  

[...]受保护的成员在成员名称前加上“*”。这些前置值在任一侧都有空字节。

如果你只是接受echo-ed字符串,然后尝试unserialize那你就会得到你提到的错误,因为指示的字符串长度(如s:10:)将不再对应到后面的null-byte-stripped属性名称的长度。

另一方面,如果您unserialize原始字符串,它将生成数组,但元素将具有受保护的属性,这使得很难访问它们。

这里的代码将用其他三个可读字符(我选择:“key”)替换null-asterisk-null序列,保持长度不变。这样,unserialize函数将不会生成受保护的属性,您可以使用“key_answer”等名称轻松访问它们:

// Replace two NUL bytes separated by an asterisk with three other characters: "key"
// Note that you need to use double quotes for the first argument.
// This will make it easier to access those properties:
$ser = str_replace("\0*\0_", 'key_', $ser);
// Now unserialize this:
$un = unserialize($ser);
// Avoid warnings about incomplete objects: 
// turn specific class objects to standard associative arrays:
$un = json_decode(json_encode($un), true);
// Extract the answers:
$answers = array_column($un, 'key_answer');
// Output the answers (but you could also use a foreach loop):
echo implode(",", $answers);

如果您的PHP版本低于5.5,则它不支持array_column。而只是写:

foreach($un as $row) {
    $answers[] = $row['key_answer'];
}