1
\$\begingroup\$

Consider the following code.

$car = (object)[
   'general' => [
        'interior' => [
            'seats' => 'destroyed'
        ]
    ]
];

$exteriorProperties = [
    'hood' => 'shiny',
    'windows' => 'dirty'
];

foreach($exteriorProperties as $key => $prop){
    $car->{'other'}->{'exterior'}->{$key} = $prop;
}

This is a scenario where I'd like to add properties to an object, a few layers deep at a time, while iterating through some other data. If it doesn't exist, it will just create it, if it does it will override. PERFECT!

Unfortunately, this will throw the warning:

Creating default object from empty value

I could resolve the issue by checking first if the property exists like so:

foreach($exteriorProperties as $key => $prop){
    if(!isset($car->other))
        $car->other = (object)[];
    if(!isset($car->other->exterior))
        $car->other->exterior = (object)[];
    $car->other->exterior->{$key} = $prop;
}

This is not my ideal solution. I'm wondering if there's a more elegant solution. Currently, I'm using this:

@$car->{'other'}->{'exterior'}->{$key} = $prop;

to suppress the warnings but I'm worried about compatibility in the future.

Does anyone have a more elegant solution to this scenario?

\$\endgroup\$
  • \$\begingroup\$ Don't use arrays as the answer below suggest, use object properly. Arrays are only good for local code, shared outside a file or class means you are writing keys manually, having to remember them, miss one or two, typo. Good IDE with auto complete and objects with getter/setter are a happy dev world. \$\endgroup\$ – James Sep 12 at 0:02
1
\$\begingroup\$

Yes, use arrays.

$car = [
   'general' => [
        'interior' => [
            'seats' => 'destroyed'
        ]
    ]
];

$exteriorProperties = [
    'hood' => 'shiny',
    'windows' => 'dirty'
];

foreach($exteriorProperties as $key => $prop){
    $car['other']['exterior'][$key] = $prop;
}
$car = (object) $car;

Anyway, the object conversion will only convert the outermost array. The nested arrays are still arrays.

\is_array($car->general); // true

Why you need it to be shapeless objects anyway? Either define classes for those objects or treat them as arrays is the simple answer.

Btw $car->{'other'} is really weird way of writing $car->other...

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I suppose you're right, I just hate getting locked into arrays all the time. The $car->{'other'} is because most of my property keys are coming from string variables. such as $car->{$var1}->{$var2} \$\endgroup\$ – Rager Nov 13 '19 at 20:42
1
\$\begingroup\$

Yes, you can avoid the iterated conditional operations by processing all data as arrays.

Code: (Demo)

$car = json_decode(
    json_encode(
        array_replace_recursive(
            (array)$car, 
            ['other' => ['exterior' => $exteriorProperties]]
        )
    )
);

When only coverting the top level from object-type to array-type you can just cast it with (array). If you need to convert all levels -- json encode the whole object, then decode that string to an array. When you are done processing, use json_ functions to revert the data to object-type.

I still find this a little clunky (perhaps just as clunky as your conditional approach). The benefit in the above is in the recursion; if your data depth changes, you won't need to alter the processing script. Ask yourself if you actually need to use an object. If coding is simplified with a different data-type, perhaps have a rethink/refactor.

P.s. DEFINITELY don't write the stfu operator (@) into your code. In nearly all implementations, the technique is avoidable (this is one of those cases) and projects with such syntax are categorized/presumed as low quality by knowledgeable developers.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks, good assessment. I unfortunately could not choose anything but objects since a previous programmer has coded it as such. \$\endgroup\$ – Rager Nov 13 '19 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.