I have an array of objects that I'm converting to a CSV file for export. My problem is, that the objects are not identical in terms of keys. Some contain more than others.
My array of objects could look like this:
Array
(
[0] => stdClass Object
(
[Type] => Company
[Address] => My Address
[Zip] => 1234
[City] => Cityname
)
[1] => stdClass Object
(
[Type] => Private
[Status] => Inactive
)
)
How can I convert an array of objects so each object would contain all possible "keys" even though they are empty, e.g. like this for the above example:
Array
(
[0] => stdClass Object
(
[Type] => Company
[Address] => My Address
[Zip] => 1234
[City] => Cityname
[Status] =>
)
[1] => stdClass Object
(
[Type] => Private
[Address] =>
[Zip] =>
[City] =>
[Status] => Inactive
)
)
I think I would have to get all keys first and then some sort of mapping into them for each object. My hope is, there's some clever way to do this, but I'm totally lost here. Any help is greatly appreciated.
Edit: I have collected all my keys in a $headers array and mapped all data to the new array of objects. Not sure if this is the most elegant way, but it works.
$records = json_decode($records);
$headers = array();
foreach ($records as $object) {
foreach ($object as $key => $value) {
$headers[] = $key;
}
}
$headers = array_unique($headers);
$export = array();
$i = 0;
foreach ($records as $object) {
$newObject = new stdClass();
foreach ($headers as $key) {
$newObject->$key = $object->$key;
}
$export[$i] = $newObject;
$i ;
}
CodePudding user response:
This is a bit long winded but will achieve the requirement. Documentation as comments so I hope you understand what going on :)
$original = [
(Object)[ 'Type' => 'Company', 'Address' => 'My Address', 'Zip' => '1234', 'City' => 'Cityname'],
(Object)[ 'Type' => 'Company', 'Address' => 'My Address']
];
$all_props = [];
# process all the inputs to make sure you
# have a complete list of possible properties
foreach ($original as $objects){
foreach ($objects as $prop_name => $val){
if ( ! in_array($prop_name, $all_props) ) {
$all_props[$prop_name] = '';
}
}
}
# convert the array to an object
$all_obj = (object)$all_props;
# now process the inputs to create a new array of objects
# using the all_obj as a base
foreach ( $original as $obj){
$new = clone $all_obj;
foreach ($obj as $prop=>$val){
$new->{$prop} = $val;
}
$new_complete[] = $new;
}
print_r($new_complete);
RESULT
PHP 8.1.3
Array
(
[0] => stdClass Object
(
[Type] => Company
[Address] => My Address
[Zip] => 1234
[City] => Cityname
)
[1] => stdClass Object
(
[Type] => Company
[Address] => My Address
[Zip] =>
[City] =>
)
)
CodePudding user response:
You can perform the merge with array_merge
(after converting the object to array) and then convert that back to object:
foreach ($csv as $object) {
foreach ($object as $key => $value) {
$headers[$key] = null;
}
}
foreach ($csv as $object) {
$result[] = (object) array_merge($headers, (array) $object);
}
$result
will then have the desired structure.
CodePudding user response:
consider array_map , @ and you can get this:
<?php
$yep = [
(Object)[ 'Type' => 'Company', 'Address' => 'My Address', 'Zip' => '1234', 'City' => 'Cityname'],
(Object)[ 'Type' => 'Company2', 'Address' => 'My Address', 'Status' => 'i am lame']
];//this part is 'taken' from RiggsFolly-friend's example 'cause i'm too lame to write it by myself
function small_code($v){
//var_dump($v->Type);
return ['Type' => (@$v->Type??null) , 'Address' =>(@$v->Address??null), 'Zip' =>(@$v->Zip??null), 'City' =>(@$v->City??null) , 'Status' =>(@$v->Status??null) ];
}
var_dump(array_map('small_code',$yep) );
?>
lol