String Functions
PHP has a huge library of string functions — searching, extracting, replacing, splitting, trimming, padding, changing case. They're plain functions rather than methods, and they never change the original string: each returns a new value. This lesson tours the ones you'll use every day.
Case and trimming
<?php $input = " Hello, World! "; echo "[", trim($input), "]\n"; echo "[", ltrim($input), "]\n"; echo "[", rtrim($input), "]\n"; echo strtoupper(trim($input)), "\n"; echo strtolower(trim($input)), "\n"; echo ucfirst("hello world"), "\n"; echo ucwords("hello wide world"), "\n"; echo trim("--==Title==--", "-="), "\n";
[Hello, World!] [Hello, World! ] [ Hello, World!] HELLO, WORLD! hello, world! Hello world Hello Wide World Title
Trimming input is a good habit: form fields often arrive with stray spaces. The second argument to the trim functions lists the characters to remove.
Searching
<?php $text = "The rain in Spain stays mainly in the plain"; var_dump(str_contains($text, "Spain")); var_dump(str_starts_with($text, "The")); var_dump(str_ends_with($text, "plain")); var_dump(strpos($text, "ain")); var_dump(strrpos($text, "ain")); var_dump(stripos($text, "SPAIN")); // case-insensitive var_dump(strpos($text, "snow")); echo substr_count($text, "ain"), "\n";
bool(true) bool(true) bool(true) int(5) int(40) int(12) bool(false) 4
strpos returns the position of the first match, or false if there isn't one. That leads to a famous bug: a match at position 0 is falsy too, so always compare with === false or !== false. For a yes/no question, str_contains is clearer anyway.
<?php $s = "apple pie"; if (strpos($s, "apple")) { echo "found (loose check)\n"; } else { echo "not found?! (bug: position 0 is falsy)\n"; } if (strpos($s, "apple") !== false) { echo "found (strict check)\n"; }
not found?! (bug: position 0 is falsy) found (strict check)
Extracting parts
substr($string, $start, $length) returns part of a string. A negative start counts from the end. strstr returns the part from a match onwards (or before it):
<?php $email = "maria.lopez@example.com"; $at = strpos($email, "@"); echo substr($email, 0, $at), "\n"; echo substr($email, $at + 1), "\n"; echo substr($email, -3), "\n"; echo strstr($email, "@"), "\n"; echo strstr($email, "@", true), "\n"; echo strrchr("archive.tar.gz", "."), "\n"; // from the last dot
maria.lopez example.com com @example.com maria.lopez .gz
Replacing
<?php $s = "I like cats. Cats are great."; echo str_replace("cats", "dogs", $s), "\n"; echo str_ireplace("cats", "dogs", $s), "\n"; echo str_replace(["I", "great"], ["We", "the best"], $s), "\n"; echo substr_replace("2026-10-08", "**", 5, 2), "\n"; echo strtr("Hi NAME, your code is CODE", ["NAME" => "Ana", "CODE" => "X7"]), "\n";
I like dogs. Cats are great. I like dogs. dogs are great. We like cats. Cats are the best. 2026-**-08 Hi Ana, your code is X7
strtr with an array replaces all placeholders in one pass, which makes it handy for simple templates.
Splitting and joining
explode splits a string into an array at a separator; implode joins an array back into a string. str_split splits into fixed-size chunks:
<?php $csv = "Oslo,Bergen,Trondheim"; $cities = explode(",", $csv); echo count($cities), " cities, second is $cities[1]\n"; echo implode(" | ", $cities), "\n"; [$key, $value] = explode("=", "timeout=30=seconds", 2); // at most 2 parts echo "$key -> $value\n"; print_r(str_split("ABCDEFGH", 3)); echo ucwords(implode(" ", explode("-", "my-blog-post"))), "\n";
3 cities, second is Bergen
Oslo | Bergen | Trondheim
timeout -> 30=seconds
Array
(
[0] => ABC
[1] => DEF
[2] => GH
)
My Blog PostPadding and repeating
<?php $items = ["Tea" => 2.5, "Coffee" => 3.2, "Hot chocolate" => 3.95]; foreach ($items as $name => $price) { echo str_pad($name, 15, "."), str_pad(number_format($price, 2), 6, " ", STR_PAD_LEFT), "\n"; } echo str_pad("42", 6, "0", STR_PAD_LEFT), "\n"; echo str_repeat("=-", 10), "\n";
Tea............ 2.50 Coffee......... 3.20 Hot chocolate.. 3.95 000042 =-=-=-=-=-=-=-=-=-=-
Other useful functions
<?php echo strrev("stressed"), "\n"; echo wordwrap("The quick brown fox jumps over the lazy dog", 15, "\n", true), "\n"; echo nl2br("line one\nline two"), "\n"; echo number_format(1234.5, 1), "\n"; echo str_word_count("How many words are here?"), "\n"; echo similar_text("World", "Word"), "\n"; echo levenshtein("kitten", "sitting"), "\n";
desserts The quick brown fox jumps over the lazy dog line one<br /> line two 1,234.5 5 4 3
levenshtein counts the edits needed to turn one string into another — useful for "did you mean…?" suggestions.
Quick reference
| Task | Function |
|---|---|
| Length | strlen (bytes), mb_strlen (characters) |
| Contains / starts / ends | str_contains, str_starts_with, str_ends_with |
| Position | strpos, stripos, strrpos (returns false if missing) |
| Part of a string | substr, strstr, strrchr |
| Replace | str_replace, str_ireplace, strtr, substr_replace |
| Split / join | explode, implode, str_split |
| Clean up | trim, ltrim, rtrim |
| Case | strtolower, strtoupper, ucfirst, ucwords |
| Layout | str_pad, str_repeat, wordwrap |
Try it yourself
Turn a blog post title into a URL "slug": lower-case, with words joined by hyphens and punctuation removed.
hello-world-php-strings-explained