4

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!

Community
  • 1
  • 1
  • 3
    So you read file line by line and unserialize every line. – u_mulder Jan 21 '19 at 13:20
  • what is your desired output? – devpro Jan 21 '19 at 13:22
  • What do you mean by _"and is lacking HTML markup for easier formatting later on"_? As far as I can tell, there's no HTML in the serialized data? – M. Eriksson Jan 21 '19 at 13:40
  • code example is messed up ? i get some notice : PHP Notice: unserialize(): Error at offset 0 of 144 bytes and Error at offset 30 of 145 bytes in... – FatFreddy Jan 21 '19 at 13:46
  • _“Is it possible to loop through serialized data, then unserialize it”_ - no, you need to do it the other way around - first unserialize it, and then loop over whatever in the resulting structure can be looped over. _“Here is a sample of the unserialized rows”_ - is that supposed to be _one_ row, or are this _five_ rows? – misorude Jan 21 '19 at 13:53
  • @u_mulder appreciate the help. But, for a file that has over 1000 lines, seems like a less than ideal way to go about this. – Andrew Jones Jan 22 '19 at 18:51
  • @devpro I'm hoping to have each serialized row to go from something like this: `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"";} ` to something like this: `weight: 108lbs, ah:24", sw: 50", sdw: 23", shw: 18", sd: 27", sh: 12"` Essentially, removing all the serialized quotes and semi-colons – Andrew Jones Jan 22 '19 at 18:52
  • @misorude that's 5 separate rows. Have you seen the answer below by @geoffry? Is that what you were referencing when you said "first unserialize it, then loop over it"? – Andrew Jones Jan 22 '19 at 18:58

1 Answers1

0

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.

Geoffrey
  • 10,843
  • 3
  • 33
  • 46
  • Please do not use comments for code, please update your question with what you have attempted and the result. Please also note that we are working blind as you have not provided a sample of your CSV. – Geoffrey Jan 22 '19 at 20:56
  • I've updated my question above. Thanks for your patience and help. – Andrew Jones Jan 23 '19 at 13:21
  • The sample file provided is not a [CSV](https://en.wikipedia.org/wiki/Comma-separated_values), are you sure this is the correct file you wish to parse? The file you have shown is just multiple lines of PHP serialised data. If you are truly using a CSV please provide the actual CSV with multiple columns so that we can truly see what is going on with the code. – Geoffrey Jan 24 '19 at 19:48