Andrew Jones
Andrew Jones

Reputation: 67

How do you unserialize multiple strings of data with a loop?

Problem

I have a large csv file that I've exported from a mysql database. One of the file's columns has serialized strings in it. I'm trying to find a way to:

  1. Unserialize each string (which lives in its own cell) of the column
  2. Output it in a way so the text is in a similar format to this:
    array (
  'weight' => '108 lbs', 'ah' => '24"', 'sw' => '50"', 'sdw' => '23"', 'shw' => '18"', 'sd' => '27"', 'sh' => '12"',
)

Here is a sample of the unserialized rows (there are about 1000 of these):

    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"";}

Questions

  1. Is it possible to loop through serialized data, then unserialize it and display it in a desired format (e.g. in a HTML table format)?

Note: although this serialized data is from a MySQL database, if possible, I'd prefer not have to hook into the database to retrieve this serialized data again.

Attempted Solutions

So far, I have:

  1. Reviewed the php documentation http://php.net/manual/en/function.unserialize.php
  2. Review code examples on Stack Overflow
  3. Used tools like this http://unserialize.onlinephpfunctions.com/ to see how to use this function
  4. Tried to implement my own code (see below)

After reading up on the topic/issue, I know I likely need to be using:

  1. A loop (to loop through the serialized data)
  2. var_export or var_dump to display the content in the desired format

Code Example

Here is the code I used to get the above result:

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

    ?>

Although I'm not getting the desired output, I am able to get some unserialized data to appear on the screen:

    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" )

This is progress but it is problematic since it isn't a loop (was manually inputted) and is lacking HTML markup for easier formatting later on.

Any insight on this would be greatly appreciated. Thanks in advance!


UPDATE 1

Attempted Solutions

I created a temporary CSV file with only one column and 10 rows. See the CSV file here.

I've attempted to use the code @geoffry shared, but it doesn't seem to be pulling any info in from my csv file. I was getting an endless loop (1000's of <tr> tags showing up in the console (but with no content from the csv file).

After being pointed in the right direction with fgetscsv, I found the code below. With this code, I'm able to get the columns onto the page in their serialized form, so I know for sure the file is being opened properly. But this loop leaves out the unserialize step, which is more important here.

<?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";

?>

I've tried combining aspects of this code and @geoffrey 's code below with no luck (for example, adding in the unserialize code to the loop).

Questions:

  1. I read in the comments of the PHP fgetscsv manual that if you're a mac user (which I am), you need to add auto_detect_line_endings into your code. I've tried this and didn't notice any difference. Could this be part of the problem?
  2. The placement of fclose($fp); in both @geoffrey 's code and the one I pasted above are different. Tried using it in different lines/areas of my code/loop without luck. Is this part of the reason why I'm not seeing anything when using unserialized in my code?
  3. Anything I might be missing?

Thanks again for any insight. Much appreciated!

UPDATE 2

I was able to unserialize the serialized data using a helper function called maybe_unserialize. While I wasn't able to loop through all the code, it was a step in the right direction being able to get an unserialized array using PHP.

Code Example

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

 ?>

Hopefully this help anyone else with a similar issue!

Upvotes: 4

Views: 1630

Answers (1)

Geoffrey
Geoffrey

Reputation: 11354

Since you're dealing with a CSV I will assume that you would want to read in the file and iterate each row where the data you wish to unserialize is in column 5. I am also assuming the HTML output format desired, this should be enought to get you on your way.

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

You may want to check the documentation on fgetcsv as you may need to specify additional arguments depending on your CSV format.

Upvotes: 0

Related Questions