I have an array in the Below format.
time_range:6 [▼
"limit_by" => array:1 [▼
0 => "Day",
1 => "Date"
]
"day" => array:1 [▼
0 => "mon",
1 => ""
]
"date" => array:1 [▼
0 => "",
1 => "2015-03-14"
]
"from_time" => array:1 [▼
0 => "07:00:00",
1 => "10:30:00"
]
"to_time" => array:1 [▼
0 => "20:00:00",
1 => "16:30:00"
]
"max_covers_limit" => array:1 [▼
0 => "5",
1 => "3"
]
]
How can I format the above array in PHP so that I can display a table which looks similar to the below format:
Limit By | Day or Date | From Time | To Time | Max Limit
Day | Mon | 07:00:00 | 20:00:00 | 5
Date | 2015-03-14 | 10:30:00 | 16:30:00 | 3
Please provide me a way.
This is what I Tried:
foreach($time_range as $time_range)
{
$block_time_range['limit_by'] = $time_range['limit_by'];
$block_time_range['day'] = $time_range['day'];
$block_time_range['date'] = $time_range['date'];
$block_time_range['from_time'] = $time_range['from_time'];
$block_time_range['to_time'] = $time_range['to_time'];
$block_time_range['max_covers'] = $time_range['max_covers'];
}
You can do so by using the following code.
<?php
$keys = array_keys($time_range);
// count the number of rows based on the first column
$rows = count($time_range[key($time_range)]);
echo '<table><thead><tr>';
// show header
foreach($keys as $key) {
echo '<th>'.$key.'</th>';
}
echo '</tr></thead><tbody>';
// for every row
for($i = 0; $i < $rows; ++$i) {
echo '<tr>';
// for every column
foreach($time_range as $column) {
echo '<td>'.$column[$i].'</td>';
}
echo '</tr>';
}
echo '</tbody></table>';
?>
Related
Hello I've got two arrays, one which is made with Carbon that takes the last 12 months from today (in Y-m format) and a Collection (which have an array of items that return every transaction of the last 12 months in the same Y-m format). What I want to do is fill in this items array if there's no transaction for example on the month 12, 9, 8 fill them with 0.
Here's the 2 arrays I need compared and fill missing Year-month with 0 (the last array is the balance which will be merged into the array for every month).
^ array:12 [▼
"2022-02" => 0
"2022-03" => 0
"2022-04" => 0
"2022-05" => 0
"2022-06" => 0
"2022-07" => 0
"2022-08" => 0
"2022-09" => 0
"2022-10" => 0
"2022-11" => 0
"2022-12" => 0
"2023-01" => 0
]
^ array:12 [▼
"2022-01" => 0
"2022-02" => 1
"2022-03" => 2
"2022-04" => 3
"2022-06" => 4
"2022-07" => 5
"2022-08" => 6
"2022-09" => 7
"2022-10" => 8
"2022-11" => 9
"2022-12" => 10
"2023-01" => 11
]
^ array:12 [▼
0 => 340
1 => 480
2 => 550
3 => 690
4 => 830
5 => 970
6 => 1110
7 => 1250
8 => 1460
9 => 1600
10 => 1670
11 => 1880
]
The code I used at the moment to find the balance per month (the latest balance of the month) but at the moment I dont print the missing months (it just skips them instead of filling with 0):
$period = CarbonPeriod::create(now()->subMonths(11), now())->month();
$dates = array();
$days = array();
foreach($period as $date) {
$dates[] = $date->format("Y-m");
$days[] = $date->lastOfMonth()->format("d-m-Y");
}
$userTransactions = auth()->user()->transactions;
$flipped = array_flip($dates);
$transactionsByMonth = $userTransactions->groupBy(function($d) {
$monthlyTransaction = Carbon::parse($d->created_at)->format('Y-m');
return $monthlyTransaction;
});
foreach($flipped as $key => $yearMonth){
$yearMonth = 0;
$flipped[$key] = $yearMonth;
}
dump($flipped);
foreach($transactionsByMonth as $transaction) {
if (sizeof($transaction) > 1){
$duplicatedTransactions = $transaction->groupBy(function($d) {
return Carbon::parse($d->created_at)->format('Y-m-d');
});
$lastDuplicatedTransactions = $duplicatedTransactions->last();
foreach($lastDuplicatedTransactions as $lastTransaction){
$transactionDates[] = $lastTransaction->created_at;
$transactionBalance[] = $lastTransaction->main_balance;
}
} else {
foreach($transaction as $notDuplicatedTransaction){
$transactionDates[] = $notDuplicatedTransaction->created_at;
$transactionBalance[] = $notDuplicatedTransaction->main_balance;
}
}
};
$transactionsPerMonth = [];
foreach($transactionDates as $date){
$date = Carbon::parse($date)->format('Y-m');
$transactionsPerMonth[] = $date;
}
$transactionsPerMonth = array_flip($transactionsPerMonth);
dump($transactionsPerMonth);
dump($transactionBalance);
At the moment I achieved printing the balance of the oldest day of the month on the last 12 months, what Im missing is comparing if of this 12 months if there's a month missing fill it with 0 instead of skipping it.
You can use array_key_exists() function to compare the two arrays and fill in missing months with 0.
Example:
$carbonMonths = ["2022-01", "2022-02", "2022-03", "2022-04", "2022-05", "2022-06", "2022-07", "2022-08", "2022-09", "2022-10", "2022-11", "2022-12"];
$transactions = [
["2022-01" => 200],
["2022-02" => 150],
["2022-03" => 100],
["2022-05" => 50]
];
foreach ($carbonMonths as $month) {
if (!array_key_exists($month, $transactions)) {
$transactions[$month] = 0;
}
}
In this example, the $carbonMonths array contains the last 12 months in Y-m format. The $transactions array contains transactions in the same format.
You can also use the array_merge() function to merge the two arrays and fill in any missing values with 0.
$merged = array_merge(array_fill_keys($carbonMonths, 0), $transactions);
Here $transactions should be an associative array with keys as month and value for this to work.
Both of the approach should give you the same result, you may use the one which you find easy to implement.
Improved the code to this:
$months = CarbonPeriod::create(now()->subMonths(11), now())->month();
$transactions = auth()->user()->transactions
->groupBy( fn($d) => Carbon::parse( $d->created_at )->format('Y-m'))->map->last();
$transactionsByMonth = collect($months)
->flatMap(function ($key) use ($transactions) {
$key = $key->format('Y-m');
return [$key => collect($transactions[$key]->main_balance ?? 0)];
});
$transactionsByMonth = $transactionsByMonth->toArray();
$transactionsByMonth = array_values($transactionsByMonth);
dump($transactionsByMonth);
But Im getting an array inside an array:
array:12 [▼
0 => array:1 [▼
0 => 480
]
1 => array:1 [▼
0 => 550
]
2 => array:1 [▼
0 => 690
]
3 => array:1 [▶]
4 => array:1 [▶]
5 => array:1 [▶]
6 => array:1 [▶]
7 => array:1 [▶]
8 => array:1 [▶]
9 => array:1 [▶]
10 => array:1 [▶]
11 => array:1 [▶]
]
So What I finally did to solve it was instead of returning the collect() for every $key I just returned the collect directly so I would stop getting an array inside an array.
Replaced this:
$transactionsByMonth = collect($months)
->flatMap(function ($key) use ($transactions) {
$key = $key->format('Y-m');
return [$key => collect($transactions[$key]->main_balance ?? 0)];
});
$transactionsByMonth = $transactionsByMonth->toArray();
$transactionsByMonth = array_values($transactionsByMonth);
dump($transactionsByMonth);
Into this:
$transactionsByMonth = collect($months)
->flatMap(function ($key) use ($transactions) {
$key = $key->format('Y-m');
return collect($transactions[$key]->main_balance ?? 0);
});
$transactionsByMonth = $transactionsByMonth->toArray();
I have this array with certain brand_ids, within these brands I have an array of dates in which a sale occured but these are based on the products in sale so they may appear multiple times on the same brand_id;
This is my array:
array:5 [▼
2 => array:3 [▼
0 => "2022-05-08"
1 => "2022-05-08"
2 => "2022-05-08"
]
3 => array:5 [▼
0 => "2022-05-08"
1 => "2022-05-08"
2 => "2022-05-08"
3 => "2022-05-08"
4 => "2022-05-08"
]
4 => array:1 [▼
0 => "2022-05-08"
]
1 => array:3 [▼
0 => "2022-05-01"
1 => "2022-05-08"
2 => "2022-05-08"
]
6 => array:3 [▼
0 => "2022-05-08"
1 => "2022-05-08"
2 => "2022-05-08"
]
]
The code to generate this :
pastSales = [];
$historySales = SaleHistoryCount::all()->toArray();
foreach($historySales as $key => $historySale) {
$saleDateToCompare = Carbon::createFromFormat('Y-m-d H:i:s', $historySale['sale_date'])
->format('Y-m-d');
if(in_array($saleDateToCompare , $saleDays)) {
if(! isset($pastSales[$historySale['sale_date']])) {
$pastSales [$historySale['brand_id']][] = Carbon::createFromFormat('Y-m-d H:i:s', $historySale['brand_id'])
->format('Y-m-d');
}
}
}
$saleDays is a 2D array of every sunday untill a certain year like so
[
"2022-05-08"
"2022-05-15"
"2022-05-22"
]
All the duplicates stripped out and have it reduced to one unless the date is different per brand_id but I can't seem to be able to produce that with array_unique, array_mapping and/or array_columns... How would I achieve the output below?
array:5 [▼
2 => array:3 [▼
0 => "2022-05-08"
]
3 => array:5 [▼
0 => "2022-05-08"
]
4 => array:1 [▼
0 => "2022-05-08"
]
1 => array:3 [▼
0 => "2022-05-01"
2 => "2022-05-08"
]
6 => array:3 [▼
0 => "2022-05-08"
]
]
Use in_array as Tim Lewis proposed:
foreach($historySales as $key => $historySale) {
$saleDateToCompare = Carbon::createFromFormat('Y-m-d H:i:s', $historySale['sale_date'])
->format('Y-m-d');
if(in_array($saleDateToCompare , $saleDays)) {
$date_formatted = Carbon::createFromFormat('Y-m-d H:i:s', $historySale['brand_id'])->format('Y-m-d');
// !!! Is this string correct? Maybe we should check for "$historySale['brand_id']" existance?
if(! isset($pastSales[$historySale['sale_date']]))
$pastSales[$historySale['brand_id']] = [];
if( !in_array($date_formatted, $pastSales[$historySale['brand_id']]) )
$pastSales[$historySale['brand_id']][] = $date_formatted;
}
}
I've database like this
+------------+----------------------------+---------------------------+
| day | start_time | end_time |
+---------------------------------------------------------------------+
| Sunday | 01:00 | 03:00 |
| Sunday | 13:00 | 15:00 |
| Sunday | 19:00 | 21:00 |
+------------+----------------------------+---------------------------+
and for checking date, i do with looping
// **nowTime = 02:00**
$get = DateModel::find($id)->get();
foreach($get as $result){
if(nowTime >= $result->start_time && nowTime <= $result->end_time){
echo "in range time";
}else{
echo "not in range time";
}
}
and the result :
in range time not in range time not in range time
i just want only show 1 result if there have "in range time" ,
and if all data not in range time, go to else.
any idea ?
You can use mapToGroups collection method.
$get = DateModel::get()
->mapToGroups(function ($item, $key) {
$nowTime = '02:00';
if ($nowTime >= $item->start_time && $nowTime <= $item->end_time) {
return ['in range time' => $item];
} else {
return ['not in range time' => $item];
}
});
Result
array:2 [
"in range time" => array:1 [
0 => array:3 [
"day" => "Sunday"
"start_time" => "01:00"
"end_time" => "03:00"
]
]
"not in range time" => array:2 [
0 => array:3 [
"day" => "Sunday"
"start_time" => "13:00"
"end_time" => "15:00"
]
1 => array:3 [
"day" => "Sunday"
"start_time" => "19:00"
"end_time" => "21:00"
]
]
]
My current array that is being looped dumps this structure
0 => array:11 [▼
"category_code" => "123"
"category_name" => "Testing"
"category_description" => "This is a test category"
19738 => array:5 [▼
"identifier" => "720368842943"
"description" => Test Description One
"count" => 4
"details" => array:2 [▼
0 => array:3 [▼
"detail_code" => "2751"
"detail_code2" => "43"
"detail_specifier" => "Detail One"
]
1 => array:3 [▼
"detail_code" => "2681"
"detail_code2" => "9"
"detail_specifier" => "Detail Two"
]
]
"prices" => array:1 [▼
"01" => "1129.00"
]
]
19739 => array:5 [▼
"identifier" => "720368844121"
"description" => "Test Description Two"
"count" => 4
"details" => array:2 [▼
0 => array:3 [▼
"detail_code" => "2751"
"detail_code2" => "43"
"detail_specifier" => "Detail One"
]
1 => array:3 [▼
"detail_code" => "2681"
"detail_code2" => "9"
"detail_specifier" => "Detail Two"
]
]
"prices" => array:1 [▼
"01" => "1490.00"
]
]
But when I export to excel it only shows the three top level attributes
123 | Testing | This is a test category
I'm trying to export this in a way so that those top 3 values are one row (like a header) and all related products are listed under it like so:
123 | Testing | This is a test category
====================================================================================================================
19738 | 720368842943 | Test Description One | 4 | 2751 | 43 | Detail One | 2681 | 9 | Detail Two | 1129.00
19739 | 720368844121 | Test Description Two | 4 | 2751 | 43 | Detail One | 2681 | 9 | Detail Two | 1490.00
I'm using Laravel Excel by maatwebsite which is just a wrapper for PHPExcel in laravel, but all i want to do is simply take the category info as a row with the subsequent product info as rows below it.
Here's the excel code with the array I'm using, which is dumped above (item Code is the 19738,19739 values)
$allCategoryResult= array();
foreach($prices->categories as $category){
$categoryItem = array();
$categoryItem["category_code"] = $category->category_code;
$categoryItem["category_name"] = $category->category_name;
$categoryItem["category_desc"] = $category->category_desc;
foreach($category->skus as $sku){
$skuItem = array();
$skuItem["identifier"] = $sku->sku_info->identifier;
$skuItem["description"] = $sku->sku_info->item->description;
$skuItem["count"] = $sku->sku_info->item->item_type->count;
$skuItem["details"] = array();
foreach ($sku->sku_info->details as $details) {
$detailsItem = array();
$detailsItem["detail_code"] = $details->detail_code;
$detailsItem["detail_code2"] = $details->detail_code2;
$detailsItem["detail_specifier"] = $details->detail_specifier;
$skuItem["details"][] = $detailsItem;
}
$skuItem["prices"] = get_object_vars($sku->prices);
$itemCode = $sku->sku_info->item->item_code;
$categoryItem[$itemCode] = $skuItem;
}
$allCategoryResult[] = $categoryItem;
}
$name = 'Test Export';
$build = Excel::create($name, function ($excel) use ($allCategoryResult) {
$excel->setTitle('Test Export');
$excel->sheet('Test Export', function ($sheet) use ($allCategoryResult) {
$sheet->fromArray($allCategoryResult);
})->download('xlsx');
The methodfromArray() expects a 2D array
$data=(
array(2) (
[0] => array(3) (
[0] => 19738
[1] => ...
[2] => ...
)
[1] => array(4) (
[0] => 19739
[1] => ...
[2] => ...
[3] => ...
Each element of the array $data is a row. Each sub element is the value of a column. Restructure the creation of your array to fit this structure and you will be in business.
This code is untested, just trying to give an example. I'm not sure what you're doing with the get_object_vars($sku->prices);. I'm sure this will have to change.
$excelRows = [];
foreach($prices->categories as $category){
$excelRows[] = [
$category->category_code,
$category->category_name,
$category->category_desc
]
foreach($category->skus as $sku){
$row = [
$sku->sku_info->identifier,
$sku->sku_info->item->description,
$sku->sku_info->item->item_type->count
]
foreach ($sku->sku_info->details as $details) {
$row[] = $details->detail_code;
$row[] = $details->detail_code2;
$row[] = $details->detail_specifier;
}
$row[] = get_object_vars($sku->prices);
$row[] = $sku->sku_info->item->item_code;
$excelRows[] = $row;
}
}
This question already has answers here:
PHP's array_merge_recursive behaviour on integer keys
(5 answers)
Closed 5 months ago.
I have 2 arrays, each will always have the same number of rows and same number of values per row.
I need to merge the 2 arrays together, to combine the results on each row, but in a particular way (there will always be only 3 results per row on each array too):
For example, for each row, take the first result of each array, and put them next to each other, then the second result of each array, and put them next to each other, then finally the third.
So Array 1's value will always precede Array 2's value (example shown below):
Array 1:
array:7 [▼
24 => array:3 [▼
0 => 0
1 => 0.66666666666667
2 => 0.66666666666667
]
25 => array:3 [▶]
26 => array:3 [▶]
27 => array:3 [▶]
29 => array:3 [▶]
30 => array:3 [▶]
31 => array:3 [▶]
]
Array 2:
array:7 [▼
24 => array:3 [▼
0 => 0.375
1 => 0.42857142857143
2 => 0.55555555555556
]
25 => array:3 [▶]
26 => array:3 [▶]
27 => array:3 [▶]
29 => array:3 [▶]
30 => array:3 [▶]
31 => array:3 [▶]
]
Intended Combined Array Format:
array:7 [▼
24 => array:6 [▼
0 => 0
1 => 0.375
2 => 0.66666666666667
3 => 0.42857142857143
4 => 0.66666666666667
5 => 0.55555555555556
]
25 => array:6 [▶] ...
Current loop which returns the incorrect layout:
$results = array();
foreach ($questionDetails as $key => $question) {
for ($i = 0; $i < 3; $i++) {
$results[$key][] = $array1[$key] + $array2[$key];
}
}
Returns:
array:7 [▼
24 => array:3 [▼
0 => array:3 [▼
0 => 0
1 => 0.66666666666667
2 => 0.66666666666667
]
1 => array:3 [▼
0 => 0
1 => 0.66666666666667
2 => 0.66666666666667
]
2 => array:3 [▼
0 => 0
1 => 0.66666666666667
2 => 0.66666666666667
]
]
25 => array:3 [▶]
26 => array:3 [▶]
27 => array:3 [▶]
29 => array:3 [▶]
30 => array:3 [▶]
31 => array:3 [▶]
]
I'm unsure why my loop isn't just adding the three values from each row together - but then I think they still won't be in the right order, but I'm unsure of how to approach this.
Many thanks.
This is the "unfancy" (but save) solution if I understand your question correctly - all keys are preserved an set as desired:
$array1;
$array2;
$results = array();
foreach ($questionDetails as $key => $question1) {
$question2 = $array2[$key];
$tp = array();
$tp[0] = $question1[0];
$tp[1] = $question2[0];
$tp[2] = $question1[1];
$tp[3] = $question2[1];
$tp[4] = $question1[2];
$tp[5] = $question2[2];
$results[$key] = $tp;
}
EDIT: There is a way more flexible way to implement this where the number of arguments may vary (see PHP: array_merge() in alternate order (zip order)?).
$array1;
$array2;
function array_zip(...$arrays) {
return array_merge(...array_map(null, ...$arrays));
}
$results = array();
foreach ($questionDetails as $key => $question1) {
$results[$key] = array_zip($question1,$array2[$key]);
}
I would do this:
$combined = array();
foreach($array1 as $key => $value){
$combined[$key] = array();
foreach($value as $key2 => $value2){
$combined[$key][] = $value2;
$combined[$key][] = $array2[$key][$key2];
}
}
For a variable number of records.