Skip to content

Instantly share code, notes, and snippets.

@juliyvchirkov
Last active April 14, 2024 22:24
Show Gist options
  • Save juliyvchirkov/8f325f9ac534fe736b504b93a1a8b2ce to your computer and use it in GitHub Desktop.
Save juliyvchirkov/8f325f9ac534fe736b504b93a1a8b2ce to your computer and use it in GitHub Desktop.
php: polyfills of string functions str_starts_with, str_contains and str_ends_with
<?php declare(strict_types = 1);
/**
* Provides polyfills of string functions str_starts_with, str_contains and str_ends_with,
* core functions since PHP 8, along with their multibyte implementations mb_str_starts_with,
* mb_str_contains and mb_str_ends_with
*
* Covers PHP 4 - PHP 7, safe to utilize with PHP 8
*/
/**
* @see https://www.php.net/manual/en/function.str-starts-with
*/
if (!function_exists('str_starts_with')) {
function str_starts_with(string $haystack, string $needle): bool
{
return strlen($needle) === 0 || strpos($haystack, $needle) === 0;
}
}
/**
* @see https://www.php.net/manual/en/function.str-contains
*/
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool
{
return strlen($needle) === 0 || strpos($haystack, $needle) !== false;
}
}
/**
* @see https://www.php.net/manual/en/function.str-ends-with
*/
if (!function_exists('str_ends_with')) {
function str_ends_with(string $haystack, string $needle): bool
{
return strlen($needle) === 0 || substr($haystack, -strlen($needle)) === $needle;
}
}
if (!function_exists('mb_str_starts_with')) {
function mb_str_starts_with(string $haystack, string $needle): bool
{
return mb_strlen($needle) === 0 || mb_strpos($haystack, $needle) === 0;
}
}
if (!function_exists('mb_str_contains')) {
function mb_str_contains(string $haystack, string $needle): bool
{
return mb_strlen($needle) === 0 || mb_strpos($haystack, $needle) !== false;
}
}
if (!function_exists('mb_str_ends_with')) {
function mb_str_ends_with(string $haystack, string $needle): bool
{
return mb_strlen($needle) === 0 || mb_substr($haystack, -mb_strlen($needle)) === $needle;
}
}
@nextgenthemes
Copy link

@juliyvchirkov
Copy link
Author

juliyvchirkov commented Apr 5, 2024

@nextgenthemes Thanks for your review!

Covers PHP 4 - PHP 7

It is actually not true, the code uses string type hints that are part of PHP 7.0 array was already part of 5.6.

C'mon, it's just a gist. Sure thing PHP 4 provides no support for type hints. Remove the type hints from the code and you'll achieve the goal.

That simple.

https://onlinephp.io/c/9bbc68fa-4065-43ac-800b-072275ce4b74

Знімок екрана 2024-04-05 о 19 48 46

You should consider using this (made it after writing this) or symfony/polyfill-php80 instead of this gist. I am saying this while I use my own polyfills for the 3 string functions as well at this time, but I think I will change to that even though I do not need most of it. Here is why.

  1. It's done by people who absolutely know what they are doing.
  2. It exits early if PHP 8.0 is detected.
  3. It's quite complex how these functions are called, it does not use strict types. First it uses ?string nullable types and then $haystack ?? '' to call the actual polyfill that has string types. Meaning that these functions can be called with null as arguments that get tuned into empty strings. I assume this is to correctly actually polyfill the functions how they behave natively. That fact that it does not use declare(strict_types = 1); actually means the functions can be called with all kinds of types that will be transformed to string or null.

Thank you, I'm utilizing Symfony Polyfill myself if available. The code of these guys is implemented in a strict clear Symphony way and I like and respect it.

Mine simplified alternatives shared above have been developed the day after the release of PHP 8 as temporary solution till Symfony delivers their polyfills for PHP 8, and as soon as symfony/polyfill-php80 bundle arrived, I switched to it.

But, long story short, the fact that Symfony no doubt implements top quality solutions doesn't mean my alternatives don't serve their job.

The mb_ versions are actually not part of PHP so they are not polyfills.

C'mon, the preamble at the gist header comment notes clear and crisp «polyfills of string functions str_starts_with, str_contains and str_ends_with, core functions since PHP 8, along with their multibyte implementations». Period.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment