php - 从 mysql 数据库中提取序列化数据并在 php 中反序列化和使用各个字段

标签 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”和“Option4”。如何将它们提取为四个字符串或字符串数​​组?

编辑------------------------------------

按照建议我使用反序列化函数如下:

$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----------------------------

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

$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'

最佳答案

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

*_answer

...而实际上原始字符串(未回显)有这个(其中 <NUL> 表示空字节):

<NUL>*<NUL>_answer

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

[...] protected members have a '*' prepended to the member name. These prepended values have null bytes on either side.

如果你只接受回显字符串,然后尝试 unserialize那,你会得到你提到的错误,因为指示的字符串长度(如 s:10: )将不再对应于随后的空字节剥离属性名称的长度。

如果另一方面你unserialize原始字符串,它将生成数组,但随后元素将具有 protected 属性,这使得很难访问它们。

这是将空-星号-空序列替换为其他三个可读字符(我选择:“key”)的代码,同时保持长度不变。这样,unserialize函数不会产生 protected 属性,您可以使用诸如“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'];
}

关于php - 从 mysql 数据库中提取序列化数据并在 php 中反序列化和使用各个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38882158/

相关文章:

php - 使用 CSS/JS/PHP 在 CodeIgniter 中访问隐藏的无序列表

php - 需要帮助通过 PHP 在 MySQL 中设置 future 日期

php - 使用 cae bake 时错误数据库连接丢失

Python MySQL 日期格式

php - 无法使用 add_post_meta() 函数保存关联数组

php - 禁用 woocommerce_checkout_update_customer_data

php - 当我尝试在 symfony 4 中哈希我的密码时,出现这个错误是什么?

php - 使用 PHP/MySQL 简化数据库/登录流程

php - FuelPHP:多对多连接表中可能有额外的列吗?

html - 如何使用 CSS 控制标题 (H2) 的宽度?