0

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.

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++;
    
}
3
  • 1
    If you don't have a predefined list of all the keys to be met withing your objects, i don't see another way to collect them other than just.. you know, collect them. Commented Mar 10, 2022 at 15:29
  • Since your end-goal is to create CSV, why not just use your existing method to collect the keys? Then to create the rows of the CSV, check for the existence of each key in your objects. If exists, use that data. If not, empty string. Commented Mar 10, 2022 at 15:54
  • Just ran your edited code. Got "Trying to get property ... of non-object". Commented Mar 10, 2022 at 16:27

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.