How do you unserialize multiple strings of data with a loop? - php
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:
Unserialize each string (which lives in its own cell) of the column
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
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:
Reviewed the php documentation http://php.net/manual/en/function.unserialize.php
Review code examples on Stack Overflow
How to use php serialize() and unserialize()
How to get each value of unserialized data
Used tools like this http://unserialize.onlinephpfunctions.com/ to see how to use this function
Tried to implement my own code (see below)
After reading up on the topic/issue, I know I likely need to be using:
A loop (to loop through the serialized data)
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:
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?
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?
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!
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.
Related
Using Include Files with PHP Associative Array
I have an event listing page in a wordpress plugin I mage that is showing a date with times for that date.It shows 14 days worth. I’ve used an associated array to grab the server date and strip it down to a number. Each day has an include file associated with it. I’m trying to get it to sort those dates and then include that file so it will show. When use the following code, it works fine. Shows the key, date, value and name of the include for all the 14 days. $compare = array($getshow1=>("day1.php"),$getshow2=>("day2.php"),$getshow3=> ("day3.php"),$getshow4=>("day4.php"),$getshow5=>("day5.php"),$getshow6=>("day6.php"),$getshow7=>("day7.php"),$getshow8=>("day8.php"),$getshow9=>("day9.php"),$getshow10=>("day10.php"),$getshow11=>("day11.php"),$getshow12=>("day12.php"),$getshow13=>("day13.php"),$getshow14=>("day14.php")); ksort($compare); foreach($compare as $x => $x_value) { echo "Key=" . $x . ", Value=" . $x_value; echo "<br>"; } However when change it to the following sorth to try and use the includes, it works but for some reason only shows on about half of the 14. ksort($compare); foreach($compare as $x => $x_value) { include $x_value; } I’m thinking there is some function I need to use but I’ve working on this a while now and think I have code block. Any help would be appreciated.
use associative array key as string it will work fine :) Make sure that your php file should be in same directory if it is in different directory than define its proper path in array value. your array should look like this $compare = array( 'getshow1'=> "day1.php", 'getshow2'=> "day2.php", 'getshow3'=> "day3.php", 'getshow4'=> "day4.php", 'getshow5'=> "day5.php", 'getshow6'=> "day6.php", 'getshow7'=> "day7.php" ); and try again ksort($compare); foreach($compare as $x => $x_value){ include $x_value; }
For some reason, the sorting would not work if any of the fields were empty. So, I created a null value for each field and had it auto add that value if the user didn't enter a value when filling out the data. Using the getshow or $getshow in between '' did not work as it just sorted on that an not the actual variable that needs to be pulled in to each one of the 14. I dropped the '' and now with the no blanks everything is working as I needed it to.
Splitting an external array to give different titles
I've been trying to figure out how to split the array and add different titles for each of the separate titles on the page, for each of the different things that this displays. However the most I can manage to do is add a comma between the numbers and words. I would like to add selling"1st variable price"second variable" etc however I don't quite know how to do anything other than to turn this very confusing looking bunch of letters: user name and notes 01001000013972583957ecCCany amount-w378- v west into anything other than this: 0,100,10000,1397258395,7ec,CC,any amount-w378- v west Also, this is what it looks like in its JSON form: {"selling":"0","quantity":"100","price":"10000","date":"1397258395","rs_name":"7ec","contact":"CC","notes":"any amount-w378- v west"} I just want all the information that is in there to displayed like that however I'm not quite sure how to add the titles that is in the JSON data. I also don't have access to the external site to change anything. A little background: what I am trying to achieve is a price look-up for a game on my website from an external site. I tried to use an iframe but it was terrible; I would rather just manually display it rather than showing their site from mine - their style and my style clash terribly. $json = file_get_contents('http://forums.zybez.net/runescape-2007-prices/api/rune+axe'); $obj = json_decode($json,true); $blah1 = implode( $obj[0]["offers"][1]); print_r($blah1);
If you know where it is, you should be able to just grab it and show it out? You can use a failsafe to check if it is present with is_array() and isset() functions - see php.net docs on them. Your print_r should give you good valid info -- try to wrap it around <pre></pre> tags before for better readability or view the source - it will be easier! <pre><?php print_r($obj) ?></pre> This should be your starting point, and from here you will either take the first one of your items or loop through all with foreach ($obj as $o) { //should be $objects, not $obj //do whatever with $o, like echo $o['price'] }
Each offers row is a table with each field separated by row: $item = json_decode(file_get_contents('http://forums.zybez.net/runescape-2007-prices/api/rune+axe')); while ($offer = array_shift($item[0]->offers)) { echo "<table>" . PHP_EOL; foreach ($offer as $field => $value) { echo "<tr><th>$field</th><td>$value</td></tr>" . PHP_EOL; } echo "</table>" . PHP_EOL; } http://codepad.org/C3PQJHqL Tables in HTML: http://jsfiddle.net/G5QqZ/
Put a lot of data from an array into usable data?
Okay hi guys, I've been messing with my little side project today (had some great help on something I was stuck on & I've a new little issue I cant seem to get my head around. I'm sure its me just being stupid. So basically, I've a lot of data from a game (LoL) but I'm not sure how to structure this so it's readable, am I going to have to put it into an array and explode the contents? If so how? This is what I've got that's pulling the data from an API: <?php $summoner_name = 'amphios'; $summoner_id = 21554735; $profile = new riotapi('euw'); $summonername = $profile->getSummonerByName($summoner_name); print_r($summonername); $summonerstats = $profile->getStats($summoner_id, 'ranked'); print_r($summonerstats); $getsummoner = $profile->getSummoner($summoner_id, 'name'); print_r($getsummoner); ?> And this is what it's showing (sorry for the big wall of text): {"id":21554735,"name":"Amphios","profileIconId":588,"summonerLevel":30,"revisionDate":1390725829000}{"summonerId":21554735,"modifyDate":1390725829000,"champions":[{"id":89,"name":"Leona","stats":{"totalSessionsPlayed":1,"totalSessionsLost":1,"totalSessionsWon":0,"totalChampionKills":0,"totalDamageDealt":27547,"totalDamageTaken":21722,"mostChampionKillsPerSession":0,"totalMinionKills":17,"totalDoubleKills":0,"totalTripleKills":0,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":6,"totalGoldEarned":7288,"mostSpellsCast":0,"totalTurretsKilled":0,"totalPhysicalDamageDealt":6559,"totalMagicDamageDealt":20987,"totalFirstBlood":0,"totalAssists":12,"maxChampionsKilled":0,"maxNumDeaths":6}},{"id":254,"name":"Vi","stats":{"totalSessionsPlayed":1,"totalSessionsLost":0,"totalSessionsWon":1,"totalChampionKills":2,"totalDamageDealt":101554,"totalDamageTaken":18470,"mostChampionKillsPerSession":2,"totalMinionKills":122,"totalDoubleKills":0,"totalTripleKills":0,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":1,"totalGoldEarned":11358,"mostSpellsCast":0,"totalTurretsKilled":0,"totalPhysicalDamageDealt":81674,"totalMagicDamageDealt":18995,"totalFirstBlood":0,"totalAssists":15,"maxChampionsKilled":2,"maxNumDeaths":1}},{"id":103,"name":"Ahri","stats":{"totalSessionsPlayed":5,"totalSessionsLost":2,"totalSessionsWon":3,"totalChampionKills":33,"totalDamageDealt":583292,"totalDamageTaken":86957,"mostChampionKillsPerSession":10,"totalMinionKills":798,"totalDoubleKills":2,"totalTripleKills":0,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":22,"totalGoldEarned":55637,"mostSpellsCast":0,"totalTurretsKilled":0,"totalPhysicalDamageDealt":88954,"totalMagicDamageDealt":323163,"totalFirstBlood":0,"totalAssists":38,"maxChampionsKilled":10,"maxNumDeaths":7}},{"id":64,"name":"LeeSin","stats":{"totalSessionsPlayed":2,"totalSessionsLost":0,"totalSessionsWon":2,"totalChampionKills":15,"totalDamageDealt":283794,"totalDamageTaken":47208,"mostChampionKillsPerSession":8,"totalMinionKills":324,"totalDoubleKills":3,"totalTripleKills":1,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":7,"totalGoldEarned":26702,"mostSpellsCast":0,"totalTurretsKilled":2,"totalPhysicalDamageDealt":179409,"totalMagicDamageDealt":102365,"totalFirstBlood":0,"totalAssists":29,"maxChampionsKilled":8,"maxNumDeaths":4}},{"id":81,"name":"Ezreal","stats":{"totalSessionsPlayed":1,"totalSessionsLost":0,"totalSessionsWon":1,"totalChampionKills":10,"totalDamageDealt":168089,"totalDamageTaken":27079,"mostChampionKillsPerSession":10,"totalMinionKills":165,"totalDoubleKills":0,"totalTripleKills":0,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":8,"totalGoldEarned":15275,"mostSpellsCast":0,"totalTurretsKilled":3,"totalPhysicalDamageDealt":131121,"totalMagicDamageDealt":34756,"totalFirstBlood":0,"totalAssists":17,"maxChampionsKilled":10,"maxNumDeaths":8}},{"id":105,"name":"Fizz","stats":{"totalSessionsPlayed":1,"totalSessionsLost":1,"totalSessionsWon":0,"totalChampionKills":3,"totalDamageDealt":80294,"totalDamageTaken":21753,"mostChampionKillsPerSession":3,"totalMinionKills":114,"totalDoubleKills":0,"totalTripleKills":0,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":7,"totalGoldEarned":9389,"mostSpellsCast":0,"totalTurretsKilled":0,"totalPhysicalDamageDealt":19029,"totalMagicDamageDealt":60293,"totalFirstBlood":0,"totalAssists":12,"maxChampionsKilled":3,"maxNumDeaths":7}},{"id":2,"name":"Olaf","stats":{"totalSessionsPlayed":1,"totalSessionsLost":0,"totalSessionsWon":1,"totalChampionKills":5,"totalDamageDealt":183508,"totalDamageTaken":34625,"mostChampionKillsPerSession":5,"totalMinionKills":211,"totalDoubleKills":0,"totalTripleKills":0,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":7,"totalGoldEarned":14095,"mostSpellsCast":0,"totalTurretsKilled":3,"totalPhysicalDamageDealt":117878,"totalMagicDamageDealt":37453,"totalFirstBlood":0,"totalAssists":8,"maxChampionsKilled":5,"maxNumDeaths":7}},{"id":1,"name":"Annie","stats":{"totalSessionsPlayed":6,"totalSessionsLost":2,"totalSessionsWon":4,"totalChampionKills":49,"totalDamageDealt":905226,"totalDamageTaken":122780,"mostChampionKillsPerSession":12,"totalMinionKills":1045,"totalDoubleKills":5,"totalTripleKills":1,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":45,"totalGoldEarned":83361,"mostSpellsCast":0,"totalTurretsKilled":5,"totalPhysicalDamageDealt":84761,"totalMagicDamageDealt":813322,"totalFirstBlood":0,"totalAssists":53,"maxChampionsKilled":12,"maxNumDeaths":12}},{"id":0,"name":"Combined","stats":{"totalSessionsPlayed":18,"totalSessionsLost":6,"totalSessionsWon":12,"totalChampionKills":117,"killingSpree":60,"totalDamageDealt":2333304,"totalDamageTaken":380594,"mostChampionKillsPerSession":12,"totalMinionKills":2796,"totalDoubleKills":10,"totalTripleKills":2,"totalQuadraKills":0,"totalPentaKills":0,"totalUnrealKills":0,"totalDeathsPerSession":103,"totalGoldEarned":223105,"mostSpellsCast":0,"totalTurretsKilled":13,"totalPhysicalDamageDealt":709385,"totalMagicDamageDealt":1411334,"totalNeutralMinionsKilled":234,"totalFirstBlood":0,"totalAssists":184,"totalHeal":26727,"maxLargestKillingSpree":7,"maxLargestCriticalStrike":769,"maxChampionsKilled":12,"maxNumDeaths":12,"maxTimePlayed":3149,"maxTimeSpentLiving":1666,"normalGamesPlayed":0,"rankedSoloGamesPlayed":0,"rankedPremadeGamesPlayed":0,"botGamesPlayed":0}}]}{"summoners":[{"id":21554735,"name":"Amphios"}]} I'd like to be able to use a lot of this data, and have them in a sort of $api_data['username'] and $api_data['level'] and so on, or a better way.. I'm still getting used to large amounts of data like this.
Use json_decode function for converting your SJON string into PHP array: $api_data = json_decode($getsummoner);
You could use the PHP json_decode function like this; $json = '{"id":21554735,"name":"Amphios","profileIconId":588,"summonerLevel":30,"revisionDate":1390725829000}'; $arr = json_decode($json, true); echo "<xmp>".print_r($arr, true)."</xmp>"; // Display the contents of $arr. echo "Name is {$arr['name']}"; // Display the contents of $arr['name']. The above will output the following; Array ( [id] => 21554735 [name] => Amphios [profileIconId] => 588 [summonerLevel] => 30 [revisionDate] => 1390725829000 ) Name is Amphios
PHP arrays within arrays in session
I've been using PHP for a little bit, but only doing basic tasks, and have gotten stuck while trying to build part of a knowledgebase. While creating an article, you can upload screenshots - these need to be stored in a staging area until the article is saved, and I've got their information saved into the users session. In POST upload: ... $new_ss = array(); $new_ss['display_name'] = $ss_name; $new_ss['server_path'] = "../uploads/"; /* outside of doc root */ $new_ss['server_path'] .= hash_file('md5', $ss_tmp_name) . "_" . $ss_name; if ( #move_uploaded_file($ss_tmp_name, $new_ss['server_path']) ) { $_SESSION['article']['screenshots'] .= $new_ss; ... Then trying to display the upload to the user within the editing page: if ( is_array($_SESSION['article']['screenshots']) && count($_SESSION['article']['screenshots']) > 0 ) { echo "<table border=\"1\">\n"; foreach ( $_SESSION['article']['screenshots'] as $ss ) { ... display table of uploaded images ... The trouble is, PHP isn't seeing $_SESSION['article']['screenshots'] as an array - and I can't see why. After following the answer here: PHP foreach() with arrays within arrays? I tried quickly doing the following: function print_array($key, $item) { echo "$key -> $item\n"; } ... { $_SESSION['article']['screenshots'] .= $new_ss; array_walk_recurisve($_SESSION['article']['screenshots'], 'print_array'); ... however I get the error "expects parameter 1 to be array, string given". If I do an 'error_log($_SESSION['article']['screenshots']);' it just prints "Array" for however many images are uploaded, and print_r just printed '1' by itself. Can someone shed some light please?
Well I'm not really sure which of your key should be an array, in this line: $_SESSION['article']['screenshots'] .= $new_ss; You're making it a string by concatenating it. If you want to append as an array, you should probably do this: $_SESSION['article']['screenshots'][] = $new_ss;
Send PHP Array data to html table
I'm not a PHP pro and would really appreaciate some help with displaying some array data (pulled from an XML file) in an HTML table format. My array is setup as follows: $strTodayIs = date('l F/n'); foreach($xml->last7days->day AS $Daily) { //if (date('l F/n',(int)$Daily->starttime) != $strTodayIs) { $intAverageLastweek += (int)$Daily->avgresponse; $intDowntimeLast7 += (int)$Daily->totaldowntime; $intUptimeLast7 += (int)$Daily->totaluptime; array_push($arrLastWeek, array( "starttime" => $Daily->starttime, "response" => $Daily->avgresponse, "totalup" => $Daily->totaluptime, "totaldown" => $Daily->totaldowntime )); //} } I'm trying to display the results of some simple percentage calculations in an HTML table, using the data from the $arrLastWeek array. My end goal is to display the background colour of each cell depending on the calculated value of the data from the array, e.g. 100 = green, 100 to 99.8 = yellow, less than 99.8 =red. Again, any help even pointing me in the right direction would be greatly appreciated. Please let me know if I've left out any important info that could help me solve my problem? Regards, Eli
Basically you're going to do something like this: <?php foreach($array as $line): ?> <tr><td><?php echo $line['value']; ?></td><td><?php echo $line['value2']; ?></td></tr> <?php endforeach; ?> You can do math by setting PHP variables to zero before the foreach, and adding to them inside the foreach, and outputting them somewhere. Good luck