Warning: Only the first byte will be assigned to the string offset

13.8k views Asked by At

The following code was working just fine in PHP 7 so why am I seeing this warning in PHP 8?

$str = 'xy';
$str[0] = 'bc';
2

There are 2 answers

0
Rain On BEST ANSWER

As of PHP 8 trying to replace a string offset with more than one byte using square array brackets style will emit a warning.

So you just need to remove the extra byte (c in this case)

$str = 'xy';
$str[0] = 'b';

Or if you really want to replace x with bc you can use substr_replace

$str = 'xy';
var_dump(substr_replace($str, 'bc', 0, 1)); // output: string(2) "bcy"

Note: this function accepts byte offsets, not code point offsets.

0
JSowa On

Actually code works the same as in PHP 7.4. The only difference is that now it throws Warning.

$str = 'xy';
$str[0] = 'bc';

var_dump($str); // string(2) "by"
var_dump(phpversion()); // string(6) "7.4.10"

PHP 8

var_dump($str); // string(2) "by"
var_dump(phpversion()); // string(10) "8.0.0beta4"

As PHP documentation says:

Internally, PHP strings are byte arrays. As a result, accessing or modifying a string using array brackets is not multi-byte safe, and should only be done with strings that are in a single-byte encoding such as ISO-8859-1.

If you want to insert all bytes from replacement string in a destination string you can use:

$str = 'xy';

function chars_replace(string $str, string $replacement, int $indexAt)
{
    return substr_replace($str, $replacement, $indexAt, $indexAt + strlen($replacement));
}

var_dump(chars_replace($str, 'bc', 0)); // string(2) "bc"

However it will not work with multibyte encoding.

If you want to replace only one char then you can use:

$str = 'xy';
$str[0] = substr('bc', 0, 1);

var_dump($str); // string(2) "by"