如何使用循环取消对多个数据字符串的序列化



问题

我有一个从mysql数据库导出的大csv文件。文件的一列中有序列化的字符串。我正试图找到一种方法:

  1. 取消序列化列的每个字符串(位于其自己的单元格中)
  2. 以类似于以下格式的方式输出文本:
array (
'weight' => '108 lbs', 'ah' => '24"', 'sw' => '50"', 'sdw' => '23"', 'shw' => '18"', 'sd' => '27"', 'sh' => '12"',
)

以下是未序列化行的示例(其中大约有1000行):

a:7:{s:6:"weight";s:6:"30 lbs";s:2:"ah";s:3:"26"";s:2:"sw";s:3:"20"";s:3:"sdw";s:0:"";s:3:"shw";s:3:"19"";s:2:"sd";s:3:"19"";s:2:"sh";s:3:"17"";}
a:7:{s:6:"weight";s:7:"107 lbs";s:2:"ah";s:3:"26"";s:2:"sw";s:3:"72"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}
a:7:{s:6:"weight";s:6:"37 lbs";s:2:"ah";s:0:"";s:2:"sw";s:0:"";s:3:"sdw";s:0:"";s:3:"shw";s:0:"";s:2:"sd";s:0:"";s:2:"sh";s:0:"";}
a:7:{s:6:"weight";s:6:"66 lbs";s:2:"ah";s:3:"26"";s:2:"sw";s:3:"50"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}
a:7:{s:6:"weight";s:6:"30 lbs";s:2:"ah";s:0:"";s:2:"sw";s:3:"26"";s:3:"sdw";s:0:"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"39"";s:2:"sh";s:3:"12"";}

问题

  1. 是否可以循环序列化数据,然后取消序列化并以所需格式(例如HTMLtable格式)显示

注意:虽然这个序列化的数据来自MySQL数据库,但如果可能的话,我不想再次挂接到数据库中检索这个序列化数据

尝试的解决方案

到目前为止,我已经:

  1. 查看了php文档http://php.net/manual/en/function.unserialize.php
  2. 查看堆栈溢出的代码示例
    • 如何使用php serialize()和unserialize(
    • 如何获取未序列化数据的每个值
  3. 像这样的二手工具http://unserialize.onlinephpfunctions.com/查看如何使用此函数
  4. 尝试实现我自己的代码(见下文)

在阅读了主题/问题后,我知道我可能需要使用:

  1. 循环(循环序列化数据)
  2. CCD_ 2或CCD_

代码示例

这是我用来获得上述结果的代码:

<?php 

$var1='a:7{s:6:"weight";s:7:"105lbs";s:2:"ah";s:3:"23"";s:2:"sw";s:3:"26"";s:3:"sdw";s:0:"";s:3:"shw";s:3:"17"";s:2:"sd";s:3:"80"";s:2:"sh";s:3:"12"";}';
$var2='a:7:{s:6:"weight";s:7:"108 lbs";s:2:"ah";s:3:"24"";s:2:"sw";s:3:"50"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}';
$combined = unserialize($var2);
$combined2 = unserialize($var1);
print_r($combined);
print_r($combined2);
?>

虽然我没有得到想要的输出,但我可以得到一些未序列化的数据显示在屏幕上:

Array ( [weight] => 108 lbs [ah] => 24" [sw] => 50" [sdw] => 23" [shw] => 18" [sd] => 27" [sh] => 12" ) Array ( [weight] => 105 lbs [ah] => 23" [sw] => 26" [sdw] => [shw] => 17" [sd] => 80" [sh] => 12" )

这是一个进步,但它是有问题的,因为它不是一个循环(手动输入),并且缺乏HTML标记,以便以后更容易格式化

如对此有任何见解,我们将不胜感激。提前感谢!


更新1

尝试的解决方案

我创建了一个只有一列和10行的临时CSV文件。请在此处查看CSV文件。

我曾尝试使用@geoffry共享的代码,但它似乎没有从我的csv文件中提取任何信息。我得到了一个无休止的循环(控制台中显示了1000个<tr>标签(但csv文件中没有内容)。

在用fgetscsv指向正确的方向后,我找到了下面的代码。有了这段代码,我可以将列以序列化的形式放到页面上,这样我就可以确保文件被正确打开。但这个循环忽略了非序列化步骤,这在这里更重要。

<?php
$filename = "myfilename.csv"; 
$id = fopen($filename, "r"); 
while ($data = fgetcsv($id, filesize($filename))) 
$table[] = $data; 
fclose($id);
echo "<table>n";
foreach($table as $row)
{
echo "<tr>";
foreach($row as $data)
echo "<td>$data</td>";
echo "</tr>n";
}
echo "</table>n";
?>

我尝试过将此代码的各个方面与下面的@geoffrey代码结合起来,但没有成功(例如,将unserialize代码添加到循环中)。

问题:

  1. 我在PHP fgetcsv手册的评论中读到,如果你是mac用户(我也是),你需要在代码中添加auto_detect_line_endings。我试过了,没有发现任何区别。这可能是问题的一部分吗
  2. fclose($fp);在@geoffrey的代码和我上面粘贴的代码中的位置不同。尝试在我的代码/循环的不同行/区域中使用它,但没有成功。这是我在代码中使用unserialized时没有看到任何内容的部分原因吗
  3. 我可能遗漏了什么

再次感谢您的真知灼见。非常感谢!

更新2

我可以使用一个名为maybe_unserialize的辅助函数来取消序列化数据的序列化。虽然我无法循环浏览所有代码,但使用PHP获得未序列化数组是朝着正确方向迈出的一步。

代码示例

<?php 
$original = array(
'a:7:{s:6:"weight";s:7:"149 lbs";s:2:"ah";s:3:"24"";s:2:"sw";s:3:"75"";s:3:"sdw";s:3:"23"";s:3:"shw";s:3:"18"";s:2:"sd";s:3:"27"";s:2:"sh";s:3:"12"";}'
);
$string = implode(", ", $original);
$done = maybe_unserialize($string);
var_export($done);
?>

希望这能帮助其他有类似问题的人!

由于您处理的是CSV,我假设您希望读取文件并迭代第5列中要取消序列化的数据所在的每一行。我还假设了所需的HTML输出格式,这应该足以让你上路。

<table>
<?PHP
$fp = fopen('file.csv', 'r');
while(($row = fgetcsv($fp)) !== false)
{
echo "<tr>";
$data = unserialize($row[5]);
foreach($data as $name => $value)
{
echo "<td>" . htmlspecialchars($name ) . "</td>";
echo "<td>" . htmlspecialchars($value) . "</td>";
}
echo "</tr>";
}
fclose($fp);
?>
</table>

您可能需要查看fgetcsv上的文档,因为您可能需要根据CSV格式指定其他参数。

最新更新