در تاریخ یکشنبه ۲۰ سپتامبر ۲۰۲۶، ۰۴:۴۳ Pratik Bhujel <
[email protected]> نوشت:

> Hi Sepehr,
>
> Thanks. I think we may be talking past each other slightly.
>
> When I see major frameworks like CakePHP having to implement custom
> utility functions for simple tasks like string masking, it suggests that we
> are reinventing the wheel.
>
> That shows that masking is a real use case, which I don’t dispute. What
> I’m still missing is evidence that this *specific primitive* is what
> those projects are repeatedly reinventing.
>
> If CakePHP is part of the motivation, I think the strongest evidence would
> be to show an actual CakePHP implementation/use case that could be replaced
> by:
>
> str_mask(string, mask_char, offset, length)
>
> without changing its semantics. Even better would be a small prior-art
> section with several independent libraries/frameworks converging on roughly
> the same operation.
>
> Otherwise, “frameworks implement masking” establishes the problem, but not
> necessarily this particular API as the abstraction PHP core should
> standardize.
>
> The evidence for my point is available in my RFC.
>
> I did read it. My concern is exactly the distinction above: evidence that
> masking exists is different from evidence that this API is the common
> missing primitive.
>
> Assuming the recent semantic issues have now been addressed, this is the
> part I would focus on before implementation-level optimization. A concrete
> before/after from the cited real-world code would make the case much easier
> to evaluate.
>
> Best regards,
> Pratik Bhujel
>
> On Sat, 19 Sep 2026 20:53:50 +0330, “سپهر محمودی” [email protected]
> wrote:
>
> در تاریخ شنبه ۱۹ سپتامبر ۲۰۲۶، ۱۵:۲۰ Pratik Bhujel
> [email protected] نوشت:
>
> Hi Sepehr,
>
> I don’t think benchmarks actually answer the main objection being raised
> here. They can show that a dedicated C implementation is faster than
> composing substr_replace() and str_repeat(), but they cannot show that this
> operation deserves a permanent core API.
>
> Before optimizing it, I’d rather see evidence that the abstraction itself
> is common: for example, a corpus analysis of real PHP
> applications/frameworks showing how often this exact offset/length masking
> pattern occurs and what existing implementations look like. Otherwise we
> may just be benchmarking a convenience wrapper.
>
> Also, the current RFC still documents out-of-bounds offsets as returning
> the original string unchanged, despite your reply saying it was changed to
> fail-closed, and it still says a multi-byte $mask_char is silently reduced
> to its first byte. Those semantics should probably be made consistent first.
>
> And Jordi’s #[SensitiveParameter] point seems especially relevant if
> handling sensitive data is the primary motivation.
>
> So I think the order should be: demonstrate the use-case, settle the
> contract, then benchmark the implementation.
>
> Best regards,
>
> Pratik Bhujel
>
> Hi Pratik,
>
> Thank you for your feedback and for taking the time to review my proposal.
>
> You make some very valid points regarding optimization. I completely agree
> with you that performance within the PHP core is critical and must meet the
> highest standards.
>
> My main motivation for this RFC is to address a practical need in
> real-world scenarios. When I see major frameworks like CakePHP having to
> implement custom utility functions for simple tasks like string masking, it
> suggests that we are reinventing the wheel. Standardizing this capability
> within the PHP core would be a significant benefit to the entire ecosystem.
>
> I would be very happy to hear your specific thoughts on the
> implementation. If you have any suggestions on how I can improve the
> proposal or address your concerns, I am very open to that discussion.
>
> The evidence for my point is available in my RFC.
>
> Looking forward to hearing from you.
>
> Best regards,
>
> Sepehr
>
> ----------

Hi Pratik,

Fair point! I see what you mean now. You're completely right that just
showing "masking is needed" isn't enough—I need to show why this specific
`(string, mask_char, offset, length)` signature is the right primitive to
standardize.

To answer that directly:

When people build custom masking logic today, almost everyone lands on
composing `substr_replace()`, `str_repeat()`, and `strlen()`:

// What people write today:
$masked = substr_replace(
    $pan,
    str_repeat('*', $length ?? (strlen($pan) - $offset)),
    $offset,
    $length ?? (strlen($pan) - $offset)
);

// What str_mask replaces it with:
$masked = str_mask($pan, '*', $offset, $length);

They end up using these exact parameters because offset and length are
already the standard way PHP handles string slicing (like in `substr` and
`substr_replace`).

Other frameworks and internal tools (like Laravel's `Str::mask`) also
converge on this exact signature because it's the most natural fit for
PHP's existing conventions.

The big difference with making this a core primitive isn't just saving a
line of code—it's getting fail-closed error handling (throwing `ValueError`
instead of silently messing up or leaking data), built-in
`#[SensitiveParameter]` protection, and avoiding temporary string
allocations in memory.

I've updated the RFC with a quick Before/After comparison to make this
clearer.

Appreciate the feedback, it really helped sharpen the focus!

Cheers,
Sepehr

Reply via email to