How to turn sql result to multi-dimensional array dynamically? - php

Here is the query string.
$query = "SELECT t.id, t.assignee, t.owner,
d.code, d.status, d.target_completion_date,
d.target_extension_date, d.submission_date, d.approval_date,
d.revision_start_date, d.revision_completion_date, d.message,
ty.name, f.orig_name, f.new_name,
b.payment_date, b.discount, b.total_cost, b.amount_payed, b.edit_level,
b.billing_type, b.pages, b.words
FROM tasks t
INNER JOIN details d ON t.detail_id = d.id
INNER JOIN billing b ON t.billing_id = b.id
INNER JOIN TYPE ty ON d.document_type_id = ty.id
INNER JOIN files f ON t.file_id = f.id
WHERE t.assignee = 'argie1234'";
And this is the array i would like the query result to turn into.
$user = array('allTask'=>array(array('taskid' => 1,
'assignee'=>'argie1234',
'owner'=>'austral1000',
'details' => array( 'code' => 'E',
'status'=>'TC',
'targetCompletionDateUTC'=>'1379401200',
'targetExtentionDateUTC'=>'1379401200',
'submissionDateUTC'=>'1379401200',
'approvalDateUTC'=>'1379401200',
'revisionStartDateUTC'=>'1379401200',
'revisionCompletionDateUTC'=>'1379401200',
'messageToEditor'=>'Please work on it asap.',
'documentType' => 'Thesis'),
'file' => array('orig_name' =>'originalname.docx',
'new_name' => 'newname.docx'),
'billing'=>array('paymentDate'=>'July 26,2013 12:40',
'discount' => '0',
'totalRevisionCharge' => '$20.00',
'totalAmountPayed' => '$20.00',
'revisionLevel' => '1',
'chargeType'=> '1',
'numPages' => '60',
'numWords' => '120,000' ) ),
array('taskid' => 12,
'assignee'=>'argie1234',
'owner'=>'usaroberto',
'details' => array( 'code' => 'E',
'status'=>'TC',
'targetCompletionDateUTC'=>'1379401200',
'targetExtentionDateUTC'=>'1379401200',
'submissionDateUTC'=>'1379401200',
'approvalDateUTC'=>'1379401200',
'revisionStartDateUTC'=>'1379401200',
'revisionCompletionDateUTC'=>'1379401200',
'messageToEditor'=>'Please work on it asap.',
'documentType' => 'Thesis'),
'file' => array('orig_name' => 'originalname.docx',
'new_name' => 'newname.docx'),
'billing'=>array('paymentDate'=>'July 26,2013 12:40',
'discount' => '0',
'totalRevisionCharge' => '$20.00',
'totalAmountPayed' => '$20.00',
'revisionLevel' => '1',
'chargeType'=> '1',
'numPages' => '60',
'numWords' => '120,000' ) ),
'account' => array( 'username' => 'marooon55',
'emailadd' => 'marooon#yahoo.com',
'firstname' => 'Maroon',
'initial' => 'E',
'lastname' => 'Young',
'country' => 'Australia',
'gender' => 'M',
'password' =>'360e2801190744a2af74ef6cbfdb963078b59709',
'activationDate' => '2013-09-13 14:30:34') );
How can i create the above array? I sure know how to define multi dimensional array, regretfully though i am having difficulty creating this complex array dynamically. As a beginner i don't even know where to begin.

Here is an example that might help you out. Try starting with simple multi dimensional arrays, once you get a hold of it, you can move onto building complex ones. You will then find that the array you want to build is not really difficult than you initially thought it to be.
$mycomplexarray = array('key1' => array('val1', 'val2'),
'key2' => array('val3', 'val4' => array('val5', 'val6')
)
);

You could create the array just as you have here. I'm not gonna write the whole thing out, but something like this...
$result = $mysqli->query($query); // however you query the db is up to you.
$row = $result->fetch_assoc(); //same as query use your prefered method to fetch
$user = array('allTask'=>array(array('taskid' => $row['id'],
'assignee'=>$row['assignee'],
'owner'=>$row['owner'],
'details' => array( 'code' => $row['code'],
'status'=>$row['status'],
...etc, Hope this makes sense for you.

Set up a structure array first that defines which columns will be stored in a sub array like
$struc=array('Id'->0, 'assignee'->0, 'owner'->0,
'code'->'detail', 'status'->'detail', 'target_completion_date'->'detail',
'target_extension_date'->'detail', 'submission_date'->'detail', 'approval_date'->'detail',
'revision_start_date'->'detail', 'revision_completion_date'->'detail', 'message'->'detail',
'name'->'file', 'orig_name'->'file', 'new_name'->'file',
'payment_date'->'billing', 'discount'->'billing', 'total_cost'->'billing', 'amount_payed'->'billing', 'edit_level'->'billing', 'billing_type'->'billing', 'words');
In your while ($a=mysqli_fetch_assoc($res)) loop you can now use this structure to decide whether you want to store an element directly in your target array or whether you want to place it in the subarray named in this structure array. Like
$res=mysqli_query($con,$sql);
$arr=array();
while($a=mysqli_fetch_assoc($res)) {
// within result loop: $a is result from mysqli_fetch_assoc()
$ta=array(); // temp array ...
foreach ($a as $k => $v){
if ($struc[$k]) $ta[struc[$k]][$k]=$v;
else $ta[$k]=$v;
}
$arr[]=$ta; // add to target array
}
This is the complete code, no more is needed. It was typed up on my iPod, so it is NOT tested yet.
The generated array should be equivalent to your $user['allTask'] array.

Related

Merge arrays by suffix of keys PHP

I have two arrays, that I want to merge as one according to keys suffix.
$keys = array(
'staff_first_name' => NULL,
'staff_last_name' => NULL,
'staff_years' => NULL
);
$submitted_values = array(
'first_name' => 'jon',
'last_name' => 'doe',
'years' => 5
);
I understand I could use a function like shown here and modify it.
But is there a native php function that will accomplish this. I attempted to use array_merge_recursive but after reviewing the documentation It will not do what I need it to.
$wanted_array = array(
'staff_first_name' => 'jon',
'staff_last_name' => 'doe',
'staff_years' => 5
);
If you know the two arrays are the same size, and in the same order, you can use array_combine with array_keys.
$wanted_array = array_combine(array_keys($keys), $submitted_values);
Because it's a suffix that is the same on each key we don't need to worry about it.
If we ksort the arrays they should both be sorted the same because the suffix is the same on all in key array.
$keys = array(
'staff_first_name' => NULL,
'staff_last_name' => NULL,
'staff_years' => NULL
);
$values = array(
'years' => 5,
'first_name' => 'jon',
'last_name' => 'doe',
);
ksort($values);
ksort($keys);
Var_dump(array_combine(array_keys($keys), $values));
I intentionally placed years first to show that it works.
https://3v4l.org/cBNhk
If you need to reduce the $_POST to only these array items to be able to combine them you can use a combination of preg_grep, array_flip, array_values and array_intersect_key to filter out the wanted items from the array.
$val = preg_grep("/first_name|last_name|years/",array_values(array_flip($values)));
$values = Array_intersect_key($values, array_flip($val));
ksort($values);
ksort($keys);
Var_dump(array_combine(array_keys($keys), $values));
I added some extra items to simulate a larger mixed $_POST array.
https://3v4l.org/a3ju1
This is one of those questions where I must implore the OP to rethink their process. It only complicates your code to introduce associative keys that do not instantly synchronize with your form field names. This is the best advice that I can give you: declare a whitelist of keys and assign default values to each, then filter, then replace.
Since your values are all null, your code can be made more DRY by calling array_fill_keys().
The following can be written as one line of code, but to show each step, I've printed the arrays to screen after each function call.
Code: (Demo)
$defaults = array_fill_keys(['first_name', 'last_name', 'years'], null);
var_export($defaults);
$_GET = [
'last_name' => 'doe',
'Hackers' => 'can be naughty',
'years' => 5
];
var_export($_GET);
$screened = array_intersect_key($_GET, $defaults);
var_export($screened);
$replaced = array_replace($defaults, $screened);
var_export($replaced);
Output:
array (
'first_name' => NULL,
'last_name' => NULL,
'years' => NULL,
)array (
'last_name' => 'doe',
'Hackers' => 'can be naughty',
'years' => 5,
)array (
'last_name' => 'doe',
'years' => 5,
)array (
'first_name' => NULL,
'last_name' => 'doe',
'years' => 5,
)
...p.s. makes sure that you use prepared statements with placeholders if you are sending any of the values to the database.

make multilevel array from mysql php

i have this array in an example, how can i get the same result from query from database?, i need to replace the values which the values of the database.
$data = array(
array(
'qty' => 1,
'Price' => 1.00,
'total' => 1.00
),
array(
'qty' => 2,
'Price' => 1.00,
'total' => 2.00
),
array(
'qty' => 3,
'Price' => 1.00,
'total' => 3.00
)
);
then in the example use the nusoap lib
foreach($data as $concept) {
$par['Concepts'][] = new soapval('Concept', 'Concept', $concept);
}
so i need to call the query:
$query_data_cot = mysql_query("SELECT * FROM data WHERE id='1'");
while($data_quote=mysql_fetch_array($query_data_cot)){
$conceptosDatos[]["qty"]=$data_quote['qty'];
$conceptosDatos[]["Price"]=$data_quote['price'];
$conceptosDatos[]["total"]=$data_quote['total'];
}
but when i do these i got an error
Error: Array ( [faultcode] => soap:Server [faultstring] => Server was unable to process request. --->
thank you
Everytime you use $conceptosDatos[]... the [] will create a new subarray. So your result will be something like this
array(
array('qty' => ..),
array('Price' => ..),
array('total' => ...),
array('qty' => ..),
array('Price' => ..),
array('total' => ...),
...
)
Instead you need to create a new subarray only for a whole set, so use something like this
$query_data_cot = mysql_query("SELECT qty, price, total FROM data WHERE id='1'");
while($data_quote=mysql_fetch_assoc($query_data_cot)){
$conceptosDatos[] = $data_quote;
}
Of course you could also do it like this
$query_data_cot = mysql_query("SELECT qty, price, total FROM data WHERE id='1'");
while($data_quote=mysql_fetch_assoc($query_data_cot)){
$conceptosDatos[] = array(
'qty' => $data_quote['qty'],
'Price' => $data_quote['price'],
'total' => $data_quote['total'],
);
}
But why write every field if you're going to copy the whole array anyway?
If you need to use different names (as in your example price and Price), you can either change your db schema or use aliases in your query, giving you this code:
$query_data_cot = mysql_query("SELECT qty, price AS Price, total FROM data WHERE id='1'");
while($data_quote=mysql_fetch_assoc($query_data_cot)){
$conceptosDatos[] = $data_quote;
}
This has the advantage that if you wish to modify your code in the future, you'd only need to modify the query (and could probably encapsulate this logic inside a function) - so less work for future you.
By the way, did you see the big red box in the manual on all mysql_* methods's sites? It's deprecated and PDO as well as MySQLi are way better alternatives. This helps decide what to use.
Try this , while($data_quote=mysql_fetch_array($query_data_cot , MYSQL_ASSOC )) , as you are retrieving the $data as an associative array .
Each assignment line in your loop is creating a new element of the $conceptDatos array, not filling in a different element of the same element. So your array looks like:
array(
array('qty' => 1),
array('Price' => 1.0),
array('total' => 1.0),
array('qty' => 2),
array('Price' => 1.0),
array('total' => 1.0),
...
)
Your loop shoud be:
while($data_quote=mysql_fetch_array($query_data_cot)){
$conceptDatos[] = array(
'qty' => $data_quote['qty'],
'Price' => $data_quote['price'],
'total' => $data_quote['total']
);
}

how to sort and limit inside document mongodb in php

i have the array here.
http://pastebin.com/i5ZUQNm6
and this from php result.
$result1 = $mo->find(
array(
'username' => 'BLABLA',
'stream' => array('$exists' => true)
)
);
foreach ($result1 as $obj) {
print_r($obj);
}
how i sort the [stream] child and limit it to 1 result? and how to find [id_stream] child?
thanks
To limit, to a single document
use limit(1):
$result1 = $mo->find( array(
'username' => 'BLABLA',
'stream' => array('$exists' => true) ) )->limit(1);
or
findOne
$result1 = $mo->findOne( array(
'username' => 'BLABLA',
'stream' => array('$exists' => true) ) );
And to sort the child.
You need to also add at the end ->sort(array("stream.time" => -1));
I've seen the pastebin, and I guess you want to order by date.
Final code:
$result1 = $mo->findOne( array(
'username' => 'BLABLA',
'stream' => array('$exists' => true)))->sort(array("stream.time" => -1));;
From what I know for limiting to a single value of the array you need a loop
you need to add (inside the find, just after the main array): find(.... , array('streams' => array('$slice' => 1)));
Using a combination of sort and limit should work - the code in slownage's answer looks like it may be what you need.

Group results after join?

So, I have three tables. Movies, movies_genres and genres. I want to get a movie by its Id, and also join its genres in the result. I managed to join the results, but it doesn't display as i want it to. I'm not sure if what I'm asking is possible.
This is my query:
SELECT `movies`.*, GROUP_CONCAT(genres.id) AS genre_id, GROUP_CONCAT(genres.name) AS genre_name
FROM (`movies`)
INNER JOIN `movies_genres`
ON `movies_genres`.`movie_id` = `movies`.`id`
INNER JOIN `genres`
ON `genres`.`id` = `movies_genres`.`genre_id` WHERE `movies`.`id` = 19908
GROUP BY `movies`.`id`
The query was generated by Codeigniters Active Record class, here is the Codeigniter code if that helps:
$this->db->select('movies.*, GROUP_CONCAT(genres.id) AS genre_id, GROUP_CONCAT(genres.name) AS genre_name');
$this->db->from('movies');
$this->db->where('movies.id', $movie_id);
$this->db->join('movies_genres', 'movies_genres.movie_id = movies.id', 'inner');
$this->db->join('genres', 'genres.id = movies_genres.genre_id', 'inner');
$this->db->group_by('movies.id');
Here is the result i'm currently getting:
Array
(
[id] => 19908
[movie_title] => Zombieland
[overview] => An easily spooked guy...
[genre_id] => 28,12,35,27
[genre_name] => Action,Adventure,Comedy,Horror
)
And this is what I want:
Array
(
[id] => 19908
[movie_title] => Zombieland
[overview] => An easily spooked guy...
[genres] => array(
0 => array(
'id' => 28,
'name' => Action
),
1 => array(
'id' => 12,
'name' => Adventure
),
1 => array(
'id' => 35,
'name' => Comedy
),
1 => array(
'id' => 27,
'name' => Horror
)
)
)
Is this possible, and if so, how?
The query you listed will have n rows (where n = # of movies) whereas the query it seems you want will have many more rows (# of movie_genre's entries). You're probably better off leaving that query as it is, and doing some post processing.
Consider:
After you get it, just run your result (e.g. $result) array through something like:
foreach($result as &$row)
{
// Split over commas
$gi_elements = explode(',', $row['genre_id']);
$gn_elements = explode(',', $row['genre_name']);
// Build genre
$row['genre'] = array();
for($i=0; $i<count($gi_elements); $i++)
{
$row['genre'][] = array('id' => $gi_elements[$i], 'name' => $gn_elements[$i]);
}
// Cleanup
unset($row['genre_id']);
unset($row['genre_name']);
}
Afterwards, $results will look exactly as you wish without extra database work.
EDIT: Fixed some typos.

jQuery order json list from php?

i am sending an ordered json_encode list of some MySQL tables, from php, but when i retrieve it with jquery it is not in order any more? everything works fine and in order on the php side. it's the client side that i'm having trouble with. i think the problem is that i'm sending a multidimensional array from php as json. what would be the most efficient solution? also why has the order changed when retrieved by jQuery.
PHP CODE:
$user_data = array();
while($row = mysql_fetch_array($retval, MYSQL_ASSOC){
$user_id = $row['user_id'];
if(!isset($user_data[$user_id]){
$user_data[$user_id] = array(
'first_name' => $row['first_name'],
'last_name' => $row['last_name'],
'dept' => $row['dept'],
'quals' => array()
);
}
$quals = array(
'qual_cat' => $row['qual_cat'],
'qual' => $row['qual'],
'count' => $row['count']
)
$user_data[$user_id]['quals'][] = $quals;
}
echo json_encode($user_data);
jQuery:
$.post('page.php', function(post){
$.each(post, function(i,data){
alert(data.first_name+' '+data.last_name+' - '+data.dept);
});
});
PHP VAR_DUMP:
array
10 =>
array
'first_name' => string 'David' (length=5)
'last_name' => string 'Dan' (length=3)
'dept' => string 'web' (length=3)
'count' => string '5' (length=1)
'quals' =>
array
0 =>
array
...
1 =>
array
...
2 =>
array
...
3 =>
array
...
4 =>
array
...
In php, array is by default associative, so that's why you have this behavior as associative array order is not guaranteed (as per explanation in the link given by benedict_w).
To overcome this, you could try the following:
echo json_encode(array_values($user_data));
This will effectively turn your json from
["10":{prop1:val1, prop2:val2}, "25":{prop1:val1, prop2:val2}]
into
[{prop1:val1, prop2:val2}, {prop1:val1, prop2:val2}]
If you need to keep track of the id, put it inside your user_data in your php:
if(!isset($user_data[$user_id]){
$user_data[$user_id] = array(
'id' => $user_id,
'first_name' => $row['first_name'],
'last_name' => $row['last_name'],
'dept' => $row['dept'],
'quals' => array()
);
}

Categories