Using Include Files with PHP Associative Array - php

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.

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.

Filter a php array to only elements that have a matching value to $name in $data

I have a php script getting all folders in a posts folder and making them into a list.
I have a $postinfo_str variable assigned to a json file for each folder which I am using to store post date and category/tag info etc in.
I also have a $pagetitle variable assigned to a title.php include file for each folder. So say I am on a "June 2018" archive page, the text in that file will be "June 2018". If I am on say a "Tutorials" category page, that will be the text in the title.php.
In the json file, I have:
{
"Arraysortdate": "YYYYMMDD",
"Month": "Month YYYY",
"Category": ["cat1", "cat2", "etc"]
}
I am ordering the array newest to oldest using krsort with Arraysortdate as key.
How do I filter the array using $pagetitle as input, finding if there is a match in $postinfo_str, and if there isn't, remove that folder from the array?
All I can seem to find regarding array sorting is where the info in the $pageinfo_str is basically the array and so by that, the $title is the input and the output is the matching text from the $postinfo_str, whereas I want the output to be the folders that only have the matching text in the $postinfo_str to what the input ($pagetitle) is.
Here is my code I have.. Keep in mind this is flat file, I do not want a database to achieve this. See comments if you want an explaination.
<?php
$BASE_PATH = '/path/to/public_html';
// initial array containing the dirs
$dirs = glob($BASE_PATH.'/testblog/*/posts/*', GLOB_ONLYDIR);
// new array with date as key
$dirinfo_arr = [];
foreach ($dirs as $cdir) {
// get current page title from file
$pagetitle = file_get_contents("includes/title.php");
// get date & post info from file
$dirinfo_str = file_get_contents("$cdir/includes/post-info.json");
$dirinfo = json_decode($dirinfo_str, TRUE);
// add current directory to the info array
$dirinfo['dir'] = $cdir;
// add current dir to new array where date is the key
$dirinfo_arr[$dirinfo['Arraysortdate']] = $dirinfo;
}
// now we sort the new array
krsort($dirinfo_arr);
foreach($dirinfo_arr as $key=>$dir) {
$dirpath = $dir['dir'];
$dirpath = str_replace('/path/to/public_html/', '', $dirpath);
?>
<!--HTML HERE SUCH AS--!>
TEXT <br>
<?php
};
?>
I have difficulties following your problem description. Your code example is slightly confusing. It appears to load the same global includes/title.php for each directory. Meaning, the value of $pagetitle should be the same every iteration. If this is intended, you should probably move that line right outside the loop. If the file contains actual php code, you should probably use
$pagetitle = include 'includes/title.php';
or something similar. If it doesn't, you should probably name it title.txt. If it is not one global file, you should probably add the path to the file_get_contents/include as well. (However, why wouldn't you just add the title in the json struct?)
I'm under the assumption that this happened by accident when trying to provide a minimal code example (?) ... In any case, my answer won't be the perfect answer, but it hopefully can be adapted once understood ;o)
If you only want elements in your array, that fulfill certain properties, you have essentially two choices:
don't put those element in (mostly your code)
foreach ($dirs as $cdir) {
// get current page title from file
$pagetitle = file_get_contents("includes/title.php");
// get date & post info from file
$dirinfo_str = file_get_contents("$cdir/includes/post-info.json");
$dirinfo = json_decode($dirinfo_str, TRUE);
// add current directory to the info array
$dirinfo['dir'] = $cdir;
// add current dir to new array where date is the key
// ------------ NEW --------------
$filtercat = 'cat1';
if(!in_array($filtercat, $dirinfo['Category'])) {
continue;
}
// -------------------------------
$dirinfo_arr[$dirinfo['Arraysortdate']] = $dirinfo;
array_filter the array afterwards, by providing a anonymous function
// ----- before cycling through $dirinfo_arr for output
$filtercat = 'cat1';
$filterfunc = function($dirinfo) use ($filtercat) {
return in_array($filtercat, $dirinfo['Category']));
}
$dirinfo_arr = array_filter($dirinfo_arr, $filterfunc);
you should read up about anonymous functions and how you provide local vars to them, to ease the pain. maybe your use case is bettersuited for array_reduce, which is similar, except you can determine the output of your "filter".
$new = array_filter($array, $func), is just a fancy way of writing:
$new = [];
foreach($array as $key => $value) {
if($func($value)) {
$new[$key] = $value;
}
}
update 1
in my code samples, you could replace in_array($filtercat, $dirinfo['Category']) with in_array($pagetitle, $dirinfo) - if you want to match on anything that's in the json-struct (base level) - or with ($pagetitle == $dirinfo['Month']) if you just want to match the month.
update 2
I understand, that you're probably just starting with php or even programming, so the concept of some "huge database" may be frightening. But tbh, the filesystem is - from a certain point of view - a database as well. However, it usually is quite slow in comparison, it also doesn't provide many features.
In the long run, I would strongly suggest using a database. If you don't like the idea of putting your data in "some database server", use sqlite. However, there is a learning curve involved, if you never had to deal with databases before. In the long run it will be time worth spending, because it simplifys so many things.

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.

How To Stop Duplicates Being Listed On PHP Results?

I've made up a PHP script which assigns a score to listings on a website and assigns it to the results page. I have got it to work in that it shows the score and the details but it keeps listing the same results over and over.
I can't work out what it is doing but there is a small section of code I was hoping would prevent duplicate listings. Could anyone give it a tweak and see if I am going wring somewhere?
The Code is:
$dupCatch .= $adId.",";
$dupResults = explode(',', $dupCatch);
foreach($dupResults as $dupResult){
if($dupResult == $adId){
print "";
} else {
print $showResults;
$scoreBox = 'THIS IS THE SCORE: ' . $finalScore . '';
print $scoreBox;
}
}
Thanks in advance!
Jack
The problem is that you add your current $adId to the duplicate list before you check if it is there - which it will always be, of course.
Storing a bunch of numbers in a string, explodeing it every time, is a little weird, use an array instead. You also don't need to manually loop through all the items, just use in_array()
if( !in_array($adId, $dupCatch) ){
print $showResults;
$scoreBox = 'THIS IS THE SCORE: ' . $finalScore . '';
print $scoreBox;
}
$dupCatch[] = $adId;
Needless to say: it would be a better idea to fix the part that gives you the duplicate results in the first place.
You can either try to use array_unique from php side or use unique attribute at field in mysql this way duplicates can be prevent before even inserting them.

MongoDB showing error when it finds a blank entry

I have a project where it searches for a specific entry in a specific column and then returns all documents that have that entry in that column. It works almost perfectly except when that entry field is empty it gives an error. Let me try to illustrate below.
My DB:
A|B|C|D
1|1|5|5
2|1| |6
3|2|7|7
4|2|8|8
My PHP:
$query = array( "B" => 1);
$cursor = $collection->find( $query );
foreach ($cursor as $obj) {
echo $obj["A"] . $obj["B"] . $obj["C"] .$obj["D"] . "<br />";
}
My output is:
1155
21Notice: Undefined index: C6
How do I go about not giving any errors. Just treat it as an empty field. I'm not sure if this is a common problem but, I'm still new to PHP and very new to MongoDB.
Use isset() to find out if the key exists in the array before trying to index using it
foreach ($cursor as $obj) {
echo $obj["A"] . $obj["B"]. (isset($obj["C"]) ? $obj["C"] : '' ) .$obj["D"]."<br />";
//It will replace each blank with an ''
}
I believe thats nothing to do with mongodb. Its how the flexible document schema works. It wont return the field because the key C doesnt exist in the particular document.
I dont have any experience with PHP. But am sure php throws the error because you are trying to access the key 'C' that doesnt exist in the particular document.
But i believe these problems can easily be solved if you use some ODM (Object document mappers). It solves the problem by assigning default value based on the data type of the field.
Hope it helps

Categories