Creating a multidimensional array using an array and loop through mysql table - php

I have a table with the following structure. There are currently 9 students enrolled in 3 classes (classes 01, 16 and 52), with 3 enrollments in each class.
studentcode | classcode
-------------------------
D3kcIvyp | 01
DdIhBc | 01
2vx0KV | 01
9p1PxWCV | 52
RnmfH1WE | 52
MSTBEv | 52
Yp4J3o | 16
fWQ5Oo | 16
6sxw3u | 16
This is the array with all current classes:
$classes_array = array ( [0] => 01 [1] => 52 [2] => 16 )
Using this array I would like to go through the mysql table and create a multidimensional array with the classcodes used as first level keys:
Array
(
[01] => Array
(
[0] => D3kcIvyp
[1] => DdIhBc
[2] => 2vx0KV
)
[52] => Array
(
[0] => 9p1PxWCV
[1] => RnmfH1WE
[2] => MSTBEv
)
[16] => Array
(
[0] => Yp4J3o
[1] => fWQ5Oo
[2] => 6sxw3u
)
)
foreach ($classes_array as $key => $value)
{
$sql = "SELECT studentcode FROM table WHERE classcode = '$classes_array[$key]'";
$result = mysql_query($sql) or die();
while($data = mysql_fetch_array($result))
{
$studentcodes_array[] = $data['studentcode'];
}
foreach ($studentcodes_array as $studentcodeskey => $studentcodesvalue)
{
$multid_array[$value][] = $studentcodesvalue;
}
}
Using the code above, unfortunately I don't get the array I would like to get. I get this instead:
Array
(
[01] => Array
(
[0] => D3kcIvyp
[1] => DdIhBc
[2] => 2vx0KV
)
[52] => Array
(
[0] => D3kcIvyp
[1] => DdIhBc
[2] => 2vx0KV
[3] => 9p1PxWCV
[4] => RnmfH1WE
[5] => MSTBEv
)
[16] => Array
(
[0] => D3kcIvyp
[1] => DdIhBc
[2] => 2vx0KV
[3] => 9p1PxWCV
[4] => RnmfH1WE
[5] => MSTBEv
[6] => Yp4J3o
[7] => fWQ5Oo
[8] => 6sxw3u
)
)
What is wrong with my code? Can anybody help me with this?

You never initialise $studentcodes_array so it is remembering all the values from your previous loops.
Try adding $studentcodes_array = array(); before your while.

Related

How to insert 100 records in mysql procedure and loop in MySQL procedure not in PHP?

I have a record of 100 or 200 questions when user submit the test all 100 or 200 questions from caches need to save to MySQL. Right now I have to loop in PHP and every time a single query has executed, any idea how I send an array in MySQL procedure and the loop of 100 or 200 should be done in MySQL procedure. I can convert the array to JSON as JSON is supported in MySQL.
array which needs to be insert looks like this
Array
(
[0] => Array
(
[0] => 19287
[1] => 1
[2] => 1
[3] => 101
[4] => 224
[5] => 0
)
[1] => Array
(
[0] => 19285
[1] => 0
[2] => 1
[3] => 101
[4] => 2
[5] => 0
)
[2] => Array
(
[0] => 19289
[1] => 1
[2] => 1
[3] => 72
[4] => 23
[5] => 0
)
[3] => Array
(
[0] => 19290
[1] =>
[2] => 1
[3] => 106
[4] => 3
[5] => 0
)
[4] => Array
(
[0] => 19291
[1] => 0
[2] => 1
[3] => 230
[4] => 76
[5] => 0
)
)
You can build a multi-row INSERT in your PHP code. Assuming your data is in $arr:
$sql = "INSERT INTO yourtable (...column list...) VALUES ";
$vsets = array();
foreach ($arr as $values) {
$vsets[] = str_replace(array(',,', ',,'), ',NULL,', "(" . implode(',', $values) . ")");
}
$sql .= implode(',', $vsets);
echo $sql;
Output:
INSERT INTO yourtable (...column list...)
VALUES (19287,1,1,101,224,0),(19285,0,1,101,2,0),
(19289,1,1,72,23,0),(19290,NULL,1,106,3,0),
(19291,0,1,230,76,0)
Make sure you filter, validate or cast your data, to prevent any non-integers (or any SQL) from being injected into your queries.

Pad missing dates in array with value previous day

I have an array generated from a database showing continuous date ranges for products in stock.
The problem I'm having is that when there are missing dates the date range gets broken in 2 parts as shown in a segment of the array below where there are no records for dec 31.
I can tell it is a missing date because the elements [0],[1],[2] in the row before the missing date are equal to the elements [0],[1],[2] in the row after the missing date. Element[3] is the number of days in the [4], [5] date range.
[20] => Array ( [0] => 745637 [1] => 24759 [2] => 6.00 [3] => 23 [4] => 2016-12-08 [5] => 2016-12-30 )
[21] => Array ( [0] => 745637 [1] => 24759 [2] => 6.00 [3] => 2 [4] => 2017-01-01 [5] => 2017-01-02 )
[22] => Array ( [0] => 745637 [1] => 26400 [2] => 5.70 [3] => 23 [4] => 2016-12-08 [5] => 2016-12-30 )
[23] => Array ( [0] => 745637 [1] => 26400 [2] => 5.70 [3] => 2 [4] => 2017-01-01 [5] => 2017-01-02 )
[24] => Array ( [0] => 745637 [1] => 29882 [2] => 7.00 [3] => 23 [4] => 2016-12-08 [5] => 2016-12-30 )
[25] => Array ( [0] => 745637 [1] => 29882 [2] => 7.00 [3] => 2 [4] => 2017-01-01 [5] => 2017-01-02 )
So what I would like to do is merge these rows IF there is only a 1 day gap AND elements [0],[1],[2] in the row before the missing date are equal to the elements [0],[1],[2] after the missing date.
[20] => Array ( [0] => 745637 [1] => 24759 [2] => 6.00 [3] => 23 [4] => 2016-12-08 [5] => 2016-12-30 )
[21] => Array ( [0] => 745637 [1] => 24759 [2] => 6.00 [3] => 2 [4] => 2017-01-01 [5] => 2017-01-02 )
would become:
[20] => Array ( [0] => 745637 [1] => 24759 [2] => 6.00 [3] => 26 [4] => 2016-12-08 [5] => 2017-01-02 )
UPDATE:
This is what I came up with, and it actually works but I'm wondering if there is a cleaner way of doing this
foreach ($data as $rows) {
$current = $rows[0].$rows[1].$rows[2];
$cur_days = $rows[3];
$cur_begin = $rows[4];
$cur_end = $rows[5];
// check if we have a 1-day gap in the date range
$comp_date = date_add(date_create($prev_end), date_interval_create_from_date_string('2 days'));
$comp_date = date_format($comp_date, 'Y-m-d');
if (($current == $previous) && ($comp_date == $cur_begin)) {
$data[$i-1][5] = $cur_end; // update [5] 'end date range'
// calculate new range in days
$date_prev_begin = date_create("$prev_begin");
$date_cur_end = date_create("$cur_end");
$interval = date_diff($date_prev_begin, $date_cur_end);
$new_days=$interval->format('%a');
$data[$i-1][3] = $new_days+1; // update [3] 'days'
unset($data[$i]); // remove row
}
// store current row to use for comparison in next iteration
$previous = $current;
$prev_days = $cur_days;
$prev_begin = $cur_begin;
$prev_end = $cur_end;
$i++;
}
$data=array_values($data); // rearrange array
Not sure if it is more efficient but it contains a few less lines of code:
$new_data = array();
foreach($data as $row) {
$cur_begin = new DateTime($row[4]);
$new_row = $row;
$days = 0;
$last_index = !empty($new_data) ? count($new_data)-1 : -1;
$prev_row = $last_index >= 0 ? $new_data[$last_index] : null;
if(!empty($prev_row)) {
$prev_end = new DateTime($prev_row[5]);
$interval = $prev_end->diff($cur_begin);
$days = $interval->days;
$isdiff = $row[0].$row[1].$row[2] != $prev_row[0].$prev_row[1].$prev_row[2];
}
if(!empty($prev_row) && $days > 0 && !$isdiff) {
$new_data[$last_index][3] += $days+1;
$new_data[$last_index][5] = $row[5];
} else {
$new_data[] = $row;
}
}
var_dump($new_data);
Hope it helps.

Getting data from an object array

I have an array
Array (
[bla123] => Array
(
[0] => 2
[1] => 3
[2] => 2
[3] => 2
[4] => 2
[5] => 2
[6] => 2
[7] => 2
[8] => 2
)
[12xye] => Array
(
[0] => 4
[1] => 3
[2] => 3
[3] => 2
[4] => 2
[5] => 4
[6] => 2
[7] => 2
[8] => 2
)
)
How can i access this array in php and also get the number of 1,2,3.. etc from it in php.
The logic is to get the rating of a products. the data is fetched from the database completely and then sorted using php.
for eg:
product1
one star:1
two star:3
three star:2
etc...
somewhat like a star system in flipkart, amazons etc..
use the below code:
<?php
$mainArrDat = array('bla123'=>array('Your_Array_Data_Here'),'12xye'=>('Your_Array_Data_Here'));
foreach( $mainArrDat as $mainArr )
{
foreach($mainArr as $nowArr)
{
//you can access the data that you require from $nowArr
}
}
?>

php multidimensional array path segment combination loop

I am trying to figure a way to get this to work. But I have a hard time thinking out the logics.
I have this array:
Array
(
[0] => Array
(
[0] => news
[1] => {section}
[2] => {slug}
[3] => {*}
)
[1] => Array
(
[0] => {id}
[1] => {*}
)
[2] => Array
(
[0] => {date}
[1] => 25-07-1982
[2] => {section}
[3] => {slug}
[4] => {*}
)
)
That I need to convert to this result:
0 news/{id}/{date}
1 news/{id}/25-07-1982
2 news/{id}/{section}
3 news/{id}/{slug}
4 news/{id}/{*}
5 news/{*}/{date}
6 news/{*}/25-07-1982
7 news/{*}/{section}
8 news/{*}/{slug}
9 news/{*}/{*}
10 {section}/{id}/{date}
11 {section}/{id}/25-07-1982
12 {section}/{id}/{section}
13 {section}/{id}/{slug}
14 {section}/{id}/{*}
15 {section}/{*}/{date}
16 {section}/{*}/25-07-1982
17 {section}/{*}/{section}
18 {section}/{*}/{slug}
19 {section}/{*}/{*}
20 {slug}/{id}/{date}
21 {slug}/{id}/25-07-1982
22 {slug}/{id}/{section}
23 {slug}/{id}/{slug}
24 {slug}/{id}/{*}
25 {slug}/{*}/{date}
26 {slug}/{*}/25-07-1982
27 {slug}/{*}/{section}
28 {slug}/{*}/{slug}
29 {slug}/{*}/{*}
30 {*}/{id}/{date}
31 {*}/{id}/25-07-1982
32 {*}/{id}/{section}
33 {*}/{id}/{slug}
34 {*}/{id}/{*}
35 {*}/{*}/{date}
36 {*}/{*}/25-07-1982
37 {*}/{*}/{section}
38 {*}/{*}/{slug}
39 {*}/{*}/{*}
The input array could contain more than three keys, so the solution I'm looking for should be dynamic. And the result should have the same order as the result shown above.
Does someone know how to do this in a efficient way? Can someone give me a push in the right direction? Thanks a lot! :)
Sth like this
foreach ($array[0] as $val0 )
foreach ($array[1] as $val1 )
foreach ($array[2] as $val2 )
$newArray[] = "$val0/$val1/$val2";
EDIT: for variable array length
function recursive($array , $length = 0){
$retval =array();
if($length < count($array) -1){
foreach ($array[$length] as $val0 )
foreach (recursive($array, $length+1) as $val1)
$retval[] = "$val0/$val1";
}
else
{
foreach ($array[$length] as $val0 )
$retval[] = "$val0";
}
return $retval;
}
print_r(recursive($array));
Just because I like writing functions that mis/manage PHP arrays, I put this together, mainly because I was pretty sure you could avoid recursion — because the structure itself isn't recursive. (My head seems to think that is a rule, I'm sure someone somewhere can prove it wrong).
foreach ( array_reverse($array) as $sub ) {
if ( isset($rem) ) {
$ret = array();
foreach ( $sub as $itm ) {
foreach ( $rem as $val ) { $ret[] = "$itm/$val"; }
}
$rem = $ret;
}
else {
$rem = $sub;
}
}
The output found in $rem is as follows:
Array (
[0] => news/{id}/{date}
[1] => news/{id}/25-07-1982
[2] => news/{id}/{section}
[3] => news/{id}/{slug}
[4] => news/{id}/{*}
[5] => news/{*}/{date}
[6] => news/{*}/25-07-1982
[7] => news/{*}/{section}
[8] => news/{*}/{slug}
[9] => news/{*}/{*}
[10] => {section}/{id}/{date}
[11] => {section}/{id}/25-07-1982
[12] => {section}/{id}/{section}
[13] => {section}/{id}/{slug}
[14] => {section}/{id}/{*}
[15] => {section}/{*}/{date}
[16] => {section}/{*}/25-07-1982
[17] => {section}/{*}/{section}
[18] => {section}/{*}/{slug}
[19] => {section}/{*}/{*}
[20] => {slug}/{id}/{date}
[21] => {slug}/{id}/25-07-1982
[22] => {slug}/{id}/{section}
[23] => {slug}/{id}/{slug}
[24] => {slug}/{id}/{*}
[25] => {slug}/{*}/{date}
[26] => {slug}/{*}/25-07-1982
[27] => {slug}/{*}/{section}
[28] => {slug}/{*}/{slug}
[29] => {slug}/{*}/{*}
[30] => {*}/{id}/{date}
[31] => {*}/{id}/25-07-1982
[32] => {*}/{id}/{section}
[33] => {*}/{id}/{slug}
[34] => {*}/{id}/{*}
[35] => {*}/{*}/{date}
[36] => {*}/{*}/25-07-1982
[37] => {*}/{*}/{section}
[38] => {*}/{*}/{slug}
[39] => {*}/{*}/{*}
)
Also, for those that like their arrays multidimensional, this might come in handy (although I'd hate to think what the overheads are for such a code golfed version). Just to be clear, this second example doesn't create the string list as requested by the OP, but a hierarchical array structure instead.
foreach ( array_reverse($array) as $sub ) {
$rem = isset($rem)
? array_combine($sub, array_fill(0, count($sub), $rem))
: $sub
;
}
This generates (again in $rem):
Array (
[news] => Array (
[{id}] => Array (
[0] => {date}
[1] => 25-07-1982
[2] => {section}
[3] => {slug}
[4] => {*}
)
[{*}] => Array (
[0] => {date}
[1] => 25-07-1982
[2] => {section}
[3] => {slug}
[4] => {*}
)
)
[{section}] => Array (
[{id}] => Array (
[0] => {date}
[1] => 25-07-1982
[2] => {section}
[3] => {slug}
[4] => {*}
)
... and so on
Now if only PHP had a join_recursive that included keys.
(it would be almost pointless, save for helping with the above).

PHP Remove subarray from main array if specific value range is found

Lets say I have the following array:
[9] => Array
(
[0] => Bob Smith
[1] => bobsmith#gmail.com
[2] => Helsinki
[3] => 10
[4] => 34
[5] => 2014-05-12
)
[10] => Array
(
[0] => John Smith
[1] => johnsmith#domain.com
[2] => some values
[3] => 9
[4] => 67
[5] => 2014-05-15
)
[11] => Array
(
[0] => Clarke Kent
[1] => ckent#superman.com
[2] => Crystal
[3] => 9
[4] => 89
[5] => 2014-05-16
)
What if i want to remove a subarray when the date falls outside a specific range. So if i say wanted to find data where the date is between 2014-05-14 and 2014-05-28. Then the (new) array would print the following:
[10] => Array
(
[0] => John Smith
[1] => johnsmith#domain.com
[2] => some values
[3] => 9
[4] => 67
[5] => 2014-05-15
)
[11] => Array
(
[0] => Clarke Kent
[1] => ckent#superman.com
[2] => Crystal
[3] => 9
[4] => 89
[5] => 2014-05-16
)
I thought something like the following:
foreach ($array as $row) {
if($row[5] >= '2014-05-14' && $row[5] <= '2014-05-14') {
// Do Something // e.g. unset subarray?
}
}
OR should i approach it differently and iterate through the array and if a subarray matches my criteria create a new array. The result being an array with subarrays that contain dates that meet my date range. I hope this makes sense, i am trying to find the most efficient way to do this.
Thanks
For the use case described, I would personally use array_filter:
$start_date = DateTime::createFromFormat('Y-m-d', '2014-05-14');
$end_date = DateTime::createFromFormat('Y-m-d', '2014-06-14');
$filtered_array = array_filter($array, function($row) use ($start_date, $end_date) {
$date = DateTime::createFromFormat('Y-m-d', $row[5]);
return $date >= $start_date && $date <= $end_date;
});

Categories