2

I have a PHP object that I need to change the key name of in a foreach loop:

stdClass Object
(
   [first-name] => NAME
   [last-name] => NAME
   [phone-number] => NUMBER
   ...
)

I need to replace the dash '-' to a underscore '_' within a foreach so it looks like this:

stdClass Object
(
   [first_name] => NAME
   [last_name] => NAME
   [phone_number] => NUMBER
   ...
)

I found this post: PHP - How to rename an object property? which does tell me how to do it, the problem is that when I use unset() inside of the foreach it unsets all of the keys instead of just the ones I want it to.

Here's my code:

foreach ($customer as $key => $value) {
    $key2 = str_replace('-', '_', $key);
    $customer->$key2 = $customer->$key;            
    unset($customer->$key);
}

which returns an empty object:

stdClass Object
(
)

How can I unset the original keys without affecting the new ones?

3
  • $customer = json_decode(str_replace('-', '_', json_encode($customer))); 3v4l.org/aaXG0 | Good if you're sure that values don't contain dashes. :) Commented Nov 20, 2022 at 16:57
  • @OMiShah: Well even if you're sure today, I would not suggest to run this on data which may change over time. OP clearly only wants to map the keys and side effects on data is part of the question already, therefore ... NO (, not sorry :) ). Commented Nov 20, 2022 at 17:18
  • @hakre: Yes, you're right, sir ;) Commented Nov 20, 2022 at 17:19

2 Answers 2

2

There is a simple trick you can do in general and that is only doing the operation if there is a change:

    $key2 = str_replace('-', '_', $key);
    if ($key2 !== $key) {
        $customer->$key2 = $customer->$key;            
        unset($customer->$key);
    }

You just do nothing if the operation has already been done (by the outcome).

Within a foreach this can be further "tweaked" by making use of the continue keyword and inversing the comparison:

foreach ($customer as $key => $value) {
    $key2 = str_replace('-', '_', $key);
    if ($key2 === $key) {
        continue; // nothing to do
    }
    $customer->$key2 = $customer->$key;            
    unset($customer->$key);
}

But at the end of the day you only don't want to delete which equals to always set (which works if you unset first and iterate on a clone):

foreach (clone $customer as $key => $value) {
    $key2 = str_replace('-', '_', $key);
    unset($customer->$key);
    $customer->$key2 = $value;
}

So choose your weapon, there are even more ways to skin this cat, this just for inspiration. At the end of the day the order of the operations (adding, deleting etc.) is the "key" point.

All examples on 3v4l.org.

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

8 Comments

Can you please test your code? It doesn't seem to work.
@KIKOSoftware: That's unfortunate as its perhaps pseudo code continued from the question. Which one specifically you'd like to see under test? Just so that I can add an online example on 3v4l.org.
You can use my 3v4l example to test your code.
@ChristopherAnsbaugh: It did before the edit, yes. That is because foreach'ing the same instance (the one that is modified while iterating, SO reference Q&A), a clone resolves this easily. It requires to unset first IMHO due to how $customer->key on the original may have gone away due to earlier iterations and str_replace resulting in a same key by accident.
Cloning is a smart idea.
|
1

You code almost seems to work, but its a bad idea to work on an object you're looping through. The solution is get_object_vars() which can get the properties before you loop:

foreach (get_object_vars($customer) as $key => $value) {
    $key2 = str_replace('-', '_', $key);
    $customer->$key2 = $customer->$key;            
    unset($customer->$key);
}

See: https://3v4l.org/sfZq3

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.