This question already has answers here:
How to Flatten a Multidimensional Array?
(31 answers)
Closed 3 years ago.
I have an eloquent object with data from the model which I need to convert to an array and have all indexes from the relations at the same array depth.
I tried array_flatten(), map(), filter() and other PHP methods but couldn't get it working correctly.
How I get my relations:
$data = Person::whereIn('id', $this->id[0])->where('school_id', '=',
$this->school)->with(['personinfo'=>function ($query) {
$query->select(
'person_id',
'general_info',
);
}, 'trades'=>function ($query) {
$query->select('person_id', 'trade_id')->with('trades');
}, 'measurements'=>function ($query) {
$query->select(
'person_id',
'measuring_point_1',
'measuring_point_1_date',
);
}])->get();
return $data->toArray();
What results in the array below, this is as close as I could get using different methods.
This is the outcome of the return function:
array:3 [
1 => array:17 [
"school_id" => 6
"birth_date" => null
"sex_id" => 1
"phone_number" => 62452676867897
"mobile_number" => 62398356786787
"email" => "example#example.com"
"personinfo" => array:5 [
"person_id" => 21
"general_info" => null
"health_info" => null
]
"trades" => array:3 [
"person_id" => 21
"trade_id" => 2
"trades" => array:8 [
"school_id" => 2
"name" => "blablabla"
]
]
"measurements" => array:7 [
"person_id" => 21
"measuring_point_1" => null
"measuring_point_1_date" => null
]
]
];
I need the array to be like this:
array:3 [
1 => array:17 [
"school_id" => 6
"birth_date" => null
"sex_id" => 1
"phone_number" => 624176676867897
"mobile_number" => 649498356786787
"email" => "example#example.com"
"person_id" => 21
"general_info" => null
"health_info" => null
"person_id" => 21
"trade_id" => 2
"school_id" => 2
"name" => "blablabla"
"person_id" => 21
"measuring_point_1" => null
"measuring_point_1_date" => null
]
]
];
Basically, I need to convert the multidimensional array to a zero depth array.
Any help would be appreciated.
You can use custom of array flatten with merging the inner with array-merge as:
function arrayFlatten($array) {
$res = array();
foreach ($array as $k => $v) {
if (is_array($v)) $return = array_merge($res, array_flatten($v)); // add recursively
else $res[$k] = $v; // just add
}
return $res;
}
Now just return arrayFlatten($data->toArray());
Simple live example
How i made it work using dWinder's answer
$data = Person::whereIn('id', $this->id[0])->where('school_id', '=', $this->school)->with(['personinfo'=>function ($query) {
$query->select(
'person_id',
'general_info',
);
}, 'trades'=>function ($query) {
$query->select('person_id', 'trade_id')->with('trades');
}, 'measurements'=>function ($query) {
$query->select(
'person_id',
'measuring_point_1',
'measuring_point_1_date',
);
}])->get();
function array_flatten($array)
{
$return = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$return = array_merge($return, array_flatten($value));
} else {
$return[$key] = $value;
}
}
return $return;
}
foreach ($data as $value) {
$result[] = array_flatten($value->toArray());
}
return $result;
Related
Am working on some set of PHP array. Am trying to loop through each of them and check
the array whose name is equal to Josw Acade. Am using a for loop but I get zero
after extracting the data. I want to store the data in an array.
Array
array:6 [
0 => array:4 [
"id" => 1
"name" => "Josw Acade"
"value" => "Unlimited"
"plan_type" => "Superior"
]
1 => array:4 [
"id" => 2
"name" => "Verbal"
"value" => "true"
"plan_type" => "Superior"
]
2 => array:4 [
"id" => 12
"name" => "Josw Acade"
"value" => "$1,500,00"
"plan_type" => "Classic"
]
3 => array:4 [
"id" => 13
"name" => "Leon"
"value" => "true"
"plan_type" => "Classic"
]
4 => array:4 [
"id" => 14
"name" => "One Time"
"value" => "true"
"plan_type" => "Classic"
]
5 => array:4 [
"id" => 15
"name" => "Deat"
"value" => "$25,000"
"plan_type" => "Classic"
]
6 => array:4 [
"id" => 23
"name" => "Josw Acade"
"value" => "$100,000"
"plan_type" => "Essential"
]
]
Logic
$Inst = [];
for($med = 0; $med < count($array); $med++){
if($med['name'] == "Josw Acade"){
$Inst = $med['value'];
}
}
dd($Inst);
Your variables is not corretly set in the for loop, you are setting $med = 0 and acessing $med as an array.
Use filter, that runs a condition on each element and returns the items that satisfy that condition.
array_filter($array, function ($item) {
return $item['name'] === 'Josw Acade';
});
In general you don't have to make old school arrays anymore, foreach does the same.
$results = [];
foreach($array as $item)
{
if ($item['name'] === 'Josw Acade') {
$results[] = $item['value'];
}
}
You can use array_filter with callback
$filtered = array_filter($array, function($v){ return $v['name'] == 'Josw Acade'})
print_r($filtered);
You are looping through array; so on each iteration to get values; you need to pass index value and you are missing that. You are using $med as index.
Here is code.
$Inst = [];
for($med = 0; $med < count($array); $med++){
if($array[$med]['name'] == "Josw Acade"){
$Inst[] = $array[$med]['value'];
}
}
there is many way to do this but according to me the best way to use array_filer()
array_filter($array, function ($item) {
return $item['name'] === 'Josw Acade';
});
This question already has answers here:
multidimensional array array_sum
(10 answers)
Closed 5 years ago.
I have the following collection that contains the arrays below:
#items: array:2 [▼
0 => array:13 [▼
"label" => "00000000-N/A"
"views" => 980
"clicks" => 444
"form_submissions_perc" => "100.0"
]
1 => array:13 [▼
"label" => "1111-N/A"
"views" => 323
"clicks" => 1009
"form_submissions_perc" => "100.0"
]
]
I am trying to sum clicks and average views but in my try I get the wrong data:
$sum = 0;
foreach ($data as $k => $subArray) {
foreach ($subArray as $id => $value) {
$sum += $subArray['views'];
}
}
dd($sum);
This was my try to sum but didnt get the right results
Desired output
array:2 [
"views"=> 1303,
"clicks"=> 1451
]
Use $sum as array and get correct value of multiarray:
$sum = array(
'clicks' => 0,
'views' => 0
);
foreach ($data as $id => $value) {
$sum['clicks'] += $value['clicks'];
$sum['views'] += $value['views'];
}
dd($sum);
foreach ($data as $k => $subArray) {
$valueSum[] = $subArray['views'];
$clickSum[] = $subArray['clicks'];
}
echo array_sum($valueSum);
echo array_sum($clickSum);
this is also a clean and easy way .
You can use array_reduce instead
$data = array_reduce($array, function ($old, $new) {
return [
"view" => $old["view"] + $new["view"],
"clicks" => $old["clicks"] + $new["clicks"]
];
}, ["view" => 0, "clicks" => 0]);
print '<pre>';
print_r($data);
$data = [
[
"label" => "00000000-N/A",
"views" => 980,
"clicks" => 444,
"form_submissions_perc" => "100.0"
],
[
"label" => "1111-N/A",
"views" => 323,
"clicks" => 1009,
"form_submissions_perc" => "100.0"
]
];
$result['views'] = array_sum( array_column( $data, 'views' ) );
$result['clicks'] = array_sum( array_column( $data, 'clicks' ) );
dd( $result );
This is the easiest way to do your work.
Result:
Array ( [views] => 1303 [clicks] => 1453 )
For a social media login with Xing, I want to verificate the data send from XING as described in https://dev.xing.com/plugins/login_with/docs#signature-verification
My page sends data as JSON-Array to a PHP function
public function indexAction(Request $request)
{
dump($request->request);
$xingData=\GuzzleHttp\json_decode($request->request->get('xingData'),true);
$xingUser=$xingData['user'];
$xingError=$xingData['error'];
$xingCookie=$request->request->get('xingCookie');
$xingSerialised= $this->flatArray($xingUser);
dump($xingUser);
dump($xingError);
dump($xingCookie);
dump($xingSerialised);
//$xingUserhash=hash_hmac('sha256',$xingSerialised,$this->container->getParameter('xing_salt'));
//dump($xingUserhash);
die(0);
return $this->render('base.html.twig', array(
));
}
function flatArray($fullArray = array())
{
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($fullArray));
$elements = array();
foreach($iterator as $element) {
$elements[] = $iterator->key().$element;
}
return $elements;
}
The JSON-decode-Function makes this array:
XingController.php on line 36:
array:9 [▼
"id" => "MyId"
"first_name" => "MyName"
"last_name" => "MyLastName"
"display_name" => "MyDisplayName"
"active_email" => "my#email.de"
"permalink" => "https://www.xing.com/profile/MyName"
"business_address" => array:4 [▼
"street" => "MyStreet"
"city" => "MyCity"
"province" => "MyProvince"
"country" => "DE"
]
"photo_urls" => array:1 [▼
"maxi_thumb" => "https://www.xing.com/image/image.jpg"
]
"professional_experience" => array:1 [▼
"primary_company" => array:3 [▼
"name" => "MyCompanyName"
"title" => "Inhaber"
"industry" => "CONSUMER_SERVICES"
]
]
]
The problem is, I get
XingController.php on line 39:
array:14 [▼
0 => "idMyId"
1 => "first_nameMyName"
2 => "last_nameMyLastName"
3 => "display_nameMyDisplayName"
4 => "active_emailmy#email.de"
5 => "permalinkhttps://www.xing.com/profile/MyName"
6 => "streetMyStreet"
7 => "cityMyCity"
8 => "provinceMyProvince"
9 => "countryDE"
10 => "maxi_thumbhttps://www.xing.com/image/image.jpg"
11 => "nameMyCompanyName"
12 => "titleInhaber"
13 => "industryCONSUMER_SERVICES"
]
But I wanted the full parents with it, for example:
6 => "business_addressstreetMyStreet"
Thanks for any idea/help!
Try something like:
function flatArray($fullArray = array())
{
$elements = array();
foreach($fullArray as $key => $value) {
if (is_array($value)) {
$elements[] = $this->flatArray($value);
} else {
$elements[] = sprintf('%s%s', $key, $value);
}
}
return $elements;
}
Probably the recursion could be improved
Hope this help
Version with full recursion:
function flatArray($fullArray = array(), $parentkey=null)
{
$elements = array();
foreach($fullArray as $key => $value) {
if (is_array($value)) {
$elements = array_merge($elements, $this->flatArray($value, $parentkey.$key));
} else {
$elements[] = sprintf('%s%s%s', $parentkey, $key, $value);
}
}
return $elements;
}
I have a laravel collection on output, I want to parse it ->toArray()
Collection {#335
#items: array:2 [
"0f39b1e0-a507-11e7-9d6e-33e84951047e" => array:2 [
"total_amount" => 25000
"debt_type" => array:2 [
0 => "car_loan"
1 => "car_loan"
]
]
"0f218520-a507-11e7-b0ba-8554a4ad039b" => array:2 [
"total_amount" => 15000
"debt_type" => array:1 [
0 => "house_loan"
]
]
]
}
is there any way to parse it so I get the following output:
array:1[
0=>[
'debt_id'=>'0f39b1e0-a507-11e7-9d6e-33e84951047e',
'debt_type'=>'car_loan',
'total_amount'=>25000
],
1=>[
'debt_id'=>'0f218520-a507-11e7-b0ba-8554a4ad039b',
'debt_type'=>'house_loan',
'total_amount'=>15000
]
]
what I have tried it works but not sure if its a good way to go around it:
$appDebts = $appDebts->groupBy('debt_type_id')->map(function ($item) {
return [
'total_amount' => $item->sum('amount'),
'debt_type' => $item->map(function ($item) {
return $item->debt_type->slug;
})->toArray(),
];
})->toArray();
if you dd $appDebts you get the collection that I have added on top of the post
$carLoan = [];
$studentLoan = [];
$houseLoan = [];
$cardLoan = [];
foreach ($appDebts as $debt) {
if ($debt['debt_type'][0] === 'car_loan') {
$carLoan['TotalAmount'] = $debt['total_amount'];
$carLoan['LoanType'] = $debt['debt_type'][0];
}
if ($debt['debt_type'][0] === 'house_loan') {
$houseLoan['TotalAmount'] = $debt['total_amount'];
$houseLoan['LoanType'] = $debt['debt_type'][0];
}
if ($debt['debt_type'][0] === 'student_loan') {
$studentLoan['TotalAmount'] = $debt['total_amount'];
$studentLoan['LoanType'] = $debt['debt_type'][0];
}
if ($debt['debt_type'][0] === 'credit_card_loan') {
$cardLoan['TotalAmount'] = $debt['total_amount'];
$cardLoan['LoanType'] = $debt['debt_type'][0];
}
}
Based on the array you shared:
$parsed = $collection->map(function ($item, $id) {
return [
'debt_id' => $id,
'debt_type' => collect($item['debt_type'])->first(),
'total_amount' => $item['total_amount']
];
})->values()->toArray();
With values you remove the key => value, you get the array without keys
Try with this mapping after the first one that you did :
$appDebts = $appDebts->groupBy('debt_type_id')->map(function ($item) {
return [
'total_amount' => $item->sum('amount'),
'debt_type' => $item->map(function ($item) {
return $item->debt_type->slug;
})->toArray(),
];
}); // <-- remove ->toArray() from here
$appDebts = $appDebts->map(function ($item, $key) {
return [
'debt_type_id' => $key
'debt_type' => $item["debt_type"][0], // assuming you want the first type !!
'total_amount' => $item["total_amount"],
];
})->toArray();
PS : This convert the given collection to tha wanted array for more performance tweaking consider editing the SQL query or the logic of getting appDebts
The only thing I can add to #Llopele's answer is to use keyBy() for easier data access:
$parsed = $collection->map(function ($item, $id) {
return [
'debt_id' => $id,
'debt_type' => collect($item['debt_type'])->first(),
'total_amount' => $item['total_amount']
];
})->values()->keyBy('debt_type')->toArray();
So now you can access data like this Arr::get($parsed, 'house_loan');
I have an array issue in here and I'm spending a lot of time with.
I get a list of array like this form
array:4 [
0 => array:20 [▼
"id" => 58
"id_business" =>
"id_branch" =>
"affected_branches" => " " ▶"
"name" => ""
"banner" => ""
"description" => ""
"url" =>
"start_date" => ""
"end_date" => ""
"nr_pages" => 4
"nr_products" => 0
"type" => "global"
"views" => 24
"visible" => "yes"
"delete" => "no"
"user_create_id" =>
"user_modify_id" =>
"created_at" => ""
"updated_at" => "2017-06-07 14:19:23"]
]
by the following code
$data = Offers::whereIn('id_business', $business_id_array)
->where([
'visible' => 'yes',
'delete' => 'no'
])
->where('end_date', '>=', date('Y-m-d h:m:i'))
->orderBy('id', 'desc')->get()
->toArray();
when i try to make a foreach loop for all arrays that came, in this case 4, it does not return me 4 values, but only one.
The loop is:
foreach ($data as $key => $slide)
{
$offers = DB::select('SELECT o.`id`... WHERE o.`id` = ?',[$slide['id']]);
}
return view('...', ['offers' => $offers]);
}
I pass this values in query to get the id of each of arrays
o.`id` = ?',[$slide['id']]
PS: PLS Help Me :)
You're overwriting $offers value with each iteration, so change your code to:
$offers = [];
foreach ($data as $key => $slide) {
$offers[] = DB::select...
}
You need to change $offres in to array
$offers = array();
foreach ($data as $key => $slide)
{
$offers[] = DB::select('SELECT o.`id`... WHERE o.`id` = ?',[$slide['id']]);
}
return view('...', ['offers' => $offers]);