PHP: foreach loop with array_merge to create json objects - php

I'm new to php but i really like like it so far!
Now i stumbled over a problem with array_merge.
This is my code, it simply grabs each table specified in my database then makes it to a big json file.:
$tables = array("buildings", "medical", "other", "tools", "traps", "weapons");
foreach ($tables as $table) {
// Get tables from database
$sth = $db->query("SELECT * FROM $table");
$result = $sth->fetchAll();
// Merge arrays together
if ($arr === null) {
//echo "its 0 <br/> ";
$arr = array( "$table" => $result );
} else {
//echo "more than 0 <br/> ";
$arr2 = array( "$table" => $result );
$merge = array_merge($arr, $arr2);
}
} //End loop
echo $merge;
So far It's working somehow, I manage to get the first table "buildings" and the last table "weapons" to be displayed the way i want perfectly!
But I don't understand why it jumps over the other ones..
I believe it has something to do with $arr2 and that i need to specify a unique array for each of the tables. But how can i achieve this? Is this the way to go or is there a more efficient way to achieve this?
Thanks!

Its failing because of this line
$merge = array_merge($arr, $arr2);
Your merge is always a merge of $arr (which is the first entry in $tables) and $arr2, which is the latest entry being processed. You are not merging the data with the previously merged data, such as
$arr = array_merge($arr, $arr2)
Also, you can get rid of the if/else logic by just starting off by setting $arr to an empty array to start.
$arr = array();

You can put everything inside an unique array, like:
$myArray["$table"] = $result;

$tables = array("buildings", "medical", "other", "tools", "traps", "weapons");
$tableArr = array();
foreach ($tables as $table) {
// Get tables from database
$sth = $db->query("SELECT * FROM $table");
$result = $sth->fetchAll();
if(isset($result)){
$tableArr[$table] = $result;
}else{
$tableArr[$table] = '';
}
} //End loop
print_r($tableArr);
Created new array and set index as table name and store its result in that array.

If I understand correctly...
Instead of this two lines
$arr2 = array( "$table" => $result );
$merge = array_merge($arr, $arr2);
You can try this:
$tables[$table] = $result;

Your code can be greatly simplified.
$tables = array("buildings", "medical", "other", "tools", "traps", "weapons");
foreach ($tables as & $table) {
$table = $db->query("SELECT * FROM $table")->fetchAll();
}
echo json_encode($tables);
Of course, you still need to check for errors (database and JSON errors), in order for the code to be robust, but the simpler you can make something the better. Simple is good, especially when it comes to programming.

Related

Why do i get array foreach loop?

Hello can someone explain me why i'm getting an array in this code?
$loop2 = $link->query("SHOW tables FROM test");
$tables = $loop2->fetchAll(PDO::FETCH_ASSOC);
foreach($tables as $table) {
$capital = $table;
$small = $table;
when i echo $capital or $small i get (Array) why is that? i'm using foreach by the way sorry i'm a newbie
I thinks, It's a associative array, please try print_r to check the associative and then use another one foreach loop and try again.
$kmg = array('val1'=>array('1','2','3'),
'val2'=>array('4','5','6'));
foreach($kmg as $value){
print_r($value);
}
In the loop $table is an associative array which contain items (table columns names) from your selected table, like as below
$table['column_id'];
$table['column_name'];
$table['column_date'];
You can further check it columns by using print_r() php function
print_r($table);

mysql/php - merge multiple arrays from mysql output in while statement

I need to merge many arrays from a mysql DB I have. The amount of arrays can vary. I am serializing the data into the DB and unserializing it on the way out. Where I am stumped is trying to use array_merge but not sure how to get the data into it properly.
For instance I have
$sql_get_votes_data = "SELECT * FROM algo_users WHERE data LIKE '%$movie_id%'";
$result_get_votes_data = mysql_query($sql_get_votes_data);
$final_array = array();
while($row_get_votes_data = mysql_fetch_array($result_get_votes_data)) {
$final_array[] = unserialize($row_get_votes_data['data']);
}
Ultimately I need to be able to do a unique merge like this.
array_unique(array_merge($final_array1,$final_array2), SORT_REGULAR);
But since I have to place each array into a seperate variable in order to pass into array_merge I am not sure how to do that from the mysql call.
Any help would be awesome.
Why not merge every new array while you're still in your loop?
$mergedArray=array();
while($row_get_votes_data = mysql_fetch_array($result_get_votes_data)) {
$final_array = unserialize($row_get_votes_data['data']);
$mergedArray=array_merge($mergedArray,$final_array);
}
array_unique($mergedArray, SORT_REGULAR);
Or if you need to keep track of your individual arrays:
$mergedArray=array();
$i=0;
while($row_get_votes_data = mysql_fetch_array($result_get_votes_data)) {
$final_array[$i] = unserialize($row_get_votes_data['data']);
$mergedArray=array_merge($mergedArray,$final_array[$i]);
$i++
}
array_unique($mergedArray, SORT_REGULAR);
EDIT: I first understood you just wanted all arrays to be merged to a single array. The above edited answer now also removes duplicate entries as I now understand you wish.
You can e.g. use call_user_func_array for that.
<?php
$myarrs = array();
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
$myarrs[] = array(1,2,3);
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
$myarrs[] = array(4,5,6);
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
$myarrs[] = array(7,8,9);
$result = call_user_func_array( 'array_merge', $myarrs); var_dump($result);
but maybe it's more feasible to restructure the database and not to put the serialized arrays but single fields into the tables o the database can do the sorting/filtering/merging.

adding items to array during foreach on the array

I wish to run a foreach on a load of ID's.
However each of the items in the foreach is a select query and if it finds more ID's they need to be added to the array that is being run in the foreach.
E.g
$ids = array();
foreach($ids as $id)
{
SELECT id FROM table WHERE otherid = $id;
foreach ($query2->result_array() as $row)
{
array_push($array, $row['id']);
}
}
This is obviously pseudocode so no need to correct my SQL etc. I just need for the foreach to continue if it finds more ID's.
Possible?
I have tried adding an & here -> foreach($ids as &$id) as somebody else on here has suggested in a similar question. This doesn't seem to work.
foreach actually makes a copy of your array to loop though, you will need to use while.
while(list($id_key, $id) = each($ids)){
//your code
$ids[] = $row[id];
}
You should simply be able to just reference the original array ie
foreach ($query2->result_array() as $row)
{
$id[] = $row;
}
This will automatically assign an auto incremented key to the the new array element and add it to the $id array. I assume this is what you are after.
Try to iterate with a variable:
$ids = array();
$i = 0;
while ($i < count($ids)) {
$query2->query(SELECT id FROM table WHERE otherid = $ids[$i]);
foreach ($query2->result_array() as $row)
$ids []= $row['id'];
$i++;
}
For similar problems, I have always used two different arrays. Such code can run a query for every id only one time. I don't think it would be possible with only one array+foreach;
The following code is pretty simple. It keeps finding new ids until there are no new ids.
$ids = array();
$new = array();
$new = $ids;
do {
foreach($new as $n) {
$new = array();
//// HERE PUT YOUR CODE TO RUN A QUERY AND MAYBE PUSH A NEW ID TO $new \\\\
}
$ids = array_merge($ids,$new);
} while (count($new)!==0);

Adding to a multidimensional array in PHP

I have an array being returned from the database that looks like so:
$data = array(201 => array('description' => blah, 'hours' => 0),
222 => array('description' => feh, 'hours' => 0);
In the next bit of code, I'm using a foreach and checking the for the key in another table. If the next query returns data, I want to update the 'hours' value in that key's array with a new hours value:
foreach ($data as $row => $value){
$query = $db->query('SELECT * FROM t WHERE id=$row');
if ($result){
$value['hours'] = $result['hours'];
}
It's all fine except that I've tried just about every combination of declarations for the foreach loop, but I keep getting the error that the $value['hours'] is an invalid reference. I've tried declaring $value[] ... but that doesn't work either. I don't need to iterate through $value so another foreach loop isn't necessary.
Surely this is easier than my brain is perceiving it.
Here's the whole snippet:
foreach($_gspec as $key => $value){
$sql = sprintf('SELECT * FROM List WHERE specialtyID=%s', $key);
$query = $db->query($sql);
if ($query->num_rows() !== 0){
$result = $query->row_array();
$value['hours'] = $result['hours'];
}
}
You want
$data[$row]['hours'] = $result['hours']
$row would be better named as $key (that is what it is!)
Some people would suggest using pointers, but I find this way makes more sense to me.
You need to use ampersand in front of the $value in foreach to pass it by reference like this:
foreach ($data as $row => &$value){
$query = $db->query($sql);
if ($result){
$value['hours'] = $result['hours'];
}
}
More info here: http://php.net/manual/en/control-structures.foreach.php
As of PHP 5, you can easily modify
array's elements by preceding $value
with &. This will assign reference
instead of copying the value.
Use reference ->
foreach ($data as $row => & $value) {
$query = $db->query('SELECT * FROM t WHERE id=$row');
// [...]
if ($result) {
$value['hours'] = $result['hours'];
}
}

PHP Sorting associative-array by other array

I need to sort an associative-array in the exact order of the content of another array.
The Arrays are retrieve by 2 separate sql-requests (stated below). The requests could not be combined to only one request, so I have to sort the second array into the order of the first one.
These are the arrays:
#Array which contains the id's in needed order
$sorting_array = array(1,2,3,8,5,6,7,9,11,10...);
#Array which contains the values for the id's, but in order of "id" ASC
$array_to_sort = array(
array("id" => "1", "name" => "text1", "help" => "helptxt2");
array("id" => "2", "name" => "text2", "help" => "helptxt2");
);
The SQL-Queries:
SQL-Ouery for $sorting_array: (the db-field 'conf' is setup as "text", maybe this is my problem so that I have to first explode and implode the entries before I could use it for the next query.)
$result = sql_query("select conf from config where user='me'", $dbi);
$conf = sql_fetch_array($result, $dbi);
$temp = explode(',', $conf[0]);
$new = array($temp[0], $temp[1], $temp[2], $temp[3],$temp[4],
$temp[5], $temp[6], $temp[7], $temp[8], $temp[9],
$temp[10], ...);#Array has max 30 entries, so I count them down here
$sorting_array = implode(',', $new);
SQL-Ouery for $array_to_sort:
$result = sql_query("SELECT id, name, helptxt
FROM table
WHERE id IN ($sorting_array)
AND language='english'");
while ($array_to_sort[] = mysql_fetch_array ($result, MYSQL_ASSOC)) {}
array_pop($array_to_sort);#deleting the last null entry
I could access $array_to_sort as follows to see the content one by one:
(if the lines below don't match the array above, than I mixed it up. However, the lines below is what brings the content)
echo $array_to_sort[0]["id"];
echo $array_to_sort[0]["name"];
echo $array_to_sort[0]["helptxt"];
But it is sorted by "id" ASC, but I need exactly the sorting as in $sorting_array.
I tried some things with:
while(list(,$array_to_sort) = each($sorting_array)){
$i++;
echo $array_to_sort . "<br>";
}
which only brings the Id's in the correct order, but not the content. Now I'm a bit confused, as I tried so many things, but all ended up in giving me the same results.
Maybe the sql-query could be done in one step, but I didn't brought it to work.
All results to my searches just showed how to sort ASC or DESC, but not what I want.
Furthermore I must confess that I'm relative new to PHP and MySQL.
Hopefully some one of you all could bring me back on track.
Many thanks in advance.
To fetch your results:
$result = mysql_query("SELECT id, name, helptxt
FROM table
WHERE id IN ($sorting_array)
AND language='english'");
$array_to_sort = array();
while ( ($row = mysql_fetch_assoc($result)) !== false ) {
// associate the row array with its id
$array_to_sort[ $row[ "id" ] ] = $row;
}
To display them in order of $sorting_array:
foreach ( $sorting_array as $id ) {
// replace the print_r with your display code here
print_r( $array_to_sort[ $id ] );
}
And a bonus tip for the code fetching $sorting_array:
$result = mysql_query("select conf from config where user='me'", $dbi);
$conf = mysql_fetch_array($result, $dbi);
$temp = explode(',', $conf[0]);
// limit to 30 ids
$new = array();
// no need to do this manually, use a loop
for ( $i = 0; $i < 30; ++$i )
$new[] = $temp[ 0 ];
$sorting_array = implode(',', $new);
Its a little hard to tell because there is a lot going on here, in the future you'll probably get better/more responses if you ask several simple questions and figure out yourself how to make the answers fit together.
Your best bet long term is going to be to restructure your SQL tablessuch that you can combine these query together. You can do what you're asking in PHP, but it's going to be slower than doing it in MySQL and much more complicated.
To do what you're asking (pretty slow in PHP):
$sorted = array();
foreach ( $sorting_array as $id )
{
foreach ( $array_to_sort as $values )
{
if ( $values['id'] == $id )
{
$sorted[] = $values;
break;
}
}
}
what I tend to do in such a situation is first to rearrange the array with the data. so the keys represent ids
In your case:
$array_to_sort_ids = array();
foreach ($array_to_sor as $item)
{
$array_to_sort_ids[$item['id']] = $item;
}
Then sorting is as simple as:
$array_sorted = array();
foreach ($sorting_array as $id)
{
$array_sorted[] = $array_to_sort_ids[$id];
}
This solution is quite efficient, since you only have 2 foreach loops.
EDIT!!!
As I couldn't edit my question anymore, I just like to state my solution this way:
The tip to rethink my database was what brought me to some testings and then I found the solution, with the following query:
$result = sql_query("SELECT id, name, helptxt
FROM table
WHERE id IN ($sorting_array)
AND language='english'
ORDER BY FIELD(id,$sorting_array)");
while ($array_to_sort[] = mysql_fetch_array ($result, MYSQL_ASSOC)) {}
array_pop($array_to_sort);#deleting the last null entry
Just the line:
ORDER BY FIELD(id,$sorting_array)
will do the trick. It orders the results the way you want, even if this means 1,4,2,3,9,7,...
Sometimes it's so easy, when you know where to look.
Thanks again!!!

Categories