I would like to propose a new native utility function: str_mask().
The Problem:
Developers frequently need to mask sensitive information (like phone
numbers, email addresses, or token IDs) before displaying them or
logging them. Currently, this is achieved in userland using various
combinations of substr(), str_repeat(), or preg_replace(). These
implementations are often error-prone, especially when dealing with
multibyte character encodings.
The Proposal:
I am suggesting a simple, native helper:
str_mask(string $string, int $start, int $length, string $mask_char =
'*'): string
Why native?
Consistency: Providing a reliable, standard way to mask strings across projects.
Multibyte Support: Unlike custom userland implementations that might
break on non-Latin strings (like Persian/Arabic/CJK), a native
implementation can seamlessly handle multibyte characters.
I have a draft implementation ready for review. I would appreciate
feedback on whether this utility fits within the scope of the PHP
core, or if there are specific concerns regarding such an addition.
On 18 June 2026 17:13:59 BST, "سپهر محمودی" <sepehrphpr@gmail.com> wrote:
Hi everyone,
I would like to propose a new native utility function: str_mask().
I can definitely see the use case for this function - in fact, I was just reviewing a change which could have used it.
Multibyte Support: Unlike custom userland implementations that might
break on non-Latin strings (like Persian/Arabic/CJK), a native
implementation can seamlessly handle multibyte characters.
As a rule, PHP's str_* functions operate on byte strings with no knowledge of encoding. Multibyte support would belong in the mbstring or intl extensions, which have conventions for specifying the encoding in use.
In fact, a correct Unicode implementation would need to operate on "graphemes", using the bindings to ICU in the intl extension. Otherwise, it would incorrectly handle things like combining diacritics and emoji variation selectors.
On 18 June 2026 17:13:59 BST, "سپهر محمودی" <sepehrphpr@gmail.com> wrote:
>Hi everyone,
>
>I would like to propose a new native utility function: str_mask().
I can definitely see the use case for this function - in fact, I was just reviewing a change which could have used it.
>Multibyte Support: Unlike custom userland implementations that might
>break on non-Latin strings (like Persian/Arabic/CJK), a native
>implementation can seamlessly handle multibyte characters.
As a rule, PHP's str_* functions operate on byte strings with no knowledge of encoding. Multibyte support would belong in the mbstring or intl extensions, which have conventions for specifying the encoding in use.
In fact, a correct Unicode implementation would need to operate on "graphemes", using the bindings to ICU in the intl extension. Otherwise, it would incorrectly handle things like combining diacritics and emoji variation selectors.
Rowan Tommins
[IMSoP]
Hi, Sepehr, Rowan and Internals
I'm interesting your idea.
I agree that Rowan say mbstring or grapheme function.
For example, number is not only ASCII. One of Full Width number:
0123456789(U+FF19 - U+FF19).
There is Japanese number in Kanji (一,二,三,四,五,六,七,八,九)
Therefore, your proposal are useful but I suggest to move to grapheme* function.
(mbstring is not accept from nearly)
You may like to demonstrate a few existing approaches which are prone to breakage. 3v4l.org/36DtC
You might like to expose framework implementations and how your proposal aligns/differs from their implementations.
Points of clarification…
When obfuscating/redacting, sometimes I intentionally avoid a one-to-one replacement of characters. Might your function somehow offer that flexibility? stackoverflow.com/questions/43762251
What happens if the number of targeted characters in the input string is fewer than the range that the offset and length parameters represent? Will the input string increase in length or stay the same multibyte length?