15

How can I replace a sub string with some other string for all items of an array in PHP?

I don't want to use a loop to do it. Is there a predefined function in PHP that does exactly that?

How can I do that on keys of array?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
hd.
  • 17,596
  • 46
  • 115
  • 165
  • 4
    why don't you want to use a loop? sounds more like a whim rather than sensible reason. – Your Common Sense Feb 12 '11 at 08:03
  • @edit: Use `array_flip` before it and after it on the array and leave the other code as is. – NikiC Feb 12 '11 at 08:28
  • Possible duplicate of [String replace all items in array PHP](http://stackoverflow.com/questions/5045101/string-replace-all-items-in-array-php) – J.D. Jun 06 '16 at 22:04
  • 1
    Relevant pages with better clarity: [Replace substring in column values of a 2d array](https://stackoverflow.com/q/30647581/2943403) and changing keys [Recursively change keys in array](https://stackoverflow.com/q/11993613/2943403) – mickmackusa Apr 11 '23 at 03:15
  • 1
    Even "_How can I do that on keys of array?_" is ambiguous. Do you want to change the keys or only change values for specific keys? – mickmackusa Apr 11 '23 at 04:15
  • Does this answer your question? [Replace substring in values of an array with PHP](https://stackoverflow.com/questions/30647581/replace-substring-in-values-of-an-array-with-php) – rubo77 Apr 12 '23 at 18:19

8 Answers8

99

Why not just use str_replace without a loop?

$array = array('foobar', 'foobaz');
$out = str_replace('foo', 'hello', $array);
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • When I try this with a decoded JSON array I get an error `PHP Catchable fatal error: Object of class stdClass could not be converted to string` I am very new to PHP, seems it's difficult to edit an array so far. – Dennis Jan 24 '19 at 08:21
  • @Dennis: `json_decode` returns an object by default, not an array, unless you explicitly specify that you want an array. – netcoder Jan 29 '19 at 20:58
  • This will not work on php 8.1 any more if your array contains more than one dimension, see: https://3v4l.org/VgF8j#v8.1.17 – rubo77 Apr 11 '23 at 14:18
  • @rubo77 well, that's exactly why I've voted to delete this page -- there is no [mcve]. We don't know what data needs to be replaced. There is such a deficit of clarity that answers on this page are solving different problems. It may have high scoring posts, but this page has been sprayed with too many divergent answers -- several which are unexplained -- making this page not helpful for readers and not a good fit for Stack Overflow. – mickmackusa Apr 11 '23 at 20:11
29
$array = array_map(
    function($str) {
        return str_replace('foo', 'bar', $str);
    },
    $array
);

But array_map is just a hidden loop. Why not use a real one?

foreach ($array as &$str) {
    $str = str_replace('foo', 'bar', $str);
}

That's much easier.

NikiC
  • 100,734
  • 37
  • 191
  • 225
  • Ok, I tried the second option, but without & sign before $str and it didn't work. But why & sign, what does the & sign mean in this case? – kv1dr Nov 28 '19 at 18:25
  • The and-sign makes the variable a pointer to reach real array element in the loop – rubo77 Apr 09 '23 at 09:28
7

This is a very good idea that I found and used successfully:

function str_replace_json($search, $replace, $subject) 
{
    return json_decode(str_replace($search, $replace, json_encode($subject)), true);
}

It is good also for multidimensional arrays.

If you change the "true" to "false" then it will return an object instead of an associative array.

Source: Codelinks

  • It wouldn't work if you're trying to replace a bracket `{ ` or `}`. – Max S. Mar 20 '22 at 14:43
  • this works fine on arrays, but if an array contains an element, that is an Object, it will convert the Object into an array – rubo77 Apr 08 '23 at 07:51
  • This answer will mutate any qualifying key and or value. It is also prone to producing invalid json thus breaking the script. – mickmackusa Apr 09 '23 at 12:38
1

I am not sure how efficient this is, but I wanted to replace strings in a big multidimensional array and did not want to loop through all items as the array structure is pretty dynamic.

I first json_encode the array into a string.

Replace all the strings I want (need to use preg_replace if there are non-English characters that get encoded by json_encode).

json_decode to get the array back.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Golu
  • 414
  • 5
  • 16
  • A word of caution to developers who are entertaining this advice: using `str_replace()` or `preg_replace()` on a json-encoded string will make all keys, values, and the json formatting characters vulnerable to mutation. There may be scenarios where this technique is safe, but this generalized advice should not be implemented as a general-use approach. – mickmackusa Apr 11 '23 at 20:28
1
function my_replace_array($array,$key,$val){
    for($i=0;$i<count($array);$i++){
        if(is_array($array[$i])){
            $array[$i] = my_replace_array($array[$i],$key,$val);
        }else{
            $array[$i]=str_replace($key,$val,$array[$i]);
        }
    }
    return $array;
}
Ferhat KOÇER
  • 3,890
  • 1
  • 26
  • 26
0

With array_walk_recursive()

function replace_array_recursive( string $needle, string $replace, array &$haystack ){
    array_walk_recursive($haystack,
        function (&$item, $key, $data){
        $item = str_replace( $data['needle'], $data['replace'], $item );
        return $item;
    },
        [ 'needle' => $needle, 'replace' => $replace ]
    );
}
J.BizMai
  • 2,621
  • 3
  • 25
  • 49
0

There is no predefined function anymore (since PHP 8.1). So this will replace in all elements, even if there are Objects:

<?php

class Arrays {
    /**
     * Replaces in all strings within a multidimensional array, even if objects are included
     * @param  string $search       search for this string
     * @param  string $replace_with replace with this string
     * @param  mixed $haystack        Array or Object to search in all elements
     * @return mixed               gives the same structure back
     */
    public static function replace_everywhere($search, $replace_with, $haystack) {
        if (is_array($haystack) or is_object($haystack)) {
            // Arrays and Objects
            foreach ($haystack as &$value) {
                $value = Arrays::replace_everywhere($search, $replace_with, $value);
            }
            return $haystack;
        } elseif (is_string($haystack)) {
            // replace in a string element
            return str_replace($search, $replace_with, $haystack);
        } else {
            // other datatypes (e.g. integer) stay untouched
            return $haystack;
        }
    }
}


// You can call this like e.g.
$a = array(true, 1, 'foo<bar', 'foo<baz', array("foo<loo"), (object) array('1' => 'foo<boo'));
$a = Arrays::replace_everywhere("<", "&lt;", $a);
var_export($a);

Example: https://3v4l.org/CDGvC#v8.2.5


If you want to replace array keys, I think that's another question with good answers like: recursively-change-keys-in-array

rubo77
  • 19,527
  • 31
  • 134
  • 226
  • Rather vandalizing the question to suit only your answer, you should have asked a new question with a clear [mcve] and self-answered it. – mickmackusa Apr 12 '23 at 02:05
  • Adding a sample input is only a part of a [mcve]. There is no desired output -- so the question remains Unclear (and should not have been reopened). By biasing the input data set to accommodate your answer, you have potentially invalidated earlier posted answers. Foul play. – mickmackusa Apr 12 '23 at 02:20
  • Your are right, I edited the minimal example so that it fits to all answers. – rubo77 Apr 12 '23 at 04:23
  • Btw: I think "vandalizing" is something different. Here I just added am example, so this searchengine-famous question will become more clear what the author obviously intended – rubo77 Apr 12 '23 at 04:28
  • I find this page to be inappropriately famous. It represents some of the very worst questions on the site -- vague requirements, no mcve, no effort, clickbait title. Your answer is now an over-engineered solution that goes beyond calling `str_replace()` on a flat array. In other words, your answer is better suited to a different question. – mickmackusa Apr 12 '23 at 04:30
  • OK, We can close this as duplicate of https://stackoverflow.com/a/75998530. I posted my answer there: https://stackoverflow.com/a/75998530/1069083 – rubo77 Apr 12 '23 at 18:19
  • No, we cannot close this page with that question. That question very clearly wants to call `str_replace()` on one column of a 2d array. This question is far too vague to be closed that way. Please do not deliberately post the same answer in more than one place. – mickmackusa Apr 12 '23 at 20:05
-1
$base = array('citrus' => array( "orange") , 'berries' => array("blackberry", "raspberry"), );
$replacements = array('citrus' => array('pineapple'), 'berries' => array('blueberry'));
$basket = array_replace_recursive($base, $replacements);
$basket = array_replace($base, $replacements);
Matt Ke
  • 3,599
  • 12
  • 30
  • 49
Moon
  • 1
  • This answer is missing its educational explanation. How does it work? In what situations will this technique not work? I know these answers, but researchers won't -- please be more generous with your contribution. The trouble with these old question that do not include sample data is that the scope is open to interpretation. I fear you are stretching the scope beyond the original post, but there is no way of knowing. – mickmackusa Sep 13 '21 at 06:05