A PHP string is a sequence of characters wrapped in quotes
Single quotes treat everything literally; double quotes parse variables inside
PHP offers 100+ built-in functions: strlen, strpos, str_replace, explode, and more
Strings are immutable — functions return new values, they don't modify the original
Use double quotes for variable embedding; single quotes for performance when no variables
Production risk: forgetting strict comparison with strpos() leads to logic bugs
✦ Definition~90s read
What is PHP Strings and String Functions?
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.
★
Imagine a string is just a piece of text written on a sticky note.
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.
Plain-English First
Imagine a string is just a piece of text written on a sticky note. PHP lets you stick notes together, cut them up, search inside them, count the letters, and swap words out — all without touching the original paper. Every time a website shows your name, a search result, or an error message, it's doing exactly that: manipulating strings. PHP has a huge built-in toolkit of functions that do the heavy lifting so you don't have to write the logic yourself.
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.
creating_strings.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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 = <<<EOTDear $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;
Output
Thank you for purchasing Wireless Headphones!
Sarah Connor
Dear Sarah,
Your order for Wireless Headphones has been confirmed.
Thank you for shopping with us!
⚠ Watch Out: Single vs Double Quotes
If you write echo 'Hello $firstName'; with single quotes, PHP will literally print the dollar sign and the word firstName — it won't swap in the variable value. Always use double quotes when you want variable interpolation to work.
📊 Production Insight
Using single quotes when you need variable interpolation silently prints the raw variable name instead of its value.
Always match quote style to intent: double for interpolation, single for literal.
This seems trivial but causes confusing bugs in log messages and dynamic queries.
🎯 Key Takeaway
Double quotes interpolate variables.
Single quotes treat everything literally.
Choose deliberately, don't just type quotes out of habit.
thecodeforge.io
Php Strings String Functions
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.
string_functions.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?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";
Output
Raw length (with spaces): 21
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
💡Pro Tip: PHP 8's str_contains() Is Your Friend
Before PHP 8, checking if a string contained a word meant using strpos() !== false — an ugly pattern that trips up beginners (see Gotchas below). If you're on PHP 8+, use str_contains(), str_starts_with(), and str_ends_with() instead. They return plain true/false and read like plain English.
📊 Production Insight
Choosing the wrong function for the task leads to subtle bugs — using strpos() instead of str_contains() when you just need a boolean.
Performance matters: strpos() is slightly faster than str_contains() for very large strings, but readability wins in 99% of cases.
Always test with edge cases: empty string, single character, UTF-8 content.
🎯 Key Takeaway
Group string functions by purpose: measure, trim, case, search, replace, split.
For simple existence checks, use str_contains() (PHP 8+) or strpos() !== false.
The return value type matters — always check it strictly.
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.
🔥Interview Gold: sprintf vs echo with concatenation
Interviewers love asking why you'd choose sprintf over just echoing concatenated strings. The answer: sprintf returns a value you can store, reuse, or pass to another function. echo just prints and discards. sprintf also keeps your template and data cleanly separated, which makes complex formatted output far more maintainable.
📊 Production Insight
Using concatenation for complex strings leads to hard-to-read code and increased risk of missing spaces or quotes.
sprintf() is essential for internationalisation: placeholders make it easy to swap translated strings.
Watch out for %% to print a literal percent sign — a single % will be interpreted as a format placeholder.
🎯 Key Takeaway
sprintf() separates template from data — cleaner than concatenation.
number_format() adds commas and decimals for readable numbers.
Use placeholders (%s, %d, %.2f) and always escape % with %% to print a literal percent.
thecodeforge.io
Php Strings String Functions
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.
search_and_replace.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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', 'AliceMerritt', 'June2025'], // 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";
Output
Welcome to TheCodeForge! Written by Alice Merritt on June 2025.
I love ***! *** is awesome. *** rocks.
Safe output: <script>alert("You have been hacked!");</script>
Is email valid: Yes
⚠ Watch Out: Never echo Raw User Input
If a user submits <script>...</script> in a form and you echo it directly without htmlspecialchars(), their script runs in every visitor's browser. This is called XSS (Cross-Site Scripting) and it's one of the most common web vulnerabilities. One line — htmlspecialchars($value, ENT_QUOTES, 'UTF-8') — fixes it every time.
📊 Production Insight
Missing htmlspecialchars() is the root cause of 70% of XSS vulnerabilities in PHP applications.
Using str_replace() for simple string replacement is fast, but for patterns use preg_replace() with careful regex to avoid catastrophic backtracking.
Always test your search/replace with edge cases: empty strings, overlapping matches, and UTF-8 characters.
🎯 Key Takeaway
Sanitise user output with htmlspecialchars() before echo — non-negotiable.
Use str_replace() for simple replacements; preg_match()/preg_replace() for patterns.
Case-insensitive replacements? Use str_ireplace() or regex with /i flag.
String Comparison, Sorting, and Multibyte Safety
Comparing strings in PHP isn't always straightforward. The == operator performs type coercion, which can lead to unexpected results. '123' == 123 is true, but '123abc' == 123 is also true because PHP converts the string to a number. For strict comparison, use === which checks both value and type. For string-specific comparison, use strcmp() which returns 0 if equal, negative if first is less, positive if first is greater — and it's binary safe.
When dealing with accented characters (é, ñ, ü) or non-Latin scripts (Cyrillic, Chinese, Arabic), standard functions like strlen() and strtolower() break. They count bytes, not characters. A single emoji like 😀 is 4 bytes. Use the mb_ (multibyte) family of functions: mb_strlen(), mb_strtolower(), mb_substr(), etc. They respect character encoding and count actual characters.
Sorting user-generated lists? Use strnatcmp() for natural order (e.g., 'img2.jpg' before 'img10.jpg') and setlocale() with strcoll() for locale-aware sorting.
If your application supports any language beyond plain English, always use mb_strlen(), mb_strtolower(), mb_substr(), and other mb_ versions. The standard functions will silently produce wrong results for multi-byte characters.
📊 Production Insight
Using strlen() on UTF-8 text in a multilingual app leads to incorrect character counts, breaking validation, truncation, and search.
A common bug: checking password length with strlen() when the password contains emojis — a 4-character password can be 16 bytes, causing false rejections.
Multibyte functions have a performance cost; they are slower than byte-oriented functions, but correctness trumps speed here.
🎯 Key Takeaway
Use === for strict string comparison; avoid ==.
For multibyte strings, always use mb_ functions — strlen() counts bytes, not characters.
Natural sorting with natsort() prevents 'img10.jpg' appearing before 'img2.jpg'.
Don't Escape Blindly — When to Use addcslashes() vs addslashes()
Every junior reaches for addslashes() like it's a magic shield. It's not. It's a blunt instrument that escapes single quotes, double quotes, backslashes, and null bytes. That's it. Good for simple SQL injection prevention if you're stuck in 2007? Maybe. But you're not. addcslashes() gives you surgical precision. You specify exactly which characters to escape. That's control. That's production-grade thinking. The real trap? Charset confusion. If your input is UTF-8 and you escape a multi-byte character that contains a byte matching your escape list, you corrupt the string. Always run addcslashes() after mb_check_encoding() to ensure your string is valid for the target charset. I've debugged corrupt JSON exports on Black Friday because someone escaped a 3-byte emoji thinking one byte was a backslash. Don't be that dev. Escape with intent, not panic.
Never use addslashes() for database escaping. Use prepared statements with PDO. addcslashes() is for custom protocols, CSV exports, or generating escaped shell args — not SQL.
🎯 Key Takeaway
Escaping without context is cargo-cult security. Choose addcslashes() when precision matters; addslashes() only when the spec explicitly demands it.
Stop Messing Around — How to Actually Extract and Replace Substrings
You've used substr() and str_replace(). Good for you. Now let's talk about the two functions that prevent production fires: substr_replace() and strtr(). substr_replace() is the unsung hero for replacing a specific position in a string — like redacting a credit card number or patching a serialized data blob. strtr() is the faster, cleaner alternative to str_replace() when you need to translate many pairs at once. str_replace() scans the string once for each needle. strtr() does it in one pass. That means predictable behavior when replacements overlap. Real-world example: sanitizing template variables. If you have {{name}} and {{name_first}}, str_replace() can corrupt the longer token. strtr() won't. I once watched a billing system append '{{name_last}}' to '{{name}}' because of this exact bug. One-pass translation saved Christmas.
substring_mastery.phpPHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
// Safe one-pass replacement with strtr
$template = "Hello {{name}}, your order #{{order_id}} is ready.";
$replacements = [
'{{name}}' => 'Alice',
'{{order_id}}' => 'ORD-2024-001',
];
echostrtr($template, $replacements);
// Output: Hello Alice, your order #ORD-2024-001 is ready.// Precise position replacement with substr_replace
$card = "4111-1111-1111-1111";
$redacted = substr_replace($card, "****-****-****-", 0, 14);
echo $redacted;
// Output: ****-****-****-1111
Output
Hello Alice, your order #ORD-2024-001 is ready.
****-****-****-1111
🔥Performance Tip:
When replacing >10 pairs, strtr() is up to 5x faster than str_replace() and eliminates overlapping-match bugs. For <5 replacements, str_replace() is simpler and fine.
🎯 Key Takeaway
For secure, predictable text manipulation, use strtr() for maps and substr_replace() for positional surgery — never mix the two.
● Production incidentPOST-MORTEMseverity: high
XSS via Unsanitised Product Descriptions Took Down a Major Retailer
Symptom
Users reported fake login pop-ups on product pages. The security team found that product descriptions and reviews were displayed on the page without escaping HTML.
Assumption
The team assumed that since the CMS team validated input on submission, the output was safe. They were wrong — stored XSS doesn't need runtime input.
Root cause
The product detail template used echo $review->text; instead of echo htmlspecialchars($review->text, ENT_QUOTES, 'UTF-8');. PHP's default behavior is to output raw text, and the CMS validation only blocked explicit <script> tags but allowed other HTML like <img onerror>.
Fix
Applied htmlspecialchars() to all user-generated text in views, added a global output filter using PHP's output buffering with callback, and set Content-Security-Policy HTTP headers.
Key lesson
Never trust that input validation alone secures output.
Always apply a context-appropriate encoding function (HTML, JS, URL) before rendering.
Automate XSS scanning in CI/CD with tools like OWASP ZAP or SonarQube rules.
Production debug guideSymptom → Action guide for the most common string-related failures.5 entries
Symptom · 01
echo $someString outputs nothing (blank) but you expected text
→
Fix
Check if the variable is undefined or null. Use var_dump($someString); and set error_reporting(E_ALL); in development. Also check if output buffering (ob_start) is interfering.
Symptom · 02
strpos($haystack, $needle) evaluates to true when match is at position 0 but you expect false
→
Fix
Replace if (strpos(...)) with if (strpos(...) !== false). Upgrade to PHP 8+ and use str_contains() for clarity.
Symptom · 03
User-submitted text causes JavaScript errors or pop-ups
→
Fix
Check if htmlspecialchars() is applied before echo. Look for missing ENT_QUOTES flag or wrong encoding parameter.
Symptom · 04
strlen() returns a different count than expected for multi-byte characters (e.g., é, 日本)
→
Fix
Use mb_strlen() instead of strlen(). Ensure the mbstring extension is enabled and default_charset is set to UTF-8.
Symptom · 05
strtotime() returns false for date strings
→
Fix
Check format. Use DateTime::createFromFormat() for custom formats. Enable error-reporting to see warnings.
★ Quick XSS Debug Cheat Sheet for PHPWhen you suspect cross-site scripting via unsanitised strings, follow this protocol.
JavaScript alert displayed on page−
Immediate action
Check if user-generated content appears in page source as raw HTML.
echo mb_detect_encoding($string); to check current encoding
Add `<meta charset='UTF-8'>` in HTML head and set `default_charset='UTF-8'` in php.ini
Fix now
Use mb_ functions for all string operations on user input.
`strpos($haystack, $needle)` returns false on valid match+
Immediate action
Check if you need strict comparison (`===`).
Commands
var_dump(strpos('abc', 'a')); // outputs int(0), not false
echo gettype(strpos('abc', 'a')); // should be integer
Fix now
Replace if(strpos(...) != false) with if(strpos(...) !== false) or use str_contains() if PHP 8+.
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
Compare strings (binary safe)
strcmp()
Integer (-1, 0, 1)
All versions
Count multibyte characters
mb_strlen()
Integer (character count)
All versions (mbstring required)
Natural sort order
natsort()
Sorted array (modifies input)
All versions
⚙ Quick Reference
7 commands from this guide
File
Command / Code
Purpose
creating_strings.php
$productName = 'Wireless Headphones';
What Is a PHP String and How Do You Create One?
string_functions.php
$userInput = ' Hello, World! ';
The Most Useful PHP String Functions You'll Use Every Day
string_formatting.php
$itemName = 'Mechanical Keyboard';
Formatting Strings for Output
search_and_replace.php
$blogTemplate = 'Welcome to [site-name]! Written by [author-name] on [date].';
Searching and Replacing Text
comparison_multibyte.php
$value1 = '123';
String Comparison, Sorting, and Multibyte Safety
escape_compare.php
$input = "O'Reilly \ "Best" PHP Guide";
Don't Escape Blindly
substring_mastery.php
$template = "Hello {{name}}, your order #{{order_id}} is ready.";
Stop Messing Around
Key takeaways
1
Double quotes allow variable interpolation; single quotes treat everything literally
choose deliberately, not by habit.
2
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+.
3
Always sanitise user input with htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before echoing it
skipping this is an XSS vulnerability waiting to happen.
4
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.
5
For multilingual text, always use mb_ functions like mb_strlen() instead of strlen()
the standard functions count bytes, not characters.
Common mistakes to avoid
3 patterns
×
Using == to check if strpos() returned false
Symptom
strpos() returns 0 when match is at first character, and 0 == false is true in PHP loose comparison, causing a false negative for 'not found'.
Fix
Always use === for strpos() checks: if (strpos($haystack, $needle) === false). Better yet, use str_contains() on PHP 8+.
×
Forgetting that string indexes start at 0
Symptom
substr($email, 1) is used to skip the first character but actually returns from the second character onward because index 1 is the second character.
Fix
Remember that string indexes are zero-based. The first character is at position 0.
×
Echoing unsanitised user input
Symptom
XSS vulnerabilities allow attackers to inject executable scripts that run in visitors' browsers, leading to data theft or defacement.
Fix
Always wrap user-supplied data in htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before echoing. Make this a non-negotiable habit.
INTERVIEW PREP · PRACTICE MODE
Interview Questions on This Topic
Q01JUNIOR
What is the difference between single-quoted and double-quoted strings i...
Q02SENIOR
Why is if (strpos($str, 'word') == false) a bug, and how do you fix it?
Q03SENIOR
If you had to extract the domain name from a list of email addresses sto...
Q04SENIOR
How do you handle multibyte strings in PHP? When should you use mb_ func...
Q01 of 04JUNIOR
What is the difference between single-quoted and double-quoted strings in PHP, and when would you deliberately choose one over the other?
ANSWER
Single-quoted strings are taken literally — no variable interpolation, no escape sequences except \\ and \'. Double-quoted strings parse variables and interpret escape sequences like \n, \t. Use double quotes when you need to embed variables or escape sequences; use single quotes when you want to ensure exact output (e.g., file paths, regular expressions). Double-quoted strings are slightly slower because PHP scans for variables.
Q02 of 04SENIOR
Why is if (strpos($str, 'word') == false) a bug, and how do you fix it?
ANSWER
strpos() returns the integer position (0-based) of the substring, or false if not found. Since false == 0 is true in PHP loose comparison, when 'word' starts at index 0, strpos() returns 0, and 0 == false evaluates to true — so the condition incorrectly treats it as 'not found'. Fix: use strict comparison (===) like if (strpos($str, 'word') === false). On PHP 8+, use str_contains() which returns a boolean directly.
Q03 of 04SENIOR
If 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?
ANSWER
I would combine explode() and trim(). First, explode('@', $email) splits the email into an array where index 1 contains the domain part. Then trim() to remove any extra whitespace. For simple extraction, that's sufficient. If I needed to validate the domain, I'd use filter_var($email, FILTER_VALIDATE_EMAIL) first. For a more robust approach, use regex with preg_match('/@(.+)$/', $email, $matches) to capture the domain.
Q04 of 04SENIOR
How do you handle multibyte strings in PHP? When should you use mb_ functions?
ANSWER
Use the mb_ (multibyte) family of functions: mb_strlen(), mb_strtolower(), mb_substr(), mb_strpos(), etc. These functions respect character encoding (UTF-8 by default) and count/operate on actual characters rather than bytes. Standard functions like strlen() count bytes — for UTF-8, a single character like 'é' or an emoji can be 2-4 bytes. Always use mb_ functions when your application handles text that may contain accented characters, non-Latin scripts, or emojis. Ensure the mbstring extension is enabled and default_charset is set to UTF-8 in php.ini.
01
What is the difference between single-quoted and double-quoted strings in PHP, and when would you deliberately choose one over the other?
JUNIOR
02
Why is if (strpos($str, 'word') == false) a bug, and how do you fix it?
SENIOR
03
If 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?
SENIOR
04
How do you handle multibyte strings in PHP? When should you use mb_ functions?
SENIOR
FAQ · 5 QUESTIONS
Frequently Asked Questions
01
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.
Was this helpful?
02
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.
Was this helpful?
03
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.
Was this helpful?
04
How do I convert a string to lowercase in PHP correctly for all languages?
Use mb_strtolower() instead of strtolower(). strtolower() only handles ASCII characters — for accented characters like 'É' it leaves them uppercase. mb_strtolower() respects the UTF-8 encoding and correctly lowercases all Unicode characters.
Was this helpful?
05
What is the most efficient way to build a long string from many parts in PHP?
Use an array with implode(). For example, $parts = []; foreach (...) { $parts[] = $value; } $result = implode('', $parts);. Avoid repeated concatenation with .= inside a loop because it creates many intermediate strings and increases memory. For very large strings, consider using output buffering (ob_start/ob_get_clean) or PHP's SplFixedArray with implode.