PHP Strings and String Functions Explained — With Real Examples
Every single thing a user reads on a webpage is text — usernames, blog posts, error messages, product names, email addresses. That text has to come from somewhere, get processed, and then get shown in exactly the right format. PHP is one of the most widely-used languages for powering that backend text-processing work, and strings are at the absolute heart of it. If you can't confidently work with strings in PHP, you'll hit a wall fast.
What Is a PHP String and How Do You Create One?
A string is just a sequence of characters — letters, numbers, spaces, symbols — wrapped in quotes. Think of it like a sentence inside a box. PHP needs those quotes to know where the text starts and where it ends. Without them, PHP would try to read your text as a command and get very confused.
PHP gives you two ways to wrap that box: single quotes and double quotes. The difference matters more than beginners expect. Inside double quotes, PHP looks for variables and replaces them with their values — this is called variable interpolation. Inside single quotes, PHP takes everything literally. No substitutions, no special behaviour — what you type is exactly what you get.
There's also a third syntax called Heredoc, which is like a multi-line box for long chunks of text. It's less common day-to-day but incredibly useful when you're building HTML templates or long email bodies inside PHP.
For now, start with double quotes for most things. Use single quotes when you want to be strict and explicit, or when your string contains a lot of dollar signs (like currency) and you don't want PHP trying to treat them as variable names.
<?php // --- Single-quoted string: PHP takes it literally --- $productName = 'Wireless Headphones'; // --- Double-quoted string: PHP replaces $productName with its value --- $welcomeMessage = "Thank you for purchasing $productName!"; // --- Concatenation: joining two strings using the dot (.) operator --- $firstName = 'Sarah'; $lastName = 'Connor'; $fullName = $firstName . ' ' . $lastName; // dot joins them with a space // --- Heredoc: great for multi-line strings (note: no indent before closing label) --- $emailBody = <<<EOT Dear $firstName, Your order for $productName has been confirmed. Thank you for shopping with us! EOT; // --- Print results --- echo $welcomeMessage . "\n"; echo $fullName . "\n"; echo $emailBody;
Sarah Connor
Dear Sarah,
Your order for Wireless Headphones has been confirmed.
Thank you for shopping with us!
The Most Useful PHP String Functions You'll Use Every Day
PHP ships with over 100 built-in string functions. That sounds overwhelming, but honestly about a dozen of them handle 90% of real-world work. These aren't arbitrary — each one exists because web developers kept writing the same helper code over and over, and the PHP team baked those solutions into the language.
Here's the mental model: every string function takes at least one string as input and gives you something back — a modified string, a number, or a true/false answer. You're never changing the original variable unless you explicitly overwrite it. Strings in PHP are immutable by default in that sense — the function returns a new value, it doesn't edit in place.
The functions below are grouped by what job they do: measuring strings, transforming their case, trimming whitespace, searching inside them, and replacing content. Learn them in that order and they'll stick.
<?php $userInput = ' Hello, World! '; $articleTitle = 'php strings are powerful'; $emailAddress = 'user@example.com'; $productDescription = 'The quick brown fox jumps over the lazy dog.'; // ── MEASURING ─────────────────────────────────────────────── // strlen() counts how many characters are in the string (spaces included) $rawLength = strlen($userInput); // 21 (includes the leading/trailing spaces) // ── TRIMMING ──────────────────────────────────────────────── // trim() strips whitespace from both ends — classic for cleaning form input $cleanInput = trim($userInput); // 'Hello, World!' $trimmedLength = strlen($cleanInput); // 13 // ── CASE TRANSFORMATIONS ──────────────────────────────────── // strtoupper() makes every letter a capital $shoutedTitle = strtoupper($articleTitle); // 'PHP STRINGS ARE POWERFUL' // strtolower() makes every letter lowercase — useful before comparisons $lowerEmail = strtolower($emailAddress); // 'user@example.com' // ucwords() capitalises the first letter of every word — great for display names $formattedTitle = ucwords($articleTitle); // 'Php Strings Are Powerful' // ── SEARCHING ─────────────────────────────────────────────── // strpos() finds the position (index) of the FIRST occurrence of a substring // Returns FALSE if the substring isn't found — note: position 0 is the very first character $foxPosition = strpos($productDescription, 'fox'); // 16 // str_contains() (PHP 8+) — returns true/false, much more readable for simple checks $hasFox = str_contains($productDescription, 'fox'); // true // ── REPLACING ─────────────────────────────────────────────── // str_replace() swaps out every occurrence of a word for another $updatedDescription = str_replace('lazy', 'energetic', $productDescription); // 'The quick brown fox jumps over the energetic dog.' // ── SLICING ───────────────────────────────────────────────── // substr() extracts a portion of a string: substr(string, start, length) $domain = substr($emailAddress, 5); // 'example.com' — starts from index 5 $tld = substr($emailAddress, -3); // 'com' — negative index counts from the end // ── SPLITTING ─────────────────────────────────────────────── // explode() splits a string into an array using a delimiter $emailParts = explode('@', $emailAddress); // ['user', 'example.com'] $username = $emailParts[0]; // 'user' // ── OUTPUT RESULTS ────────────────────────────────────────── echo "Raw length (with spaces): $rawLength\n"; echo "Trimmed: '$cleanInput' — Length: $trimmedLength\n"; echo "Shouted: $shoutedTitle\n"; echo "Formatted: $formattedTitle\n"; echo "'fox' found at position: $foxPosition\n"; echo "Contains 'fox': " . ($hasFox ? 'Yes' : 'No') . "\n"; echo "Updated: $updatedDescription\n"; echo "Domain: $domain\n"; echo "TLD: $tld\n"; echo "Username from email: $username\n";
Trimmed: 'Hello, World!' — Length: 13
Shouted: PHP STRINGS ARE POWERFUL
Formatted: Php Strings Are Powerful
'fox' found at position: 16
Contains 'fox': Yes
Updated: The quick brown fox jumps over the energetic dog.
Domain: example.com
TLD: com
Username from email: user
Formatting Strings for Output — sprintf and number_format
There's a big difference between storing a number and displaying it nicely. The number 49999.5 in your database needs to look like $49,999.50 on a receipt. PHP's sprintf() function acts like a template engine for strings — you write a pattern with placeholders, then tell PHP what values to slot in.
Think of sprintf() like a Mad Libs game: you write a sentence with blank spaces, and then supply the words separately. The format codes starting with % are the blanks. %s means 'put a string here', %d means 'put a whole number here', %.2f means 'put a decimal number here with exactly 2 decimal places'.
This approach is cleaner than manually concatenating with dots, especially when building things like price labels, log messages, or SQL queries. It also separates your template from your data, which makes the code much easier to read and maintain.
number_format() is a simpler companion function focused purely on formatting numbers — adding thousands separators and controlling decimal places. Every e-commerce site uses it.
<?php $itemName = 'Mechanical Keyboard'; $itemPrice = 149.9; // raw price from database $itemQuantity = 3; $taxRate = 0.08; // 8% tax // ── number_format() ───────────────────────────────────────── // number_format(number, decimal_places, decimal_separator, thousands_separator) $formattedPrice = number_format($itemPrice, 2); // '149.90' $largeAmount = 1999999.5; $readableAmount = number_format($largeAmount, 2, '.', ','); // '1,999,999.50' // ── sprintf() ─────────────────────────────────────────────── // %s = string placeholder, %.2f = float with 2 decimal places, %d = integer $receiptLine = sprintf( '%d x %s @ $%.2f each', $itemQuantity, // fills %d $itemName, // fills %s $itemPrice // fills %.2f ); // Result: '3 x Mechanical Keyboard @ $149.90 each' // Calculating and formatting a total with tax $subtotal = $itemPrice * $itemQuantity; // 449.70 $taxAmount = $subtotal * $taxRate; // 35.976 $total = $subtotal + $taxAmount; // 485.676 $receiptSummary = sprintf( "Subtotal: $%.2f\nTax (8%%): $%.2f\nTotal: $%.2f", $subtotal, $taxAmount, $total // Note: %% prints a literal percent sign — a single % would confuse sprintf ); // ── OUTPUT ────────────────────────────────────────────────── echo $receiptLine . "\n"; echo $receiptSummary . "\n"; echo "Large amount formatted: $" . $readableAmount . "\n";
Subtotal: $449.70
Tax (8%): $35.98
Total: $485.68
Large amount formatted: $1,999,999.50
Searching and Replacing Text — The Real-World Power Move
The ability to search inside strings and replace content is where PHP strings stop being a theory exercise and start solving real problems. Imagine you're building a blog platform: users write posts with a custom shortcode like [author-name], and your system replaces it with the actual author's name before display. That's str_replace() in action.
For simple replacements, str_replace() is perfect. But sometimes you need more power — maybe you want to find all phone numbers in a block of text, or validate that an email address actually looks like an email. That's when you reach for regular expressions via preg_match() and preg_replace(). Regex is its own deep topic, but it's built on the same string foundation you're learning now.
One practical pattern every PHP developer uses: sanitising user input before storing or displaying it. The htmlspecialchars() function converts dangerous characters like < and > into safe HTML entities, stopping cross-site scripting (XSS) attacks. It's not glamorous, but skipping it is a serious security mistake. Always, always sanitise before you echo user-supplied data.
<?php // ── BASIC REPLACEMENT ─────────────────────────────────────── $blogTemplate = 'Welcome to [site-name]! Written by [author-name] on [date].'; // str_replace can accept arrays to do multiple replacements in one call $published = str_replace( ['[site-name]', '[author-name]', '[date]'], // search for these ['TheCodeForge', 'Alice Merritt', 'June 2025'], // replace with these $blogTemplate // in this string ); // Result: 'Welcome to TheCodeForge! Written by Alice Merritt on June 2025.' // ── CASE-INSENSITIVE REPLACEMENT ──────────────────────────── $userComment = 'I love PHP! PHP is awesome. php rocks.'; // str_ireplace() is case-insensitive — it catches 'PHP', 'php', 'Php', etc. $censoredComment = str_ireplace('php', '***', $userComment); // Result: 'I love ***! *** is awesome. *** rocks.' // ── SECURITY: Sanitising user input before display ─────────── $maliciousInput = '<script>alert("You have been hacked!");</script>'; // htmlspecialchars() converts < > " & into safe HTML entities // This stops the browser from executing the script tag $safeOutput = htmlspecialchars($maliciousInput, ENT_QUOTES, 'UTF-8'); // Result: '<script>alert("You have been hacked!");</script>' // The browser displays it as plain text — not an executable script // ── SIMPLE REGEX EXAMPLE: Validate an email ───────────────── $emailToCheck = 'contact@thecodeforge.io'; // preg_match() returns 1 if pattern matches, 0 if not // FILTER_VALIDATE_EMAIL is PHP's built-in email validator (simpler than raw regex) $isValidEmail = filter_var($emailToCheck, FILTER_VALIDATE_EMAIL); // ── OUTPUT ────────────────────────────────────────────────── echo $published . "\n"; echo $censoredComment . "\n"; echo "Safe output: " . $safeOutput . "\n"; echo "Is email valid: " . ($isValidEmail ? 'Yes' : 'No') . "\n";
I love ***! *** is awesome. *** rocks.
Safe output: <script>alert("You have been hacked!");</script>
Is email valid: Yes
| Task | Function to Use | Returns | PHP Version |
|---|---|---|---|
| Count characters | strlen() | Integer (character count) | All versions |
| Find substring position | strpos() | Integer or false | All versions |
| Check if string contains | str_contains() | Boolean (true/false) | PHP 8.0+ |
| Check string starts with | str_starts_with() | Boolean (true/false) | PHP 8.0+ |
| Check string ends with | str_ends_with() | Boolean (true/false) | PHP 8.0+ |
| Replace text (case-sensitive) | str_replace() | Modified string | All versions |
| Replace text (case-insensitive) | str_ireplace() | Modified string | All versions |
| Extract substring | substr() | Extracted string | All versions |
| Split string into array | explode() | Array of parts | All versions |
| Join array into string | implode() | Single string | All versions |
| Format string with placeholders | sprintf() | Formatted string | All versions |
| Format a number for display | number_format() | Formatted string | All versions |
| Sanitise for HTML output | htmlspecialchars() | Safe HTML string | All versions |
| Remove leading/trailing space | trim() | Cleaned string | All versions |
| Convert to uppercase | strtoupper() | Uppercase string | All versions |
| Convert to lowercase | strtolower() | Lowercase string | All versions |
🎯 Key Takeaways
- Double quotes allow variable interpolation; single quotes treat everything literally — choose deliberately, not by habit.
- strpos() returns 0 (not false) when a match is at index 0 — always use === false for the not-found check, or switch to str_contains() on PHP 8+.
- Always sanitise user input with htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before echoing it — skipping this is an XSS vulnerability waiting to happen.
- sprintf() is more than a formatter — it returns a value you can store, pass around, or log, making it far more flexible than concatenating strings inside an echo.
⚠ Common Mistakes to Avoid
- ✕Mistake 1: Using == to check if strpos() returned false — strpos() returns 0 when the match is at the very first character, and 0 == false is true in PHP's loose comparison. So if('banana', 0) would incorrectly say 'not found'. Fix: always use === for strpos() checks: if (strpos($haystack, $needle) === false) { ... }. Better yet, use str_contains() on PHP 8+.
- ✕Mistake 2: Forgetting that string indexes start at 0, not 1 — beginners often write substr($email, 1) expecting to skip the first character, but get the second character instead because index 0 is the first. Fix: remember that every sequence in PHP (strings, arrays) is zero-indexed. The first character is at position 0.
- ✕Mistake 3: Echoing unsanitised user input directly to the page — symptoms include XSS vulnerabilities where malicious scripts execute in visitors' browsers. Fix: always wrap user-supplied data in htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before echoing it. Make this a non-negotiable habit, not an afterthought.
Interview Questions on This Topic
- QWhat is the difference between single-quoted and double-quoted strings in PHP, and when would you deliberately choose one over the other?
- QWhy is if (strpos($str, 'word') == false) a bug, and how do you fix it?
- QIf you had to extract the domain name from a list of email addresses stored in a database column, which PHP string functions would you combine and why?
Frequently Asked Questions
What is the difference between echo and print in PHP for strings?
Both output strings to the browser, but echo is slightly faster (it's a language construct, not a function) and can output multiple values separated by commas. print always returns 1, making it technically usable inside expressions. In practice, use echo — almost every PHP codebase does.
How do I check if a PHP string contains a specific word?
On PHP 8+, use str_contains($haystack, $needle) — it returns a plain true or false. On older PHP versions, use strpos($haystack, $needle) !== false (note the triple equals). Avoid == false because strpos() returns 0 when the match is at the very beginning of the string, and 0 == false is true in PHP.
Why does strlen() sometimes give the wrong character count for non-English text?
strlen() counts bytes, not characters. A single emoji or accented character like é can be 2–4 bytes in UTF-8, so strlen() may return a larger number than you expect. For accurate character counts with multibyte text, use mb_strlen() instead — the mb_ family of functions (mb_strtolower, mb_substr, etc.) are all multibyte-safe.
Written and reviewed by senior developers with real-world experience across enterprise, startup and open-source projects. Every article on TheCodeForge is written to be clear, accurate and genuinely useful — not just SEO filler.