PHP arrays within arrays in session - php

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;

Related

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

conditional check inside a foreach is causing errors

I am using Simple_html_dom trying to grab Reputation points and make a check on those values and then extract only those user profiles whose Repu is greater that 200. Below is the code, It works fine when doing this
`
$html2=str_get_html($html1);
foreach ($html2->find('.user-details') as $value) {
foreach($html2->find('.reputation-score') as $repu){
echo (int)$repu->plaintext.$value.'<br>';
}
}
When doing the above i am getting all thereputation and the user detailswell each line, looks fine till now. But now i wanna perform aconditional checkand then echo only those profiles whose repo is higher than100`. So when i am trying the below code
`
$html2=str_get_html($html1);
foreach ($html2->find('.user-details') as $value) {
foreach($html2->find('.reputation-score') as $repu){
if($repu>100)
{
echo ($repu->plaintext.$value.'<br>';
}
}
}
I am getting an error saying Object of class simple_html_dom_node could not be converted to int seeing that i've tried doing (int) to convert and then echo still couldnt solve
Any help here ?

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.

Why is my first value in reset() null?

I have a server with a directory full of books. I wrote a script which loops through this directory and lists out all the PDF's that are located inside. I then took it a step further and started searching Google books and bringing back the picture and description of these books. For some of the books this works perfectly, but for a good number of them I get this error...
Warning: reset() expects parameter 1 to be array, null given in bookDescriber.php on line 49
This the code that is giving this error (this is all inside a big foreach, which lists all the PDFs in the directory). the last line of this code is line 49.
//search GoogleBooks for a description
$item = file_get_contents("https://www.googleapis.com/books/v1/volumes?q=$v&maxResults=1");
$item = json_decode($item);
$item = reset($item->items);
the $v in the above url is simply the filename of the book, so this is one of the links it would generate and as you can see this does return information... (if you copy the entire link all the way to maxResults=1 then the data is returned, could it be that sometimes the spaces in the URL don't matter and sometimes they do?? I'm lost)
https://www.googleapis.com/books/v1/volumes?q=Ajax the definitive guide.pdf&maxResults=1
so why is the first parameter in my reset() set to null??? Help please!!
I've tested around with that snippet and it can be recreate if:
$v is blank
The book doesn't exist
If the book doesn't exist, the null error is thrown and Google returns:
{
"kind": "books#volumes",
"totalItems": 0
}
This isn't enough information to create an array. You are better off having a check like so:
<?php
$item = file_get_contents("https://www.googleapis.com/books/v1/volumes?q=$v&maxResults=1");
if(is_array($item))
{
$item = json_decode($item);
$item = reset($item->items);
}
else
{
return false; // echo 'no book';
}
?>

parsing SEO friendly url without htaccess or mode_rewrite

Can anyone suggest a method in php or a function for parsingSEO friendly urls that doesn't involve htaccess or mod_rewrite? Examples would be awesome.
http://url.org/file.php/test/test2#3
This returns: Array ( scheme] => http [host] => url.org [path] => /file.php/test/test2 [fragment] => 3 ) /file.php/test/test2
How would I separate out the /file.php/test/test2 section? I guess test and test2 would be arguments.
EDIT:
#Martijn - I did figure out what your suggested before getting the notification about your answer. Thanks btw. Is this considered an ok method?
$url = 'http://url.org/file.php/arg1/arg2#3';
$test = parse_url($url);
echo "host: $test[host] <br>";
echo "path: $test[path] <br>";
echo "frag: $test[fragment] <br>";
$path = explode("/", trim($test[path]));
echo "1: $path[1] <br>";
echo "2: $path[2] <br>";
echo "3: $path[3] <br>";
echo "4: $path[4] <br>";
You can use explode to get the parts from your array:
$path = trim($array['path'], "/"); // trim the path of slashes
$path = explode("/", $path);
unset($path[0]); // the first one is the file, the others are sections of the url
If you really want to make it zerobased again, add this as last line:
$patch = array_values($path);
In response to your edit:
You want to make this as flexible as you can, so no fixed coding based on a max of 5 items. Although you probably will never exceed that, just don't pin yourself to it, just overhead you dont need.
If you have a pages system like this:
id parent name url
1 -1 Foo foo
2 1 Bar, child of Foo bar-child-of-foo
Make a recursive function. Pass the array to a function which takes the first section to find a root item
SELECT * FROM pages WHERE parent=-1 AND url=$path[0]
That query will return an id, use that in the parent column with the next value of the array. Unset each found value of the $path array. In the end, you will have an array with the remaining parts.
To sketch an example:
function GetFullPath(&$path, $parent=-1){
$path = "/"; // start with a slash
// Make the query for childs of this item
$result = mysqli_query($conn, "SELECT * FROM pages WHERE parent=".$parent." AND url=".current($path)." LIMIT 1");
// If any rows exists, append more of the url via recursiveness:
if($result->num_rows!==0){
// Remove the first part so if we go one deeper we start with the next value
$path = array_slice($patch,1); // remove first value
$fetch = $result->fetch_assoc();
// Use the fetched value to go deeper, find a child with the current item as parent
$path.= GetFullPath($path, $fetch['parent']);
}
// Return the result. if nothing is found at all, the result will be "/", probs home
return $path;
}
echo GetFullPath($path); // I pass it by reference, any alterations in the function happen to the variable outside the scope aswell
This is a draft, I did not test this, but you get the idea im trying to sketch. You can use the same method to get the ID of the page you are at. Just keep passing the variable back up again c
One of these days im getting the hang of recursiveness ^^.
Edit again: Oops, that turned out to be quite some code.

Categories