# RFC Posted for str_begins and str_ends functions

- Thread: https://externals.io/message/94787
- Original archive: https://news-web.php.net/php.internals/94787
- Started by will@wkhudgins.info on 2016-08-01T22:52:50+00:00
- Messages: 52
- RFC: Add str_starts_with(), str_ends_with() and related functions (Declined) — https://externals.io/rfc/add_str_begin_and_end_functions.md
- Page 1 of 3: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/94787.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #94787 — will@wkhudgins.info — 2016-08-01T22:52:50+00:00

URL: https://externals.io/message/94787#94787

Hello,

I recently emailed the group about submitting an RFC for str_begins() 
and str_ends() functions. The RFC has now been officially submitted and 
is viewable at:

https://wiki.php.net/rfc/add_str_begin_and_end_functions

The github PR may be found at:

https://github.com/php/php-src/pull/2049

Hope to be hearing about this,

Will

---

## #94788 — Sara Golemon — 2016-08-01T22:56:43+00:00

URL: https://externals.io/message/94787#94788 · In reply to: #94787

> I recently emailed the group about submitting an RFC for str_begins() and
> str_ends() functions. The RFC has now been officially submitted and is
> viewable at:
>
> https://wiki.php.net/rfc/add_str_begin_and_end_functions
>
Feeling "meh" on it (neither for nor against), but I would consider
consistency with other str*() functions by making case-insensitivity
live in separate functions rather than as a parameter. e.g.
str_begins(), str_ibegins(), str_ends(), end_iends()

-Sara

---

## #94790 — Yasuo Ohgaki — 2016-08-02T00:06:08+00:00

URL: https://externals.io/message/94787#94790 · In reply to: #94788

> 
> > […]
> Feeling "meh" on it (neither for nor against), but I would consider
> consistency with other str*() functions by making case-insensitivity
> live in separate functions rather than as a parameter. e.g.
> str_begins(), str_ibegins(), str_ends(), end_iends()

+1 for having functions for case insensitivity.
I'm not sure if we should have "s". i.e. str_begin"s".

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #94792 — David Rodrigues — 2016-08-02T01:36:33+00:00

URL: https://externals.io/message/94787#94792 · In reply to: #94790

Sara Golemon wrote:
> Feeling "meh" on it (neither for nor against), but I would consider
> consistency with other str*() functions by making case-insensitivity
> live in separate functions rather than as a parameter. e.g.
> str_begins(), str_ibegins(), str_ends(), end_iends()

I guess that "i" isn't appliable when it have slashes.
In this case, functions should be: strbegins, stribegins, strends, striends.
In all case, I think that is better a third parameter and keep underlined.



Yasuo Ohgaki wrote:
> +1 for having functions for case insensitivity.
> I'm not sure if we should have "s". i.e. str_begin"s".

I think that "s" is good here.
Sounds better for me, but I don't know if it is right in english.
In JS, for instance, we have startsWith. It have a "s" too.

2016-08-01 21:06 GMT-03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> 
> > […]
>
> +1 for having functions for case insensitivity.
> I'm not sure if we should have "s". i.e. str_begin"s".
>
> Regards,
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net
>
> --
> 
> 
>



-- 
David Rodrigues

---

## #94806 — Yasuo Ohgaki — 2016-08-02T22:44:29+00:00

URL: https://externals.io/message/94787#94806 · In reply to: #94792

Hi David,


> Sara Golemon wrote:
> > […]
>
> I guess that "i" isn't appliable when it have slashes.
> In this case, functions should be: strbegins, stribegins, strends, striends.
> In all case, I think that is better a third parameter and keep underlined.

This is difficult issue.
String function names are inconsistent currently.
It is better to stick to CODING_STANDARDS naming convention for new
function names. Therefore, new string functions are better to be named
str_*() unless they are too strange.

e.g.
http://php.net/manual/en/function.str-replace.php
http://php.net/manual/en/function.str-ireplace.php

I would like to fix function name inconsistencies by having aliases in
near future.
https://wiki.php.net/rfc/consistent_function_names

It might be okay  to have "s" in function names, but if we want to be
consistent,

str_replace -> str_replaces
str_ireplace -> str_ireplaces

IMO, following names are better for consistency.

str_begin
str_ibegin
str_end
str_iend

In addition, `str_replace()` has seach_value at first, so signature might be

boolean str_begin(string $search_value, string $str, [boolean
$case_sensitive = true])
boolean str_end(string $search_value, string $str, string
$search_value [boolean $case_sensitive = true])

However, `strstr()` (and other str functions without "_". e.g.
strpos/stripos/strrpos/strripos) has search_value as the 2nd
parameter. If we follow this format, current signature is fine.

It may be better sort out and fix consistency issues first, then add
new functions. Otherwise, we may introduce more consistency issues.

Regards,

BTW, having "i" is more readable.

str_ibegin("searchthis", $str);
is more readable than
str_begin("seachthis", $str, TRUE);
as programmer does not have to know that's the `TRUE` means.
It's small thing, but small things add up.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #94807 — Rowan Collins — 2016-08-02T22:53:08+00:00

URL: https://externals.io/message/94787#94807 · In reply to: #94806

> It might be okay  to have "s" in function names, but if we want to be
> consistent,
>
> str_replace -> str_replaces
> str_ireplace -> str_ireplaces
>
> IMO, following names are better for consistency.
>
> str_begin
> str_ibegin
> str_end
> str_iend

I think those names mean something different: "str_begin" sounds like an 
imperative "make this string begin with X"; "str_begins" is more of an 
assertion "the string begins with X". Ruby would spell it with a ? at 
the end. It's also the same form, grammatically, as the common "isFoo".

Note that this logic holds for "str_replace", which *is* an imperative - 
you are not saying "tell me if X replaces Y", you are saying "please 
replace X with Y".

Regards,

-- 
Rowan Collins
[IMSoP]

---

## #94808 — will@wkhudgins.info — 2016-08-03T01:15:42+00:00

URL: https://externals.io/message/94787#94808 · In reply to: #94806

> Hi David,
> 
> On Tue, Aug 2, 2016 at 10:36 AM, David Rodrigues 
> <david.proweb@gmail.com> wrote:
> > […]
> 
> This is difficult issue.
> String function names are inconsistent currently.
> It is better to stick to CODING_STANDARDS naming convention for new
> function names. Therefore, new string functions are better to be named
> str_*() unless they are too strange.
> 
> e.g.
> http://php.net/manual/en/function.str-replace.php
> http://php.net/manual/en/function.str-ireplace.php
> 
> I would like to fix function name inconsistencies by having aliases in
> near future.
> https://wiki.php.net/rfc/consistent_function_names
> 
> It might be okay  to have "s" in function names, but if we want to be
> consistent,
> 
> str_replace -> str_replaces
> str_ireplace -> str_ireplaces
> 
> IMO, following names are better for consistency.
> 
> str_begin
> str_ibegin
> str_end
> str_iend
> 
> In addition, `str_replace()` has seach_value at first, so signature might 
> be
> 
> boolean str_begin(string $search_value, string $str, [boolean
> $case_sensitive = true])
> boolean str_end(string $search_value, string $str, string
> $search_value [boolean $case_sensitive = true])
> 
> However, `strstr()` (and other str functions without "_". e.g.
> strpos/stripos/strrpos/strripos) has search_value as the 2nd
> parameter. If we follow this format, current signature is fine.
> 
> It may be better sort out and fix consistency issues first, then add
> new functions. Otherwise, we may introduce more consistency issues.
> 
> Regards,
> 
> BTW, having "i" is more readable.
> 
> str_ibegin("searchthis", $str);
> is more readable than
> str_begin("seachthis", $str, TRUE);
> as programmer does not have to know that's the `TRUE` means.
> It's small thing, but small things add up.
> 
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

Everyone has raised important considerations. For me, the most important 
thing is maintaining consistency with the existing PHP string library. I 
do not want these functions to feel "tacked" on, as if they were 
haphazardly added to PHP. If these functions are added to the language, 
it should feel as if they have always been a part of the language (even 
if they haven't been). This consistency is important in order to ensure 
these functions ADD to PHP instead of just cluttering it up.

Having separate functions for case sensitivity makes sense, that is much 
more consistent with the existing string library. I think the proposal 
should be amended to separate those two functionalities. I think like 
having an "s" at the end of the function names reads better, but 
omitting the "s" fits better with the existing function names and does 
not read bad. Therefore, I am in favor of dropping the "s".

As far as str_begin vs strbegin, I think str_begin is more readable. 
Therefore, I think it would be better to implement:

boolean str_begin(string $search_value, string $str)
boolean str_ibegin(string $search_value, string $str)
boolean str_end(string $search_value, string $str)
boolean str_iend(string $search_value, string $str)

This is much more consistent with the existing string library.

Regards,

Will

---

## #94809 — Yasuo Ohgaki — 2016-08-03T03:02:58+00:00

URL: https://externals.io/message/94787#94809 · In reply to: #94806

> as programmer does not have to know that's the `TRUE` means.

s/that's/what's/

I shouldn't write mails while writing code :(

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #94813 — lauri.kentta@gmail.com — 2016-08-03T07:59:24+00:00

URL: https://externals.io/message/94787#94813 · In reply to: #94787

Hello,

I only saw you mention strpos, preg_match and substr as (slower) 
alternatives. However, there's already a function called substr_compare 
which is meant for just this kind of comparisons but which is more 
general than your RFC.

function str_begins($a, $b) {
   return substr_compare($a, $b, 0, strlen($b)) === 0;
}
function str_ends($a, $b) {
   return substr_compare($a, $b, -strlen($b)) === 0;
}

-- 
Lauri Kenttä

---

## #94814 — Christoph Becker — 2016-08-03T09:23:03+00:00

URL: https://externals.io/message/94787#94814 · In reply to: #94813

> I only saw you mention strpos, preg_match and substr as (slower)
> alternatives. However, there's already a function called substr_compare
> which is meant for just this kind of comparisons but which is more
> general than your RFC.

Thanks for pointing out `substr_compare()`, of which I even have not been
aware of.  And indeed, `substr_compare()` is perfectly suitable to verify
whether a string starts or ends with a certain substring, so, in my
opinion, there is no need for the other functions to be added to
ext/standard.

-- 
Christoph M. Becker

---

## #94822 — Stanislav Malyshev — 2016-08-04T05:50:16+00:00

URL: https://externals.io/message/94787#94822 · In reply to: #94792

Hi!

> I guess that "i" isn't appliable when it have slashes.
> In this case, functions should be: strbegins, stribegins, strends, striends.
> In all case, I think that is better a third parameter and keep underlined.

Please, not stribegins. We have enough functions with weird names :)
I am ambivalent of the question whether to have additional argument or
two functions, I guess with a slight preference for argument.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #95106 — will@wkhudgins.info — 2016-08-13T00:37:39+00:00

URL: https://externals.io/message/94787#95106 · In reply to: #94822

I've updated the RFC to reflect the discussion here and on github. You 
may see it at
https://wiki.php.net/rfc/add_str_begin_and_end_functions . You can see 
the github PR at https://github.com/php/php-src/pull/2049 .

The motivation for these changes was to maximize consistency between the 
proposed functions and existing PHP string functions. The goal is to 
make these functions feel natural and add functionality to the language 
without cluttering it up.

Thanks,

Will

---

## #95107 — Bishop Bettini — 2016-08-13T02:29:18+00:00

URL: https://externals.io/message/94787#95107 · In reply to: #95106

> I've updated the RFC to reflect the discussion here and on github. You may
> see it at
> https://wiki.php.net/rfc/add_str_begin_and_end_functions . You can see
> the github PR at https://github.com/php/php-src/pull/2049 .
>
> The motivation for these changes was to maximize consistency between the
> proposed functions and existing PHP string functions. The goal is to make
> these functions feel natural and add functionality to the language without
> cluttering it up.
>

Generally, +1. A few thoughts.

First, the RFC refers to these working on "characters". I assume you mean
ASCII characters and these actually work strictly on bytes. Working on
"characters" would be more in-line for a multi-byte extension. Would you
please clarify this point?

Second, and related to the multi-byte issue: do the case insensitive
versions honor case-folding in a multi-byte fashion? Either way, it's
probably a good idea to separate the vote between the sensitive and
insensitive versions because this is fundamentally a different, and perhaps
more contentious, question.

Third, perhaps these functions could provide more information than just
yes/no. Return boolean `TRUE` if and only if the needle completely
begins/ends the haystack, otherwise return INT representing the length in
common. Yes, that'll probably be a trap for new developers who don't honor
===, but that could be illuminated in docs. Formally:

boolean|int str_begin(string $needle, string $haystack)
boolean|int str_end(string $needle, string $haystack)

For example:

str_begin('http://', 'http://example.com') === true
str_begin('http://', 'https://example.com') === 4

Finally, since the RFC will fuel the final documentation, it might be a
good idea to use needle/haystack terminology in the function signatures for
some kind of consistency.

---

## #95108 — Lester Caine — 2016-08-13T07:42:37+00:00

URL: https://externals.io/message/94787#95108 · In reply to: #94822

> > […]

> Please, not stribegins. We have enough functions with weird names :)
> I am ambivalent of the question whether to have additional argument or
> two functions, I guess with a slight preference for argument.

The bulk of the time I'm applying this to the SQL query that is going to
return a set of results rather than direct to a string. In that case
it's STARTING 'xYZ'. Because the need has not arisen I've only just
noticed - after 20 odd years - there is no matching ENDING. Although
normally one needs to build a phantom field to index the data, so I do
have ONE case of reversed_field STARTING 'ZYX'.

Is starting just a Firebird SQL thing or is it more generally available.
I do a few google searches but as usual when searching for things like
'starting' one gets hundreds of pages on 'running' the software and it's
other connotations.

I suspect like PHP the other methods of doing things take the strain, so
certainly LIKE 'XYZ%' and '%XYZ' are probably the 'generic' solution but
suffer from slower search times, especially when looking for the ENDING
string.

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #95109 — Simon Welsh — 2016-08-13T08:34:48+00:00

URL: https://externals.io/message/94787#95109 · In reply to: #94787

> 
> 
> Hello,
> 
> I recently emailed the group about submitting an RFC for str_begins() and str_ends() functions. The RFC has now been officially submitted and is viewable at:
> 
> https://wiki.php.net/rfc/add_str_begin_and_end_functions
> 
> The github PR may be found at:
> 
> https://github.com/php/php-src/pull/2049
> 
> Hope to be hearing about this,
> 
> Will

Firstly, the argument ordering is the wrong way round for a string function. String functions — especially search-related ones — are haystack, needle (see strpos, strstr, strcspn, strpbrk, etc).

Secondly, I feel like this RFC does need to include that it’s a BC break by introducing new global functions. A quick search shows that SugarCRM[1] already implements str_begin and str_end functions and there’s likely to be other projects that do too.

[1]: https://github.com/sugarcrm/sugarcrm_dev/blob/ae189cfa4ed4edd6a4e1e0d9d1d5ec66f46a0b74/include/utils.php#L2082-L2090
--
Simon Welsh

---

## #95120 — will@wkhudgins.info — 2016-08-13T16:47:03+00:00

URL: https://externals.io/message/94787#95120 · In reply to: #95109

> > […]
> 
> Firstly, the argument ordering is the wrong way round for a string
> function. String functions — especially search-related ones — are
> haystack, needle (see strpos, strstr, strcspn, strpbrk, etc).
> 
> Secondly, I feel like this RFC does need to include that it’s a BC
> break by introducing new global functions. A quick search shows that
> SugarCRM[1] already implements str_begin and str_end functions and
> there’s likely to be other projects that do too.
> 
> [1]:
> https://github.com/sugarcrm/sugarcrm_dev/blob/ae189cfa4ed4edd6a4e1e0d9d1d5ec66f46a0b74/include/utils.php#L2082-L2090
> --
> Simon Welsh

You are correct, functions like strpos and strstr do follow (haystack, 
needle) but functions like str_replace follow the format (needle, 
haystack). Because I did these functions with the underscore, it made 
sense to make the functions follow the format found in other str_* 
functions. If the functions were changed to be strbegin, stribegin, 
strend, and striend, then it would make sense to follow the (haystack, 
needle) format. However, I think adding the underscore greatly improves 
the readability of these functions. And if the functions are named with 
an underscore, I think it should follow the format found in the other 
underscore functions.

Good call on the BC break, I had not thought about it breaking userland 
functions with the same name.

-Will

---

## #95126 — Simon Welsh — 2016-08-13T23:17:01+00:00

URL: https://externals.io/message/94787#95126 · In reply to: #95120

> 
> 
> 
> > […]
> 
> You are correct, functions like strpos and strstr do follow (haystack, needle) but functions like str_replace follow the format (needle, haystack). Because I did these functions with the underscore, it made sense to make the functions follow the format found in other str_* functions. If the functions were changed to be strbegin, stribegin, strend, and striend, then it would make sense to follow the (haystack, needle) format. However, I think adding the underscore greatly improves the readability of these functions. And if the functions are named with an underscore, I think it should follow the format found in the other underscore functions.

str_replace and str_ireplace are the only str_* functions that don’t take the full string (haystack) as the first argument. str_pad, str_repeat, str_split and str_word_count all take the full string first even if there are other compulsory arguments.

Also, these functions are replacements for current usage of strpos/strrpos/substr_compare, so I feel like the argument ordering should match those rather than another function that isn’t closely related in functionality.

> 
> Good call on the BC break, I had not thought about it breaking userland functions with the same name.
> 
> -Will

--
Simon Welsh

---

## #95292 — Rowan Collins — 2016-08-18T11:39:55+00:00

URL: https://externals.io/message/94787#95292 · In reply to: #95108

> Is starting just a Firebird SQL thing or is it more generally available.
> I do a few google searches but as usual when searching for things like
> 'starting' one gets hundreds of pages on 'running' the software and it's
> other connotations.

I've never come across it in Postgres, MS SQL Server, or MySQL. 
Generally LIKE 'abc%' is the recommended approach (and will I think hit 
the index in many cases, because the DBMS can optimize the case of a 
prefix match if it knows at planning time). A "starting" keyword would 
certainly be useful if it was there. :)

It doesn't quite fill the same need as a PHP function, of course, 
because you might be checking user input, or API results, or all sorts 
of things that won't, or haven't yet, hit the database. Currently the 
common idiom for that is the ugly strpos($string, 'abc') === 0

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #95296 — Lester Caine — 2016-08-18T15:29:34+00:00

URL: https://externals.io/message/94787#95296 · In reply to: #95292

> > […]
> 
> I've never come across it in Postgres, MS SQL Server, or MySQL.
> Generally LIKE 'abc%' is the recommended approach (and will I think hit
> the index in many cases, because the DBMS can optimize the case of a
> prefix match if it knows at planning time). A "starting" keyword would
> certainly be useful if it was there. :)
> 
> It doesn't quite fill the same need as a PHP function, of course,
> because you might be checking user input, or API results, or all sorts
> of things that won't, or haven't yet, hit the database. Currently the
> common idiom for that is the ugly strpos($string, 'abc') === 0

PHP is never going to be loading millions of records into memory and
searching them. That is the job of a database, and while LIKE 'abc%' can
be optimised to use an index and speed up results, if the 'abc%' is
supplied as a parameter that is not generally possible to prepare the
query using an index. While STARTING always knows the matching string is
the first characters of the index. While PHP and SQL share a number of
alternatives, the SQL versions will have a premium on search time if an
index can't be used.

I was just wondering if str_starting and str_ending matched better with
other string handling options.

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #105976 — will@wkhudgins.info — 2019-06-18T18:45:54+00:00

URL: https://externals.io/message/94787#105976

Hello all,

I submitted this RFC several years ago. I collected a lot of feedback 
and I have updated the RFC and corresponding github patch. Please see 
the RFC at https://wiki.php.net/rfc/add_str_begin_and_end_functions and 
the github patch at https://github.com/php/php-src/pull/2049. I have 
addressed many concerns
(order of arguments, name of functions, multibye support, etc). I plan 
to move this RFC to a vote in the coming weeks.

Thanks,

Will

---

## #105990 — will@wkhudgins.info — 2019-06-19T22:31:49+00:00

URL: https://externals.io/message/94787#105990

I sent this earlier this week without [RFC] in the subject line...since 
some people might have filters to check the subject line I wanted to 
send this again with the proper substring in the subject line–to make it 
clear I intend to take this to a vote in two weeks. Apologies for the 
duplicate email.

-Will


> Hello all,
> 
> I submitted this RFC several years ago. I collected a lot of feedback
> and I have updated the RFC and corresponding github patch. Please see
> the RFC at https://wiki.php.net/rfc/add_str_begin_and_end_functions
> and the github patch at https://github.com/php/php-src/pull/2049. I
> have addressed many concerns
> (order of arguments, name of functions, multibye support, etc). I plan
> to move this RFC to a vote in the coming weeks.
> 
> Thanks,
> 
> Will

---

## #106030 — Nikita Popov — 2019-06-22T15:32:17+00:00

URL: https://externals.io/message/94787#106030

> I sent this earlier this week without [RFC] in the subject line...since
> some people might have filters to check the subject line I wanted to
> send this again with the proper substring in the subject line–to make it
> clear I intend to take this to a vote in two weeks. Apologies for the
> duplicate email.
>
> -Will
>
> 
> > […]
>

Unfortunately, this looks like a case where the RFC feedback has made the
proposal worse, rather than better :(

I think it's easier to start with what I think this proposal should be:
There should be just two functions, `str_starts_with()` and `str_ends_with()`
-- and that's it.

The important realization to have here is that these functions are a bit of
sugar for an operation that is quite common, but can also be easily
implemented with existing functions (using strcmp, strpos or substr,
depending on what you like). There is no need for us to cover every
conceivable combination, just make the common case more convenient and
easier to read.

With that in mind:
 * I believe the "starts with" and "ends with" naming is a lot more
canonical, used by Python, Ruby, Java, JavaScript and probably lots more.
 * In my experience case-insensitive "i" variants of strings functions are
used much less, by an order of magnitude. With this being sugar in the
first place, I don't think there's a need to cover case-insensitive
variations (and from a quick look, these don't seem to be first class
methods in other languages either). If we do want to have them, I'd suggest
making the names str_starts_with_ci() and str_ends_with_ci(), which is more
obvious and harder to miss than str_istarts_with() etc.
 * Having mb_* variants of these functions doesn't really make sense. I
realize that there's this knee-jerk reaction about how if it doesn't have
"mb" in the name it's not Unicode compatible, but in this case it's even
more wrong than usual. The normal `str_starts_with()` function is perfectly
safe to use on UTF-8 strings, the only difference between it and
mb_str_starts_with() is that it's going to be implemented a lot more
efficiently. The only case that *might* make some sense is the
case-insensitive variant here, because that has some genuine reliance on
the character encoding. But then again, this can be handled by case-folding
the strings first, something that mbstring is going to do internally anyway.

I would happily accept a proposal for `str_starts_with()` + `str_ends_with()`,
but I'm a lot more apprehensive about adding these 8 new functions.

Regards,
Nikita

---

## #106035 — Ben Ramsey — 2019-06-22T19:56:24+00:00

URL: https://externals.io/message/94787#106035

> 
> 
> > […]
> 
> Unfortunately, this looks like a case where the RFC feedback has made the
> proposal worse, rather than better :(
> 
> I think it's easier to start with what I think this proposal should be:
> There should be just two functions, `str_starts_with()` and `str_ends_with()`
> -- and that's it.
> 
> The important realization to have here is that these functions are a bit of
> sugar for an operation that is quite common, but can also be easily
> implemented with existing functions (using strcmp, strpos or substr,
> depending on what you like). There is no need for us to cover every
> conceivable combination, just make the common case more convenient and
> easier to read.
> 
> With that in mind:
> * I believe the "starts with" and "ends with" naming is a lot more
> canonical, used by Python, Ruby, Java, JavaScript and probably lots more.
> * In my experience case-insensitive "i" variants of strings functions are
> used much less, by an order of magnitude. With this being sugar in the
> first place, I don't think there's a need to cover case-insensitive
> variations (and from a quick look, these don't seem to be first class
> methods in other languages either). If we do want to have them, I'd suggest
> making the names str_starts_with_ci() and str_ends_with_ci(), which is more
> obvious and harder to miss than str_istarts_with() etc.
> * Having mb_* variants of these functions doesn't really make sense. I
> realize that there's this knee-jerk reaction about how if it doesn't have
> "mb" in the name it's not Unicode compatible, but in this case it's even
> more wrong than usual. The normal `str_starts_with()` function is perfectly
> safe to use on UTF-8 strings, the only difference between it and
> mb_str_starts_with() is that it's going to be implemented a lot more
> efficiently. The only case that *might* make some sense is the
> case-insensitive variant here, because that has some genuine reliance on
> the character encoding. But then again, this can be handled by case-folding
> the strings first, something that mbstring is going to do internally anyway.
> 
> I would happily accept a proposal for `str_starts_with()` + `str_ends_with()`,
> but I'm a lot more apprehensive about adding these 8 new functions.
> 
> Regards,
> Nikita


I like the idea of simplifying this to the two functions `str_starts_with()` and `str_ends_with()`.

When I was looking through this the other day, I had trouble coming up with an example of a string with the mb_* versions would ever generate a different result from the non-multibyte versions, since the implementation only needs to count and analyze bytes for uniqueness. Perhaps it would only be an issue with the case-insensitive versions, as Nikita points out? If so, can someone provide some example strings where an mb_starts_with_ci() would return true, while str_starts_with_ci() would return false?

I think the case sensitivity versions would be common enough in use cases (i.e. looking to see if a path ends with .CSV vs. .csv, etc.), but maybe the signatures could be revised to pass a third parameter?

str_starts_with($haystack, $needle, $case_sensitive = true): bool

-Ben

---

## #106037 — Bruce Weirdan — 2019-06-22T20:27:43+00:00

URL: https://externals.io/message/94787#106037

>
> The normal `str_starts_with()` function is perfectly  safe to use on UTF-8 strings,

Only if you assume strings to be normalized to the same form. Checking if NFC
string starts with NFD substring by checking them bit by bit is going
to yield false
negatives [1]

[1] https://3v4l.org/4HgUL


-- 
  Best regards,
      Bruce Weirdan                                     mailto:weirdan@gmail.com

---

## #106038 — Nikita Popov — 2019-06-22T20:43:43+00:00

URL: https://externals.io/message/94787#106038

> 
> > […]
> strings,
>
> Only if you assume strings to be normalized to the same form. Checking if
> NFC
> string starts with NFD substring by checking them bit by bit is going
> to yield false negatives [1]
>
> [1] https://3v4l.org/4HgUL
>

That's correct, but not really relevant in the context of the discussion,
as mbstring does not perform Unicode normalization, so mb_* functions
wouldn't change anything about this. (Not that basic string operations
should be performing implicit Unicode normalization...)

Nikita

---

Next page: https://externals.io/message/94787.md?page=2
