How do I convert eloquent object to a zero depth array? [duplicate] - php

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

Getting zero when extracting data from a PHP array in Laravel app

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

How to sum and count specific keys in a multidimensional array [duplicate]

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 )

Flat Array with full parents (PHP, Symfony 3)

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

How to parse a laravel collection

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

Array data issue Laravel

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]);

Categories