In general the function is called strtr():
strtr($string, $from, $to);
In this form with three parameters: $string
will be translated and the return value is the translated string.
Here $from
and $to
contain the bytes to translate from -> to, so both strings should be of equal byte-size (cf. strlen()).
$secret = strtr(
$plain,
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
'hijklmnopqrstuvwxyzabcdefgHIJKLMNOPQRSTUVWXYZABCDEFG',
);
Now what is different with that function compared to the perl translation operator is that you don’t have the inner short forms a-z
for 26 bytes.
For this you can use the range() function that also works with bytes (characters), however it returns an array then you can implode or make use of strtr() with two parameters only where the second parameter is an array.
$string = "hello, world!\n";
$from = range('a', 'z');
$to = [...range('h', 'z'), ...range('a', 'g')];
echo strtr($string, array_combine($from, $to)); // olssv, dvysk!
This second form with the array has the additional benefit that you can replace multiple bytes, also of various length (e.g. UTF-8). But NOTE though, range() is not compatible with that, from the manual:
If start or end is a non-numeric string with more than one byte, an E_WARNING is emitted.
See the manual pages for all the details:
Found no elephant PHP code-format-er and didn’t want to search deep, here is the function that can operate on the pattern as string as described above:
$string = "hello, world!\n";
$fn = fn(string $string, string $pattern) => strtr(
$string,
array_combine(
...array_map(fn(string $ranges) => array_merge(
...array_map(fn(string $range) => range(
...sscanf($range, '%[^-]-%[^-]')), str_split($ranges, 3))),
sscanf($pattern, 'tr/%[^/]/%[^/]/'))));
echo $fn($string, 'tr/a-zA-Z/h-za-gH-ZA-G/'); // olss, dvysk!
While we have Perl compatible regular expressions (PCRE) in PHP, this example is not using any of the preg_*() functions.