PHPExcel issue with multidimensional array and creating grouped data - php

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;
}
}

Related

getting emptied while checking if an array value exists - laravel?

I wanted to insert the id values of $courseCat if that id is not present in $m.In the below code, i feel the $m array is getting emptied every time and so, all id's are getting inserted to the $m ,as the result of dump($m) indicates.How can i fix this?
$m=[];
$courseCat = MyCourse::where('course_id', $key['courseId'])->get()->toArray();
foreach($courseCat as $k=>$c){
// dump($courseCat);
if(!in_array($c['id'],$m)){
array_push($m,$c['id']);
}
}
//dump($m);
dump($courseCat); shows the following result
array:2 [
0 => array:19 [
"id" => 2
"course_id" => 18
]
1 => array:19 [
"id" => 3
"course_id" => 18
]
]
array:2 [
0 => array:19 [
"id" => 2
"course_id" => 18
]
1 => array:19 [
"id" => 3
"course_id" => 18
]
]
array:2 [
0 => array:19 [
"id" => 5
"course_id" => 1
]
1 => array:19 [
"id" => 6
"course_id" => 1
]
]
array:2 [
0 => array:19 [
"id" => 5
"course_id" => 1
]
1 => array:19 [
"id" => 6
"course_id" => 1
]
]
dump($m) shows the below result:
array:2 [
0 => 2
1 => 3
]
array:2 [
0 => 2
1 => 3
]
array:2 [
0 => 6
1 => 5
]
array:2 [
0 => 6
1 => 5
]
Below attached images are the result of the query MyCourse::where('course_id', $key['courseId'])->get().
[enter image description here]1
[enter image description here]2
[enter image description here]3
Expected result :
dump($m) should show the below result
[0=>2,
1=>3,
2=>5,
3=>6]
I think it's because you have an outer loop not shown in the question. You need to declare $m before the outer loop:
$m=[];
foreach($keys as $key){
$courseCat = MyCourse::where('course_id', $key['courseId'])->get()->toArray();
foreach($courseCat as $k=>$c){
if(!in_array($c['id'],$m)){
array_push($m,$c['id']);
}
}
}
dump($m);
If you want all the values of a column from your query you can use pluck:
MyCourse::where('course_id', $key['courseId'])->pluck('id')
Now you have a list of all the 'id's.
Laravel 8.x Docs - Database - Running Database Queries - Retrieving a List of Column Values pluck

How to get values from an array in Laravel

I have a 3 level category. I need to gain businesses on level 3 category.
I write this code:
$main_cat = Category::where(['slug' => $url])->first();
$lev_cat2 = Category::where(['parent_id' => $main_cat->id, 'status' => '1'])->get();
foreach ($lev_cat2 as $subCategory) {
$cat_ids_lv2[] = $subCategory->id . ',';
}
foreach ($lev_cat2 as $subCat) {
$lev_cat3[] = Category::where(['parent_id' => $subCat->id, 'status' => '1'])->pluck('id')->toArray();
}
dd($lev_cat3);
Then I got this array which is correct:
array:5 [▼
0 => array:3 [▼
0 => 145
1 => 146
2 => 147
]
1 => array:3 [▼
0 => 148
1 => 149
2 => 150
]
2 => array:3 [▼
0 => 151
1 => 152
2 => 153
]
3 => array:3 [▼
0 => 154
1 => 155
2 => 156
]
4 => []
]
now I dont know how can I get values like 145,146,147,148,149,... to pass theme to
Business::where(['category_id'=> [145,146,147,148,...]]->get();
of course dynamic.
You can use laravel collection helpers :
Business::whereIn('category_id', collect($lev_cat3)->flatten()->all())->get();
Since PHP 5.5.0 there is a built-in function array_column which does exactly this.
You can use it to Converting php array of arrays into single array then use it like this
$category_ids = array_column($lev_cat3);
Business::where(['category_id'=> $category_ids]]->get();

Concatenate strings from 2 array based on key

so i have a bit difficulty in combining arrays in php. So let say i have these 2 array
array:4 [▼
20 => "University"
21 => "Polic Station"
22 => "Ambulance"
1 => "Zoo"
]
array:4 [▼
20 => "abc"
21 => "def"
22 => "ghi"
1 => "jkl"
]
How do i actually combine this to this
array:4 [▼
20 => "abc University"
21 => "def Polic Station"
22 => "ghi Ambulance"
1 => "jkl Zoo"
]
Here's the result:
$arr = array(
20=>'University',
21=>'Polic Station',
22=>'Ambulance',
1=>'Zoo');
$arr2= array(
20=>'abc',
21=>'def',
22=>'ghi',
1=>'jkl');
$arr_out = array();
foreach($arr as $key=>$el) {
$arr_out[$key] = $arr2[$key] ." ".$el;
}
var_dump($arr_out);
Obviously, you'll need to keep in mind to check whether the key exists in the second array so you do not get an error when accessing the value.

Format Array in PHP

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>';
?>

Php sorting based on ID and ParentID

i have the following array structure:
| ID | CategoryName | ParentID
_________________________________
1 | Movies | -1
_________________________________
2 | Series | -1
_________________________________
3 | ActionMovies | 1
_________________________________
4 | HorrorMovies | 1
_________________________________
5 | ComedySeries | 2
_________________________________
6 | TVShows | -1
My goal is to reach the following structure
Goal:
| ID | CategoryName | ParentID
_________________________________
1 | Movies | -1
_________________________________
3 | ActionMovies | 1
_________________________________
4 | HorrorMovies | 1
_________________________________
2 | Series | -1
_________________________________
5 | ComedySeries | 2
_________________________________
6 | TVShows | -1
Or explained in word:
Parent-Categories have ParentID = -1 (Example Movies)
All categories keep their original ID-Number
Should come listed directly after their ParentCategory (Example ActionMovies)
RootCategories without Children, come listed at the end of array. (Example TVShows)
How can i achieve this best with PHP? I have no access to the original Mysql query, so that is not an option :)
i have started with this code, but i am not sure it is the right path, and with minimal efforts/readability
$tmpList = Categories_Models_Main::getAllCategories();
$categoryData = array();
foreach ($tmpList as $index => $categoryObject) {
$categoryData[] = array('id' => $categoryObject->id,
'CategoryName' => $categoryObject->parentId,
'name' => $categoryObject->name);
}
///let us assume $categoryData is original state.
///Beginning of manipulation and re-sorting of $tmpList
foreach ($categoryData as $key => $value) {
$mainId[$key] = $value['id'];
$parentId[$key] = $value['parentId'];
}
array_multisort($parentId, $mainId, $categoryData);
Split the main array into two, one with those nodes that doesn't have childs and other with rests of items.
Do the sorting into array of items with array_multisort function and do too a sorting into array of categories without childs using the criteria that you want. The final step will be push the array without childs to the other.
This form isn't the most efficient, but to have a first approach is valid, after this, you can dispense time optimizing the code.
$input = array(
array("foo", "bar", "5"),
array("barr", "baz", "9"),
array("nyan", "nyu", "2")
);
usort($input, function($a, $b) {
if($a[2] < $b[2]) {
return -1;
} else if($a[2] > $b[2]) {
return 1;
} else {
return 0;
}
});
var_dump($input);
Do you mean something like this? The idea is to manually compare the contents of the array using condition you know. Since the thing what is to be sorted is unique, the logic how to sort must be always implemented. With PHP, PHP’s sorting functions most of time does it correctly.
I am pretty sure that this does not answer your question, but might give you some ideas how to make your life easier. This is javascript approach of the problem, but this way you won't even have to think about sorting anything. You just provide parents and children and it is sorted for you and ready to use. A pretty nice way in my opinion. Yet it is probably irrelevant to what you are trying to do, but maybe for some other similar problem you would see this as a solution: https://developers.google.com/chart/interactive/docs/gallery/orgchart
The only way to solve this problem is by using a bottom up approach (i am referring to the pyramids).
Explanation
We need to start with rows (entries) within an array that do not have parents. In my case, it's any element that has "parent_id = 0". Once we have those, we need to build children elements for each parent element.
The latter part would be done recursively by calling sorting method until the element which we are processing has not children. The results from the sorting method are passed down to the previous array point until the array is complete.
Code
Class Categories {
private $cats;
public function getAllCategoriesSorted() {
/**
* $this->cats = [
* 'id' => x, 'parent_id' => x
* ];
*/
$this->cats = Category::get()->toArray();
# find categories with no parents
$keys = array_keys(array_column($this->cats, 'parent_id'), 0);
$return = [];
# loop through each and populate each one
foreach ($keys as $key) {
$return[$this->cats[$key]['id']] = $this->sortCategories($this->cats[$key]);
}
dd($return);
}
private function sortCategories($currentElement) {
# we need to check if current element has any children
$keys = array_keys(array_column($this->cats, 'parent_id'), $currentElement['id']);
if ($keys === false || empty($keys)) {
# we are dealing with childless element, we should return it as it is
return $currentElement;
}
# we are dealing with element that has children, we need to loop through each child
$currentElement['children'] = [];
foreach ($keys as $key) {
$currentElement['children'][$this->cats[$key]['id']] = $this->sortCategories($this->cats[$key]);
}
return $currentElement;
}
}
Example result
array:2 [▼
65 => array:4 [▼
"id" => 65
"name" => "Parent 1"
"parent_id" => 0
"children" => array:14 [▼
66 => array:4 [▼
"id" => 66
"name" => "Child 1"
"parent_id" => 65
"children" => array:22 [▶]
]
87 => array:4 [▼
"id" => 87
"name" => "Child 2"
"parent_id" => 65
"children" => array:31 [▶]
]
117 => array:4 [▶]
118 => array:4 [▶]
120 => array:4 [▶]
124 => array:4 [▶]
125 => array:4 [▶]
127 => array:4 [▶]
225 => array:4 [▶]
305 => array:4 [▶]
434 => array:4 [▶]
321 => array:4 [▶]
348 => array:4 [▶]
468 => array:4 [▶]
]
]
64 => array:4 [▼
"id" => 64
"name" => "Parent 2"
"parent_id" => 0
"children" => array:5 [▼
128 => array:4 [▶]
132 => array:4 [▼
"id" => 132
"name" => "Child 3"
"parent_id" => 64
"children" => array:22 [▼
202 => array:3 [▶]
203 => array:3 [▼
"id" => 203
"name" => "Child 4"
"parent_id" => 132
]
204 => array:3 [▶]
205 => array:3 [▶]
206 => array:3 [▶]
207 => array:3 [▶]
208 => array:3 [▶]
209 => array:3 [▶]
210 => array:3 [▶]
211 => array:3 [▶]
212 => array:3 [▶]
213 => array:3 [▶]
214 => array:3 [▶]
215 => array:3 [▶]
216 => array:3 [▶]
217 => array:3 [▶]
218 => array:3 [▶]
220 => array:3 [▶]
221 => array:3 [▶]
222 => array:3 [▶]
223 => array:3 [▶]
224 => array:3 [▶]
]
]
134 => array:4 [▶]
394 => array:4 [▶]
454 => array:4 [▶]
]
]
]

Categories