Skip to main content

Replace by map

There are cases when you have to use more than one replacement (so with() won't work), but you also don't need Detail details or any replacement logic, really (so callback() is a little too much).

Standard map#

You can use replace()->all()->by()->map() to replace a matched, predefined value ("mp3", "mp4" or "gif") by its direct counter-part ('Audio file', 'Video file', 'Animation'):

$message = 'My words: "mp3", "mp4", "gif"';
pattern('\b\w{3}\b')->replace($message)->all()->by()->map([
'mp3' => 'Audio file',
'mp4' => 'Video file',
'gif' => 'Animation'
]);
My words: "Audio file", "Video file", "Animation"

Here, we used replace()->all() as an example, but of course replace()->first() and replace()->only(int) could be used and would replace only the first, or the first few matches.

Undefined mapping#

Normally, had you matched a string that's not present in your map, a MissingReplacementKeyException would be thrown:

$message = 'My words: "mp3", "mp4", "xxx"';
pattern('\w{3}')->replace($message)->all()->by()->map([
'mp3' => 'Audio file',
'mp4' => 'Video file',
'gif' => 'Animation'
]);

MissingReplacementKeyException is a safe-guard, since map() is supposed to be only used with a predefined set of expected matches, and if a different string is matched (like "xxx"), that's a heads up that perhaps something went wrong. Either the map was incomplete, or the pattern allowed some unexpected values.

Ignored replacements#

On the other hand, if you want to ignore unexpected values - use mapIfExists().

With mapIfExists(), superfluous occurrences are left unchanged:

$message = "Extensions: mp3, mp4, jpg, jpeg, png, gif";
pattern('\b\w{3,4}\b')->replace($message)->all()->by()->mapIfExists([
'mp3' => 'Audio',
'gif' => 'Animation'
]);
Extensions: Audio, mp4, jpg, jpeg, png, Animation

Groups#

Resolving a replacement based on a whole match however, is both uncommon and unpractical. It's much more elastic to resolve it based on a specific capturing group, using by()->group()->map().

Remember, that groups can be matched or not matched, so we need to specify how to handle an unmatched group. In this case, we'll use orElseThrow(), since we don't expect the group to ever be unmatched.

$links = 'Links: www.google.com, http://socket.io, facebook.com, https://t-regx.com';
pattern('(https?://)?(www\.)?(?<domain>[\w-]+)\.(com|io)')
->replace($links)
->all()
->by()
->group('domain')
->map([
'google' => 'Search Engine',
'socket' => 'Documentation',
'facebook' => 'Social Portal',
't-regx' => 'Documentation',
])
->orElseThrow();
Links: Search Engine, Documentation, Social Portal, Documentation
Last updated on