How to group models array in yii2 - php

Hi everyone i have a page on which i am displaying data using foreach loop from models. I wants to know that how can i group those classes and display accordingly.
For example I have registration forms on the page which has dates and classes.
So i want to group them by dates first and than classes.My registration models has fields like below.
Registration
id
event_id
dates
class_id
user_id
title
description
Now on this view file i am passing array of $modelRegistration so i dont actually have simple multi dimensional array so i cant use that logic to group that and display.Here is my view code to display the forms
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Date</th>
<th>Class</th>
<th>User Name</th>
<th>Title</th>
<th>Description</th>
</tr>
</thead>
<tbody class="container-items">
<?php foreach ($modelsRegistration as $indexRegistration => $modelRegistration): ?>
<tr value="<?= $modelRegistration->date ?>" class="house-item">
<td class="col-lg-1 col-md-1 col-sm-1 col-xs-1"><?= $modelRegistration->class->name ?></td>
<td class="col-lg-2 col-md-2 col-sm-2 col-xs-2">
<label><?= $modelRegistration->user->name ?></label>
<td class="col-lg-2 col-md-2 col-sm-2 col-xs-2"><?= $modelRegistration->title ?> </td>
<td class="col-lg-1 col-md-1 col-sm-1 col-xs-1"><?= $modelClass->description ?> </td>
</tr>
<?php endforeach; ?>
</tbody>
I want to get array like below
Registration
(
[0] => 10/12/2015
(
[0] => class-1(
[0] => array(
[title] => "Title 1"
[id] => 5
[username] => John
[Description] => Team Leader
)
[1] => array(
[title] => "Title 2"
[id] => 6
[username] => John 1
[Description] => Team 2
)
)
[1] => class-2(
[0] => array(
[title] => "Title 4"
[id] => 7
[username] => John 4
[Description] => Team 4
)
[1] => array(
[title] => "Title 5"
[id] => 9
[username] => John 5
[Description] => Team 6
)
)
[2] => class-3(
[0] => array(
[title] => "Title 1"
[id] => 5
[username] => John
[Description] => Team Leader
)
[1] => array(
[title] => "Title 2"
[id] => 6
[username] => John 1
[Description] => Team 2
)
)
)
[0] => 12/12/2015
(
[0] => class-1(
[0] => array(
[title] => "Title 8"
[id] => 12
[username] => John 10
[Description] => Team 77
)
[1] => array(
[title] => "Title 27"
[id] => 67
[username] => John 17
[Description] => Team 27
)
)
[1] => class-3(
[0] => array(
[title] => "Title 41"
[id] => 71
[username] => John 41
[Description] => Team 41
)
[1] => array(
[title] => "Title 51"
[id] => 59
[username] => John 54
[Description] => Team 64
)
)
)
If i can group it by dates first and than classes than i want to display the date only once and than under that date all the grouped classes and under classes i can display other information.Thank you

Map Your Model Data using date group Array helper Map Group in yii2
$model = Registration::findAll();
$registrationModels = ArrayHelper::map($model , 'event_id' ,'class_id' ,'dates');

Suppose that your model name is Registration and view name is vrego.
In your controller
// select all and order by date and class_name
$registrations= Registration::find()
->orderBy('date, class_name')
->all();
return $this->render('vrego', [
'registrations' => $registrations,
]);
Then in your view loop through $registrations and display each record.

i am geting the result i tried my self :
you need to create a class of Registration and i think you created that one then use this below query you will get that info .
$events = Registration::find()->all();
foreach($events as $event){
$new_array[$event->dates_date][][$event->class_id][]=$event;
}
<pre>
after print_r($new_array);
<pre>

Related

show difference between of two price list

I have history list of product price(order by created_at) like this:
Array
(
[0] => stdClass Object
(
[id] => 1
[product_id] => 49
[price] => 14520000.0000
[created_at] => 1592501154
)
[1] => stdClass Object
(
[id] => 2
[product_id] => 49
[price] => 14000000.0000
[created_at] => 1592587554
)
[2] => stdClass Object
(
[id] => 4
[product_id] => 49
[price] => 14800000.0000
[created_at] => 1592673954
)
[3] => stdClass Object
(
[id] => 5
[product_id] => 49
[price] => 10000000.0000
[created_at] => 1592760354
)
[4] => stdClass Object
(
[id] => 6
[product_id] => 49
[price] => 14000000.0000
[created_at] => 1592846754
)
[5] => stdClass Object
(
[id] => 7
[product_id] => 49
[price] => 14000000.0000
[created_at] => 1592933154
)
[6] => stdClass Object
(
[id] => 8
[product_id] => 49
[price] => 14000000.0000
[created_at] => 1593019554
)
)
Now for show data in table I listed price using foreach method like this:
<?php foreach($product_prices_list as $product_price_list):?>
<tr>
<td><?= esc($product_price_list->created_at);?></td>
<td class="text-center"><?= esc(number_format($product_price_list->price));?></td>
<td class="text-center"></td> //show difference between of two price
</tr>
<?php endforeach;?>
I can see true output in table but I need to show difference between of two price in the third column like this picture:
how do can i show difference between of two price in my list?!
You just need to compare the current price property to the price from the previous object in the array?
Something like this should work:
<?php foreach($product_prices_list as $key => $product_price_list):?>
<tr>
<td><?= esc($product_price_list->created_at);?></td>
<td class="text-center"><?= esc(number_format($product_price_list->price));?></td>
<td class="text-center"><?= (!empty($product_prices_list[$key - 1])) ? $product_prices_list[$key + 1]->price - $product_price_list->price: 0; ?></td> //show difference between of two price
</tr>
<?php endforeach;?>
If you are running MySQL 8.0, you can compute this information directly in the database using window functions:
select
t.*,
price
- lag(price, 1, price) over(partition by product_id order by created_at)
as price_diff
from mytable t
This adds one more column to your resultset, that contains the difference between the current price and the previous price of the same product.

Reconstruct PHP array to fit data into html table correctly

I'm trying to display data that shows the count for each month for locations in Jan-December.
I wrote the query to get the necessary data from the server but when I display it in the view in my table the layout for the data, doesn't look the way I want it to look like in my table. I believe I have to reconstruct the array that I wrote in the query for the right format first and then I can display it in my table?
Right now, the data that comes back from the server looks like so
<table id="registeredTable" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Locations</th>
<th>January</th>
<th>Feburary</th>
<th>March</th>
<th>April</th>
<th>May</th>
<th>June</th>
<th>July</th>
<th>August</th>
<th>September</th>
<th>October</th>
<th>November</th>
<th>December</th>
</tr>
</thead>
<tbody>
<?php
foreach($selectAllmonthlylocations as $item) {
echo '
<tr>
<td>'.$item["locations"].'</td>
<td>'.$item["Total"].'</td>
</tr>
';
}
?>
</tbody>
</table>
So my question is how can I format my array properly to display it in my table how I want?
Array
(
[0] => Array
(
[usergroup] => Austin_Domestic
[DateAdded] => 2018-01-03
[Total] => 15
)
[1] => Array
(
[usergroup] => Austin_International
[DateAdded] => 2018-01-25
[Total] => 2
)
[2] => Array
(
[usergroup] => BayArea_Domestic
[DateAdded] => 2018-01-16
[Total] => 192
)
[3] => Array
(
[usergroup] => BayArea_International
[DateAdded] => 2018-01-05
[Total] => 28
)
[4] => Array
(
[usergroup] => Bengaluru_Domestic
[DateAdded] => 2018-01-10
[Total] => 2
)
[5] => Array
(
[usergroup] => Bengaluru_International
[DateAdded] => 2018-01-05
[Total] => 1
)
[6] => Array
(
[usergroup] => Cork
[DateAdded] => 2018-01-02
[Total] => 31
)
[7] => Array
(
[usergroup] => CulverCity
[DateAdded] => 2018-01-10
[Total] => 3
)
[8] => Array
(
[usergroup] => Denver
[DateAdded] => 2018-01-10
[Total] => 1
)
[9] => Array
(
[usergroup] => Hyderabad
[DateAdded] => 2018-01-05
[Total] => 3
)
[10] => Array
(
[usergroup] => London
[DateAdded] => 2018-01-02
[Total] => 10
)
[11] => Array
(
[usergroup] => Macau
[DateAdded] => 2018-01-17
[Total] => 1
)
[12] => Array
(
[usergroup] => Munich
[DateAdded] => 2018-01-02
[Total] => 6
)
[13] => Array
(
[usergroup] => Sacramento_Domestic
[DateAdded] => 2018-01-04
[Total] => 1
)
[14] => Array
(
[usergroup] => Shanghai
[DateAdded] => 2018-01-12
[Total] => 2
)
[15] => Array
(
[usergroup] => Singapore
[DateAdded] => 2018-01-03
[Total] => 8
)
[16] => Array
(
[usergroup] => Sydney
[DateAdded] => 2018-01-21
[Total] => 1
)
[17] => Array
(
[usergroup] => Tokyo
[DateAdded] => 2018-01-04
[Total] => 3
)
[18] => Array
(
[usergroup] => Austin_Domestic
[DateAdded] => 2018-02-01
[Total] => 31
)
[19] => Array
(
[usergroup] => Austin_International
[DateAdded] => 2018-02-19
[Total] => 2
)
[20] => Array
(
[usergroup] => Bangkok
[DateAdded] => 2018-02-07
[Total] => 1
)
[21] => Array
(
[usergroup] => BayArea_Domestic
[DateAdded] => 2018-02-08
[Total] => 165
)
[22] => Array
(
[usergroup] => BayArea_International
[DateAdded] => 2018-02-12
[Total] => 29
)
Here is my code:
$selectallmonthlysql = 'SELECT locations, DateAdded, COUNT(*) as Total
FROM testserverdataSignup
WHERE DateAdded > "2017-12-31"
GROUP BY month(DateAdded), locations';
$selectAllmonthlystmt = $dbo->prepare($selectallmonthlysql);
$selectAllmonthlystmt->execute();
$selectAllmonthlylocations = $selectAllmonthlystmt->fetchAll(PDO::FETCH_ASSOC);
Screenshot of what the table currently looks like: I want the individual count for each location to correlate to the month and go across instead of down
First change your query
$selectallmonthlysql = '
SELECT
locations,
MONTHNAME(DateAdded) AS month,
COUNT(*) AS total
FROM
testserverdataSignup
WHERE
DateAdded > "2017-12-31"
GROUP BY month(DateAdded),locations';
I lowercased Total to total, its something that was irritating me.
With PDO then you can do
$results = $selectAllmonthlystmt->fetchAll(PDO::FETCH_GROUP);
foreach($results AS $location => $row ){
FETCH_GROUP is poorly documented but this will organize your data with the first column as the Key of the nested array, in this case the location, which is exactly what we want. One of the reasons I use PDO instead of that other DB library I won't mention by name but it starts with MySql and ends with i.
MONTHNAME (click for documentation) will return the full name of the month like "February" which although is not necessary (just a number would do) its much easier to read when outputting the array for debugging.
You'll wind up with something like this
//canned example data, notice one month is out of order and the big gap
// between February to October, this is to show it properly orders and
//fills those in. Always best to test this situations.
$result = array(
"Austin_Domestic" => array(
0 => Array(
"month" => "February",
"total" => 5
),
1 => Array(
"month" => "January",
"total" => 15
),
2 => Array(
"month" => "October",
"total" => 8
),
),
);
//$results = $selectAllmonthlystmt->fetchAll(PDO::FETCH_GROUP);
//then putting it all together
//we'll need the months in an array anyway so we can saves some space with them in the HTML too.
$months = array(
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
)
?>
<table id="registeredTable" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Locations</th>
<?php foreach($months as $month){
//Output the names of the months
echo "<th>{$month}</th>\n";
} ?>
</tr>
</thead>
<tbody>
<?php
foreach( $result as $location => $rows ){
echo "<tr>\n";
echo "<td>{$location}</td>\n";
//simplifies lookup by month (indexes are correlated)
//it returns column 'month' from $rows as a flat array.
//we can save ourselves an external loop by doing this "trick"
$m = array_column($rows, 'month');
//for example, in the case: [0=>February,1=>January,2=>October]
//because this is created from $rows, with a natural number index
//we can simply do array_search on $m to get the index we need in $rows (see below)
foreach($months as $month){
$index = array_search($month, $m);
if(false === $index){
echo "<td>0</td>\n";
}else{
echo "<td>{$rows[$index]['total']}</td>\n";
}
}
echo "</tr>\n";
}
?>
</tbody>
</table>
Output (I did format it to look a bit nicer):
<table id="registeredTable" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Locations</th>
<th>January</th>
<th>February</th>
<th>March</th>
<th>April</th>
<th>May</th>
<th>June</th>
<th>July</th>
<th>August</th>
<th>September</th>
<th>October</th>
<th>November</th>
<th>December</th>
</tr>
</thead>
<tbody>
<tr>
<td>Austin_Domestic</td>
<td>15</td>
<td>5</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>8</td>
<td>0</td>
<td>0</td>
</tr>
</tbody>
</table>
Sandbox
One note and benefit of using an array for the months is you spelled Feburary wrong it should be February something I've been guilty of many many times.
The only real downside to this, is the month name has to match the month name returned from the DB, which shouldn't be an issue if they are spelled correctly (which is how I found the mistake). Otherwise this can applied to the month as a number just as easily, same idea.
Cheers!
First, you should change the query to return MONTH(DateAdded) instead of the whole date, since that's how your output table is organized:
$selectallmonthlysql = 'SELECT locations, MONTH(DateAdded) AS month, COUNT(*) as Total
FROM testserverdataSignup
WHERE DateAdded > "2017-12-31"
GROUP BY month, locations';
Then you should reorganize the array into nested arrays:
array(location1 => array(month1 => total1, month2 => total2, ...),
location2 => array(month1 => total1, month2 => total2, ...),
...)
This code will do that:
$groupedData = array();
while ($selectAllmonthlystmt->fetch(PDO::FETCH_ASSOC) {
$groupedData[$row['locations']][$row['month']] = $row['Total'];
}
Then you can use nested loops when creating the table. The outer loop creates the rows, the inner loop is for the cells in the row.
foreach ($groupedData as $location => $locationData) {
echo "<tr><td>$location</td>";
for ($month = 1; $month <= 12; $month++) {
echo "<td>";
echo isset($locationData[$month]) ? $locaitonData[$month] : 0;
echo "</td>";
}
echo "</tr>";
}

Php Group array by value and count group item [duplicate]

This question already has answers here:
How to count array with group by
(2 answers)
Closed 4 months ago.
I am creating a notification system. That results shown below returns all notifications for a particular user. I want to group the array by 'notify_id' and also count each item in a group.
Such that I'll have :
"Jack Bill is now following you", John Doe commented on your post 2",
"John Doe and 2 others commented on your post 1"
Array ( [0] =>
Array ( [id] => 1
[user_id] => 10
[type] => follow
[notify_id] => 13
[notify_date] => 1483444712
[firstname] => Jack
[surname] => Bill
[picture] => )
[1] =>
Array ( [id] => 10
[user_id] => 10
[type] => comment
[notify_id] => 2
[notify_date] => 1482159309
[firstname] => John
[surname] => Doe
[picture] => )
[2] =>
Array ( [id] => 8
[user_id] => 10
[type] => comment
[notify_id] => 1
[notify_date] => 1482159219
[firstname] => John
[surname] => Doe
[picture] => )
[3] =>
Array ( [id] => 6
[user_id] => 16
[type] => comment
[notify_id] => 1
[notify_date] => 1482159129
[firstname] => James
[surname] => Canon
[picture] => )
[4] =>
Array ( [id] => 5
[user_id] => 14
[type] => comment
[notify_id] => 1
[notify_date] => 1482159079
[firstname] => Sharon
[surname] => Abba
[picture] => ) )
You have two questions, I will try to answer both of them:
I want to group the array by 'notify_id'...
Assuming your array name is $a:
$return = array();
foreach($a as $val) {
if (!isset($return[$val['notify_id']])) {
$return[$val['notify_id']] = array();
}
$return[$val['notify_id']][] = $val;
}
print_r($return); // <-- Your array is grouped by notify_id
... and also count each item in a group.
Now you have your grouped by notify_id in $return so:
foreach($return as $k => $v) {
echo count($v) . ' values are present for notify #' . $k;
// It will display something like: 10 values are present for notify #1
}
Hope it will help, good luck!

Looping through Arrays to build new array of data

I have a notifications section on my site and I am getting data from my table. There can be child notifications assigned to their parent, so I have parent_id in the table as shown below:
Below is the array I am getting
Array
(
[0] => stdClass Object
(
[user_title] => Mr
[user_firstname] => Richard
[user_lastname] => Knight-Gregson
[assignee_title] => Mr
[assignee_firstname] => Richard
[assignee_lastname] => Knight-Gregson
[created] => 2015-03-26 11:40:20
[id] => 61
[user_id] => 88
[description] => message for user rkg uid 88
[assignee] => 88
[parent_id] =>
[cc] =>
[bcc] =>
[status] => 0
)
[1] => stdClass Object
(
[user_title] => Mr
[user_firstname] => Richard
[user_lastname] => Knight-Gregson
[assignee_title] => Mr
[assignee_firstname] => Richard
[assignee_lastname] => Knight-Gregson
[created] => 2015-03-26 12:45:47
[id] => 71
[user_id] => 88
[description] => This is child
[assignee] => 88
[parent_id] => 61
[cc] =>
[bcc] =>
[status] => 0
)
[2] => stdClass Object
(
[user_title] => Mr
[user_firstname] => Ted
[user_lastname] => Chiles
[assignee_title] => Mr
[assignee_firstname] => Richard
[assignee_lastname] => Knight-Gregson
[created] => 2015-03-27 10:11:56
[id] => 207
[user_id] => 47
[description] => cc 88
[assignee] => 88
[parent_id] =>
[cc] => 88
[bcc] => 112
[status] => 0
)
[3] => stdClass Object
(
[user_title] => Mr
[user_firstname] => Richard
[user_lastname] => Knight-Gregson
[assignee_title] => Mr
[assignee_firstname] => Richard
[assignee_lastname] => Knight-Gregson
[created] => 2015-03-27 10:17:31
[id] => 209
[user_id] => 88
[description] => sadfasdfasd
[assignee] => 88
[parent_id] =>
[cc] => 88
[bcc] => 0
[status] => 0
)
)
Here is the code I have at the moment to loop through the array, what I need to add to this is to get all elements that have a parent_id and then display them under their repsective parent in a list...
<table class="notifications-table" border="1">
<tr>
<th>S No.</th><th>Date</th><th>Employee</th><th id="details">Details</th><th>Assignee</th><th>Action</th>
</tr>
<?php foreach($notifications as $row){ ?>
<?php foreach($row as $k){
} ?>
<tr <?php if($row->status){ echo "class='resolved'"; } ?> id="row-<?=$row->id;?>">
<td><?=$row->user_id?></td><td><?=date('d M, H:i',strtotime($row->created));?></td>
<td><?=$row->user_title.' '.$row->user_firstname.' '.$row->user_lastname;?></td>
<td>
row id is : <?=$row->id.' == '.$row->parent_id; ?>
<?php //echo $row->id.' == '.$row->parent_id; ?>
<?=$row->description; ?><span data-parent-id="<?=$row->id;?>" data-user-id="<?=$row->user_id;?>" id="add_not" data-featherlight="#send_child_message" data-id="add_child_notification" class="glyphicon glyphicon-plus"></span>
</td>
<td><?=$row->assignee_title.' '.$row->assignee_firstname.' '.$row->assignee_lastname;?></td>
<td><input <?php if($row->status){ echo "disabled"; } ?> value="<?=$row->id;?>" data-action="not" type="checkbox" /></td>
</tr>
<?php } ?>
</table>
I have tried a few things but just cant get what I want!
Regards!
The code you have seems correct. I was able to take most of your structure and iterate over it with and got what you see in screenshot:
I was able to see 2 rows of info because I only used 2 elements (not all of them).
Ok, I see now what you are trying to do. You want to display details of the parent id element - which in the example, would be my "row 2" since row id 71 is a 'child of' row id 61.
If my assumption is correct, you need to associate the elements with each other based on this idea of parent & child.
Before your "Details" closing td, you can add...
<?php foreach($notifications as $row2){ ?>
<?php if ($row2->id == $row->parent_id) : ?> PARENT DESC: <?= $row2->description; ?><?php endif; ?>
<?php } ?>
Which should now let you pull in some parent property values.

Php, Mysql distinctor grouped query

I'm struggling, creating a mysql query for the following scenario:
Array
(
[0] => stdClass Object
(
[id] => 1
[qid_id] => 1
[user_id] => 1
[question] => Favorite Place
[answer] => New York
[username] => john
)
[1] => stdClass Object
(
[id] => 2
[qid_id] => 1
[user_id] => 1
[question] => Additional Info
[answer] => N/A
[username] => john
)
[2] => stdClass Object
(
[id] => 3
[qid_id] => 1
[user_id] => 1
[question] => Favorite Place
[answer] => London
[username] => peter
)
[3] => stdClass Object
(
[id] => 4
[qid_id] => 1
[user_id] => 1
[question] => Additional Info
[answer] => N/A
[username] => peter
)
[4] => stdClass Object
(
[id] => 5
[qid_id] => 1
[user_id] => 2
[question] => Favorite Place
[answer] => Sidney
[username] => mike
)
[5] => stdClass Object
(
[id] => 6
[qid_id] => 1
[user_id] => 2
[question] => Additional Info
[answer] => N/A
[username] => mike
)
)
I'm trying to display data in html table, and so far I got the following:
$sql = "SELECT DISTINCT question"
. "\n FROM faq "
. "\n WHERE qid_id = 1";
$data = $db->fetchAll($sql);
$sql2 = "SELECT f.*, u.username"
. "\n FROM faq as f"
. "\n LEFT JOIN users as u on u.id = f.user_id "
. "\n WHERE f.qid_id = 1";
$data2 = $db->fetchAll($sql2);
<table>
<thead>
<tr>
<?php
print "<th>USERNAME</th>";
for ($i = 0; $i < count($data); $i++) {
print "<th>" . $data[$i]->question . "</th>";
}
?>
</tr>
</thead>
<tbody>
The above works fine, I'm having problem displaying the rest of the table, using second query ($data2). I'm not sure how to group fields in order to get unique results for each row.
The idea is to have something like:
USERNAME Favorite Place Additional Info
john New York N/A
peter London N/A
mike Sidney N/A

Categories