Last active
February 14, 2026 22:27
-
-
Save jason-napolitano/33df8c572a6e3f667f0a4fd1f73ac4ae to your computer and use it in GitHub Desktop.
A PHP String Helper Class with a Fluent API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * A class which provides helper functions for | |
| * working on strings - using a fluent API. | |
| * | |
| * USAGE: | |
| * | |
| * ``` | |
| * $str = Str::make(' this is a string '); | |
| * | |
| * return $str->trim()->upper()->get(); // THIS IS A STRING | |
| * ``` | |
| */ | |
| class Str | |
| { | |
| /** @var string $string the string to be modified */ | |
| private static string $string; | |
| /** @var array|string[] $plural Array of pluralized words */ | |
| private static array $plural = [ | |
| '/(quiz)$/i' => "$1zes", | |
| '/^(ox)$/i' => "$1en", | |
| '/([m|l])ouse$/i' => "$1ice", | |
| '/(matr|vert|ind)ix|ex$/i' => "$1ices", | |
| '/(x|ch|ss|sh)$/i' => "$1es", | |
| '/([^aeiouy]|qu)y$/i' => "$1ies", | |
| '/(hive)$/i' => "$1s", | |
| '/(?:([^f])fe|([lr])f)$/i' => "$1$2ves", | |
| '/(shea|lea|loa|thie)f$/i' => "$1ves", | |
| '/sis$/i' => "ses", | |
| '/([ti])um$/i' => "$1a", | |
| '/(tomat|potat|ech|her|vet)o$/i' => "$1oes", | |
| '/(bu)s$/i' => "$1ses", | |
| '/(alias)$/i' => "$1es", | |
| '/(octop)us$/i' => "$1i", | |
| '/(ax|test)is$/i' => "$1es", | |
| '/(us)$/i' => "$1es", | |
| '/s$/i' => "s", | |
| '/$/' => "s", | |
| ]; | |
| /** @var array|string[] $singular Array of singular words */ | |
| private static array $singular = [ | |
| '/(quiz)zes$/i' => "$1", | |
| '/(matr)ices$/i' => "$1ix", | |
| '/(vert|ind)ices$/i' => "$1ex", | |
| '/^(ox)en$/i' => "$1", | |
| '/(alias)es$/i' => "$1", | |
| '/(octop|vir)i$/i' => "$1us", | |
| '/(cris|ax|test)es$/i' => "$1is", | |
| '/(shoe)s$/i' => "$1", | |
| '/(o)es$/i' => "$1", | |
| '/(bus)es$/i' => "$1", | |
| '/([m|l])ice$/i' => "$1ouse", | |
| '/(x|ch|ss|sh)es$/i' => "$1", | |
| '/(m)ovies$/i' => "$1ovie", | |
| '/(s)eries$/i' => "$1eries", | |
| '/([^aeiouy]|qu)ies$/i' => "$1y", | |
| '/([lr])ves$/i' => "$1f", | |
| '/(tive)s$/i' => "$1", | |
| '/(hive)s$/i' => "$1", | |
| '/(li|wi|kni)ves$/i' => "$1fe", | |
| '/(shea|loa|lea|thie)ves$/i' => "$1f", | |
| '/(^analy)ses$/i' => "$1sis", | |
| '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis", | |
| '/([ti])a$/i' => "$1um", | |
| '/(n)ews$/i' => "$1ews", | |
| '/(h|bl)ouses$/i' => "$1ouse", | |
| '/(corpse)s$/i' => "$1", | |
| '/(us)es$/i' => "$1", | |
| '/s$/i' => "", | |
| ]; | |
| /** @var array|string[] $irregular Array of irregular words */ | |
| private static array $irregular = [ | |
| 'move' => 'moves', | |
| 'foot' => 'feet', | |
| 'goose' => 'geese', | |
| 'sex' => 'sexes', | |
| 'child' => 'children', | |
| 'man' => 'men', | |
| 'tooth' => 'teeth', | |
| 'person' => 'people', | |
| 'valve' => 'valves', | |
| ]; | |
| /** | |
| * Assign the string value | |
| * | |
| * @var string $string | |
| * | |
| * @return self | |
| */ | |
| public static function make(string $string): self | |
| { | |
| self::$string = $string; | |
| return new self(); | |
| } | |
| /** | |
| * Removes quotes from a string | |
| * | |
| * @return self | |
| */ | |
| public function stripQuotes(): self | |
| { | |
| self::$string = $this->replace(["'", '"'], ''); | |
| return $this; | |
| } | |
| /** | |
| * Return a singluarized string | |
| * | |
| * @return self | |
| */ | |
| public function singular(): self | |
| { | |
| // check for irregular singular forms | |
| $this->pluralSingularCheck(); | |
| // check for matches using regular expressions | |
| foreach (self::$singular as $pattern => $result) { | |
| if (preg_match($pattern, self::$string)) { | |
| self::$string = preg_replace($pattern, $result, self::$string); | |
| } | |
| } | |
| return $this; | |
| } | |
| /** | |
| * Return a pluralized string | |
| * | |
| * @return self | |
| */ | |
| public function plural(): self | |
| { | |
| // check for irregular plural forms | |
| $this->pluralSingularCheck(); | |
| // check for matches using regular expressions | |
| foreach (self::$plural as $pattern => $result) { | |
| if (preg_match($pattern, self::$string)) { | |
| self::$string = preg_replace($pattern, $result, self::$string); | |
| } | |
| } | |
| return $this; | |
| } | |
| /** | |
| * Singular / plural validation check | |
| * | |
| * @return void | |
| */ | |
| private function pluralSingularCheck(): void | |
| { | |
| // check for irregular singular forms | |
| foreach (self::$irregular as $pattern => $result) { | |
| $pattern = '/' . $pattern . '$/i'; | |
| if (preg_match($pattern, self::$string)) { | |
| self::$string = preg_replace($pattern, $result, self::$string); | |
| } | |
| } | |
| } | |
| /** | |
| * Wrapper for trim(...) | |
| * | |
| * @return self | |
| */ | |
| public function trim(): self | |
| { | |
| self::$string = trim(self::$string); | |
| return $this; | |
| } | |
| /** | |
| * Wrapper for rtrim(...) | |
| * | |
| * @param string $character | |
| * | |
| * @return $this | |
| */ | |
| public function rtrim(string $character): self | |
| { | |
| self::$string = rtrim(self::$string, $character); | |
| return $this; | |
| } | |
| /** | |
| * Wrapper for ltrim(...) | |
| * | |
| * @param string $character | |
| * | |
| * @return $this | |
| */ | |
| public function ltrim(string $character): self | |
| { | |
| self::$string = ltrim(self::$string, $character); | |
| return $this; | |
| } | |
| /** | |
| * Wrapper for str_repeat(...) | |
| * | |
| * @param int $count | |
| * | |
| * @return string | |
| */ | |
| public function repeat(int $count): string | |
| { | |
| return str_repeat(self::$string, $count); | |
| } | |
| /** | |
| * Wrapper for strlen(...) | |
| * | |
| * @return int | |
| */ | |
| public function count(): int | |
| { | |
| return strlen(self::$string); | |
| } | |
| /** | |
| * Wrapper for strtolower(...) | |
| * | |
| * @return self | |
| * | |
| * @see \strtolower() | |
| * | |
| */ | |
| public function lower(): self | |
| { | |
| self::$string = strtolower(self::$string); | |
| return $this; | |
| } | |
| /** | |
| * Wrapper for strtoupper(...) | |
| * | |
| * @return self | |
| * | |
| * @see \strtoupper() | |
| * | |
| */ | |
| public function upper(): self | |
| { | |
| self::$string = strtoupper(self::$string); | |
| return $this; | |
| } | |
| /** | |
| * Returns a title cased string | |
| * | |
| * @return self | |
| */ | |
| public function title(): string | |
| { | |
| self::$string = ucwords(self::$string); | |
| return self::$string; | |
| } | |
| /** | |
| * Check if a string is empty | |
| * | |
| * @return bool | |
| */ | |
| public function empty(): bool | |
| { | |
| return self::$string === ''; | |
| } | |
| /** | |
| * Converts string to a slug format | |
| * | |
| * @param | |
| * | |
| * @return self | |
| */ | |
| public function slug(): string | |
| { | |
| self::$string = strtolower($this->replace(' ', '-')); | |
| return self::$string; | |
| } | |
| /** | |
| * Converts a string to snake case format | |
| * | |
| * @return self | |
| */ | |
| public function snake(): string | |
| { | |
| self::$string = $this->replace(' ', '_'); | |
| return self::$string; | |
| } | |
| /** | |
| * Create a dot notation string | |
| * | |
| * @return self | |
| */ | |
| public function dot(): self | |
| { | |
| self::$string = $this->replace(' ', '.'); | |
| return $this; | |
| } | |
| /** | |
| * Replaces characters in a string | |
| * | |
| * @param string|array<string> $search | |
| * @param string $replace | |
| * | |
| * @return string | |
| */ | |
| public function replace(string|array $search, string $replace): string | |
| { | |
| return str_replace($search, $replace, static::$string); | |
| } | |
| /** | |
| * Hashes a string using bcrypt | |
| * | |
| * @return string | |
| */ | |
| public function bcrypt(): string | |
| { | |
| return password_hash(self::$string, PASSWORD_BCRYPT); | |
| } | |
| /** | |
| * Hashes a string using argon2i | |
| * | |
| * @return string | |
| */ | |
| public function argon2i(): string | |
| { | |
| return password_hash(self::$string, PASSWORD_ARGON2I); | |
| } | |
| /** | |
| * Generate a UUID | |
| * | |
| * @return string | |
| */ | |
| public static function uuid(): string | |
| { | |
| $data = random_bytes(16); | |
| $data[6] = chr(ord($data[6]) & 0x0f | 0x40); | |
| // Set variant to RFC 4122 | |
| $data[8] = chr(ord($data[8]) & 0x3f | 0x80); | |
| return sprintf( | |
| '%s-%s-%s-%s-%s', | |
| bin2hex(substr($data, 0, 4)), | |
| bin2hex(substr($data, 4, 2)), | |
| bin2hex(substr($data, 6, 2)), | |
| bin2hex(substr($data, 8, 2)), | |
| bin2hex(substr($data, 10, 6)) | |
| ); | |
| } | |
| /** | |
| * Returns the string value | |
| * | |
| * @return string | |
| */ | |
| public function get(): string | |
| { | |
| return self::$string; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment