php multi dimensional array's - php

I am pulling data out of a table that has these fields:
zipcode,city,state,county
My question is that some zip codes are in multiple cities, and some cities are in multiple zip codes... so is there a way to have all the data put into an array, then group all of the zip codes in order, then build a table out of that, so that it puts them in order, but if the data is redundant, like the zip, city, state and county are already in the array, then it skips it?
so then I can print it to the browser using echo, into a table like this:
74801 | Shawnee, Oklahoma | Pottawatomie
74801 | Bethel, Oklahoma | Pottawatomie
74801 | Johnson, Oklahoma | Pottawatomie
74851 | McLoud, Oklahoma | Pottawatomie
74851 | Dale, Oklahoma | Pottawatomie
etc.
But in the case of these:
74015 | CATOOSA, Oklahoma | Rogers
74015 | COTOOSA, Oklahoma | Rogers
Because those are duplicates in those fields (not in the rest of the table), I need it to skip showing it twice.
I think it is something like this:
$zipArray = array();
$zipCode = $dbhhandle->zip;
$cityName = $dbhhandle->city;
$countyName = $dbhhandle->county;
if($zipArray[$zipCode][$cityName] != $countyName) {
$zipArray[$zipCode][$cityName] = $countyName;
}
but I'm not sure if that is the right way to do it.
Then once I have the array built, how do I build the table?

Your code looks pretty close, but it's missing the state. So change the elements of the array into associative arrays with state and county elements.
Also, you need to check whether there's an entry for the zip code at all, before checking whether it's a duplicate, otherwise you'll access an undefined index.
$zipArray = array();
$zipCode = $dbhhandle->zip;
$cityName = $dbhhandle->city;
$countyName = $dbhhandle->county;
$stateName = $dbhandle->state;
if(!isset($zipArray[$zipCode][$cityName]) || $zipArray[$zipCode][$cityName]['county'] != $countyName) {
$zipArray[$zipCode][$cityName] = array('county' => $countyName, 'state' => $stateName);
}
To display the table, you use nested loops.
foreach ($zipArray as $zip => $cities) {
foreach ($cities as $city => $cityData) {
echo "<tr><td>$zip</td><td>$city, {$cityData['state']}</td><td>{$cityData['county']}</td></tr>";
}
}

Related

Passing String Arrays into PHP file with Android

I'm trying to use retrofit and PHP to store values in MySQL. I will pass in to the PHP a single postid string (postid) and a string array. For each index in the string array (called tags) I will make a unique row in the database. It will have the following form:
--------------------
|postid | tags |
--------------------
| postid | tags[0]|
| postid | tags[1]|
| postid | tags[2]|
....................
--------------------
The issue I am having is that for the string array, only the last value in the array is being stored.
Here is the retrofit interface
#FormUrlEncoded
#POST("create_recipe.php")
Call<Void> createRecipe(
#Field("postid") String postid,
#Field("tags") String[] tags
);
and the retrofit client call
Retrofit retrofit = ApiClient.getClient();
ApiInterface apiService = retrofit.create(ApiInterface.class);
Call<Void> call = apiService.createRecipe(postid, tags);
call.enqueue(new Callback<Void>() {
#Override
public void onResponse(Call<Void> call, Response<Void> response) {
}
#Override
public void onFailure(Call<Void> call, Throwable t) {
}
});
Here is what the PHP that handles this looks like (excluding some of the init code)
if (isset($_POST['postid']) && isset($_POST['tags']){
$uid = $_POST['postid'];
$tags = array($_POST['tags']);
$tags_new = str_replace(array('[', ',', ']'), '' , $tags);
foreach ($tags_new as $value){
mysql_query("INSERT INTO Tags(postid, tag) VALUES('$postid', '$value')");
}
}
If I pass in postid = 30 and tags = {"milk", "cheese", "bread"} I want it to look like
--------------------
|postid | tags |
--------------------
| 30 | milk |
| 30 | cheese |
| 30 | bread |
....................
--------------------
but instead only bread will be stored.
How do I handle the string array passed in as a parameter in PHP?
What is the form of the array when I pass it onto $tags?
I had the same problem some time back and found no clear solution for it. However I built a simple solution for something similar. I hope this solution helps.
Actually, you can print it out in the PHP work sheet, you can add the following to log the input here.
file_put_contents("test.log",json_encode($_POST)."--".json_encode($_GET));
Only then will you be able to determine whether the array is correctly delivered to the php script.
you might want to reconsider about this, because the following line is basically just removing all the barriers in the string($tags, which is now interpreted as a String instead of an array):
$tags_new = str_replace(array('[', ',', ']'), '' , $tags);
and change it into
$tags_new = split(',' , $tags);

(PHP) Aggregate counting of children in multidimensional array being populated in recursive function

I have a table in a MySQL database that represents a genetic language tree. Each row is a language with an ID and a parent ID; for example:
id | language | parent
-----+---------------------+--------
1 | Proto-Indo-European | NULL
6 | Celtic | 1
8 | Insular Celtic | 6
9 | Goidelic | 8
14 | Irish | 9
16 | Manx | 9
21 | British | 8
22 | Welsh | 21
109 | Germanic | 1
115 | West Germanic | 109
117 | Anglo-Saxon | 115
118 | Anglic | 117
119 | Old English | 118
My goal is to turn these rows into a pretty nested HTML list with aggregate counters after each language that has any child languages, using a simple recursive PHP function, resulting in something like this (based on the languages in the example rows above):
Proto-Indo-European (11)
Celtic (6)
Insular Celtic (5)
Goidelic (2)
Irish
Manx
British (1)
Welsh
Germanic (4)
West Germanic (3)
Anglo-Saxon (2)
Anglic (1)
Old English
I have the following PHP function (simplified here), which creates a multidimensional array with the proper structure:
function select_languages_hierarchical($parent = NULL) {
global $db;
$branch = array();
$query = "SELECT * FROM languages WHERE parent = $parent";
if ($q = $db->query($query)) {
while ($row = $q->fetch_assoc()) {
$element['id'] = $row['id'];
$element['name'] = $row['language'];
$children = select_languages_hierarchical($row['id']);
if ($children) {
$element['children'] = $children;
}
$branch[] = $element;
}
}
return $branch;
}
This produces an array that matches the nested list above, with nested arrays being in the children element of each array.
However, I simply cannot for the life of me, despite much brain-racking, Googling, and looking through oodles of recursion, aggregation-counting, and array-counting questions here on SO, figure out a way to create the counters that describe the number of descendent languages for each language.
Whatever I do, wherever I create, modify, and use my counter variables, and whatever I try counting (whether doing a ˋ$count++ˋ every time I iterate over a language, do a ˋcount($children)ˋ, etc.), I always end up with results where the counter is not reset when the function reaches a ‘higher’ level, so that I get lists like this instead:
Proto-Indo-European (12)
Celtic (6)
Insular Celtic (5)
Goidelic (2)
Irish
Manx
British (4)
Welsh
Germanic (9)
West Germanic (12)
Anglo-Saxon (14)
Anglic (15)
Old English
– Or something like that—the numbers and how they add up vary in the various different implementations I’ve attempted; but they all have in common that the counter keeps being increased throughout, without ever being reset. Or alternatively, if I do try to reset it at some point, naturally it gets reset on every iteration, leaving me with:
Proto-Indo-European (2)
Celtic (2)
Insular Celtic (1)
Goidelic (2)
Irish
Manx
British (1)
Welsh
Germanic (1)
West Germanic (1)
Anglo-Saxon (1)
Anglic (1)
Old English
Clearly, logic is not my strong suit here.
Can someone help my brain from spontaneously combusting and/or imploding by suggesting a way for me to achieve the kind of ‘intelligent tallying’ that I’m looking for here?
Thinking about it, instead of running a zillion recursive queries in PHP, you could just do a basic select * and build your tree in PHP, and do the counting there. Of cousre, this'd only be useful if you want the entire language tree.
$lang = array();
$sql = "SELECT * FROM languages";
... run query ...
while($row = fetch results) {
// store this lang's node
$lang[$row['id']]['name'] = $row['name'];
// add this language to its parent's child array
$lang[$row['parent']]['children'][$row['id']] = $row['id'];
// increment its parent's counter
$lang[$row['parent']]['count']++;
}
Now, this will probably spew out a bunch of warnings about undefined arrays and whatnot, since I'm not testing for the existence of a parent before trying to updates it's counts. But that's just some basic if (!isset()) { initialize node } type stuff.
Output into your nested <ul> would be a recursive function, but since you've now got the child-node counts in your tree already, it'll be much simpler:
function output($id = 1) { // assuming "1" is your tree root node
echo '<li>' . $lang[$id]['name'] . '(' . $lang[$id]['count'] . ')';
if ($lang[$id]['count'] > 0) {
echo '<ul>';
foreach($lang[$id]['children'] as $childID) {
output($childID);
}
echo '</ul>';
}
echo '</li>';
}

getting child id's from database dynamically?

I try to get the child id's of products dynamically.Below is my table structure.
parent|child
---------------------
44 | 35,6,47,5,50
---------------------
47 | 8,9
---------------------
50 | 12, 15
am going to pass only one parent id and get the child ids, and if anyone of child ids having again child, then i have to fetch that record also.example 44->35,6,47,5,50 in this 47 and 50 is having child ids, so my final output should be like this 44-> 35,6,47,8,9,5,50,12,15.
I tried below this,
$sql=mysql_fetch_assoc(mysql_query("select * from chain_product where parent='44'"));
$parent=$sql['parent'];
$child=$sql['child'];
$ex=explode(",",$child);
$count=sizeof($ex);
for($i=0;$i<$count;$i++)
{
$list=add_child($ex[$i],$child);
$check=explode(",",$list);
$chck_count=sizeof($check);
if($chck_count>$count)
{
$exit=add_child($ex[$i],$list);
print_r($exit);
}
}
function add_child($main,$ch)
{
$find=mysql_query("select * from chain_product where parent='$main'");
$res=mysql_fetch_assoc($find);
if($res)
{
$replace=$main.",".$res['child'];
$alter=str_replace($main,$replace,$ch);
echo $alter;
}
}
but i get the result like this,
35,6,47,8,9,5,5035,6,47,5,50,12,15
but i need output should be like this..
35,6,47,8,9,5,50,12,15.
can anyone help me to do this..
Your database structure isnt optimal for this, this would be better:
id | parent
1 | 0
2 | 1
3 | 1
4 | 2
5 | 2
This way you can do something recursive:
function getChilds($parent=0, $depth=0){
// Select the items for the given $parent
$query = $conn->mysqli_query("SELECT id WHERE parent=".$parent); // mysqli is better, but mysql will do fine
// get the items by the parent giving as input:
while($fetch = $query->fetch_assoc() ){
echo str_repeat('-', $depth) . " ".$fetch['id'];
getChilds($fetch['id'], $depth+1); // Use id of this line to find its childs
echo "<br />";
}
}
getChilds(0); // And start it. The 0 is optional, I personaly prefer -1. Whatever rows your boat
This is called a tree structure and should give something like this:
1
- 2
- - 4
- - 5
- 3
In this example I use an echo for display purposes, you can return the values via an array, same principle
To answer a bit better, your current structure could support a similar method, but because you use strings, it will be allow slower and alot less flexible. You can see the difference in the code you are using, and the amount I just used. If you would remove the echo's and only return arrays, it will be even smaller :)

Explode DB record into tabular format

I have a database connected to my site that is recording actions taken by a user on an application we have built. The application holds a number of images, which the user can view and download, and the application tracks, per user, which image they have viewed delimited by a comma
What I want to do is write a PHP script that will allow me to turn this delimited text string into a calculated table format
If the database has example records of:
1 | 1-A, 1-B, 2-A, 2-C
2 | 1-A
3 | 1-B, 2-C
4 |
5 | 1-A, 1-B, 1-C, 2-A
To which I wanted to write a script that would be able to output this as:
1-A = 3
1-B = 3
1-C = 1
2-A = 2
2-C = 2
(I want to point out, I'm not suggesting that I want to have variables named after each entry, with its calculated total as the value, I'm open to however is best to return this value)
My first step was to explode each record into an array, but then I wasn't sure as to my next step to turn this into something I can write into a table.
I realise the database is very poorly structured, but unfortunately I haven't written it, and so I have no ability to re-structure the data is stored.
Kind regards
this should work:
<?php
$values = array (
'1' => '1-A, 1-B, 2-A, 2-C',
'2' => '1-A',
'3' => '1-B, 2-C',
'4' => '',
'5' => '1-A, 1-B, 1-C, 2-A'
);
$valueCounts = array();
foreach($values as $value)
{
foreach(explode(', ', $value) as $val)
{
if(!key_exists($val, $valueCounts))
{
if($val) $valueCounts[$val] = 1;
}
else
{
$valueCounts[$val]++;
}
}
}
ksort($valueCounts);
foreach($valueCounts as $value => $count)
{
echo "$value = $count<br />";
}
?>
result:
1-A = 3
1-B = 3
1-C = 1
2-A = 2
2-C = 2
if you're not sure how to populate the $values array, please paste the database code and I will try and incorporate it into the above.

How can I put rows of MySQL data under the appropriate titles using PHP?

I have the following MySQL table structure:
num field company phone website
1 Gas abcd 123456789 abcd.com
2 Water efgh 987654321 efgh.com
3 Water ijkl 321654987 ijkl.com
4 Heat mnop 987654321 mnop.com
5 Gas qrst 123789654 qrst.com
...
Is it possible with PHP (maybe using some mixture of GROUP_BY and ORDER_BY) to echo the data to the screen in the following format:
Gas:
abcd qrst
123456789 123789654
abcd.com qrst.com
Water:
efgh ijkl
987654321 321654987
efgh.com ijkl.com
Heat:
mnop
321654987
mnop.com
The exact format of it isn't important. I just need for the different rows of data to be listed under the appropriate field with none of the fields repeated. I've been trying to figure this out for a while now, but I'm new to PHP and I can't seem to figure out how to do this, if it's even possible, or if there's a better way to organize my data to make it easier.
To avoid performing a "Gas" query, a "Water" query and a "Heat" query, you could order the results by "field" and then handle the display in PHP...
SELECT
Field,
Company,
Phone,
Website
FROM
tblYourTable
ORDER BY
Field
In your PHP loop, you would need to keep tabs on your current "Field" and start a new list when it changes. For example:
$CurrentField = '';
... loop
if ($MyData->Field != $CurrentField) {
$CurrentField = $MyData->Field;
....
}
... end loop
I will assume that you know how to retrieve MySQL data into an array... so, we have:
[0] {
num => 1,
field => "Gas",
company => "abcd",
phone => "123456789",
website => "abcd.com"
}
[1] ... (so on)
Then create a loop like:
foreach($data as $row) {
$service = $row["field"]; //Water, Gas, etc...
unset($row["field"]); //do not add this
foreach($row as $key => $value) {
$field[$service][$key][] = $value;
}
}
The resulting array will be something like:
$field["Gas"]["company"][0] = "abcd";
$field["Gas"]["company"][1] = "qrst";
$field["Water"]["company"][0] = "efgh";
...
$field["Gas"]["phone"][0] = "123456789";
$field["Gas"]["phone"][1] = "123789654";
$field["Water"]["phone"][0] = "987654321";
...
In that way you can then generate the output:
foreach($field as $service => $infoarr) {
echo $service."\n";
foreach($infoarr as $info => $datarr) {
foreach($datarr as $datum) {
echo $datum."\t";
}
echo "\n";
}
echo "\n";
}
Theorically (untested) will output:
Gas
abcd qrst
123456789 123789654
Water
efgh ...
I hope you find it useful... There should be a better way, but I didn't thought
too much about it...

Categories