MidТеория6 min

Строковые функции

substr, strpos, str_contains, str_starts_with, mb_* функции

Строковые функции PHP

Поиск в строках

str_contains, str_starts_with, str_ends_with (PHP 8.0+)

<?php
declare(strict_types=1);

$text = 'Hello, World!';

// str_contains — checks if string contains substring
var_dump(str_contains($text, 'World'));  // true
var_dump(str_contains($text, 'world'));  // false (case-sensitive!)
var_dump(str_contains($text, ''));       // true (empty string always found)

// str_starts_with — checks if string starts with prefix
var_dump(str_starts_with($text, 'Hello'));  // true
var_dump(str_starts_with($text, 'hello'));  // false

// str_ends_with — checks if string ends with suffix
var_dump(str_ends_with($text, '!'));      // true
var_dump(str_ends_with($text, 'World!')); // true

Запомни: str_contains(), str_starts_with(), str_ends_with() — появились в PHP 8.0. До этого использовали strpos() !== false. Все три функции регистрозависимы и принимают пустую строку как валидное значение (возвращают true).

strpos и strrpos

<?php
declare(strict_types=1);

$text = 'Hello World Hello';

// strpos — find FIRST occurrence (left to right)
echo strpos($text, 'Hello');    // 0
echo strpos($text, 'World');    // 6
echo strpos($text, 'PHP');      // false (not found)

// With offset (start search from position)
echo strpos($text, 'Hello', 1); // 12 (skips first occurrence)

// strrpos — find LAST occurrence (right to left)
echo strrpos($text, 'Hello');   // 12

// Case-insensitive versions
echo stripos($text, 'hello');   // 0
echo strripos($text, 'hello');  // 12

Ловушка экзамена: strpos() возвращает 0 когда подстрока найдена в начале строки. 0 является falsy! Поэтому НИКОГДА не проверяйте if (strpos(...)) — используйте строгое сравнение if (strpos($str, $needle) !== false). В PHP 8.0+ лучше использовать str_contains().

<?php
declare(strict_types=1);

$text = 'Hello World';

// WRONG! 0 is falsy
if (strpos($text, 'Hello')) {
    echo 'Found';  // NOT executed! 0 is falsy
} else {
    echo 'Not found';  // THIS executes (WRONG!)
}

// CORRECT with strict comparison
if (strpos($text, 'Hello') !== false) {
    echo 'Found';  // Correct
}

// BEST: use str_contains (PHP 8.0+)
if (str_contains($text, 'Hello')) {
    echo 'Found';  // Clean and correct
}

substr_count

<?php
declare(strict_types=1);

$text = 'banana';
echo substr_count($text, 'an');  // 2
echo substr_count($text, 'a');   // 3

// With offset and length
echo substr_count($text, 'a', 2);     // 2 (search from position 2)
echo substr_count($text, 'a', 2, 3);  // 1 (search in 'nan')

Извлечение подстрок

substr

<?php
declare(strict_types=1);

$text = 'Hello, World!';

echo substr($text, 0, 5);    // Hello
echo substr($text, 7);       // World!
echo substr($text, -6);      // orld!  (from 6th char from end)
echo substr($text, -6, 5);   // orld   (5 chars from 6th from end)
echo substr($text, 0, -1);   // Hello, World (all except last char)

// Empty/false results
echo substr($text, 20);      // '' (empty string, PHP 8.0+)
// In PHP 7: returned false

Ловушка экзамена: Начиная с PHP 8.0, substr() возвращает пустую строку '' вместо false когда offset больше длины строки. В PHP 7 возвращал false. Это может сломать старый код с проверкой === false.

substr_replace

<?php
declare(strict_types=1);

$text = 'Hello World';

echo substr_replace($text, 'PHP', 6);      // Hello PHP
echo substr_replace($text, 'PHP', 6, 5);   // Hello PHP
echo substr_replace($text, 'Dear ', 0, 0); // Dear Hello World (insert)
echo substr_replace($text, '', 5, 6);       // Hello (delete)

Преобразование строк

Регистр

<?php
declare(strict_types=1);

$text = 'hello world';

echo strtoupper($text);     // HELLO WORLD
echo strtolower('HELLO');   // hello
echo ucfirst($text);        // Hello world
echo lcfirst('Hello');      // hello
echo ucwords($text);        // Hello World

// ucwords with custom delimiter
echo ucwords('hello-world-test', '-');  // Hello-World-Test

// Multibyte versions (for UTF-8)
echo mb_strtoupper('привет');    // ПРИВЕТ
echo mb_strtolower('ПРИВЕТ');    // привет
// No mb_ucfirst in PHP! Use:
function mb_ucfirst(string $str, string $encoding = 'UTF-8'): string
{
    $first = mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding);
    $rest = mb_substr($str, 1, null, $encoding);
    return $first . $rest;
}

Обрезка (trim)

<?php
declare(strict_types=1);

$text = '  Hello World  ';

echo trim($text);        // 'Hello World'    (both sides)
echo ltrim($text);       // 'Hello World  '  (left only)
echo rtrim($text);       // '  Hello World'  (right only)

// Custom characters to trim
echo trim('***Hello***', '*');   // 'Hello'
echo trim('xxHelloxx', 'x');    // 'Hello'

// trim removes: " " (space), "\t" (tab), "\n" (newline),
// "\r" (carriage return), "\0" (null), "\v" (vertical tab)

Замена

<?php
declare(strict_types=1);

$text = 'Hello World';

// str_replace — case-sensitive
echo str_replace('World', 'PHP', $text);        // Hello PHP
echo str_replace(['Hello', 'World'], ['Hi', 'PHP'], $text); // Hi PHP

// With count parameter
$count = 0;
echo str_replace('l', 'L', $text, $count);
echo $count;  // 3 (three 'l' characters replaced)

// str_ireplace — case-insensitive
echo str_ireplace('world', 'PHP', $text);  // Hello PHP

// strtr — translate characters
echo strtr($text, 'lo', 'LO');  // HeLLO WOrLd
echo strtr($text, ['Hello' => 'Hi', 'World' => 'PHP']);  // Hi PHP

Padding

<?php
declare(strict_types=1);

$num = '42';

echo str_pad($num, 5);               // '42   '  (right pad with spaces)
echo str_pad($num, 5, '0', STR_PAD_LEFT);  // '00042' (left pad with zeros)
echo str_pad($num, 5, '-', STR_PAD_BOTH);  // '-42--' (both sides)

echo str_pad($num, 8, 'ab');         // '42ababab' (repeating pattern)

Разбиение и объединение

<?php
declare(strict_types=1);

// explode — split string to array
$csv = 'apple,banana,cherry';
$fruits = explode(',', $csv);
// ['apple', 'banana', 'cherry']

// With limit
$parts = explode(',', $csv, 2);
// ['apple', 'banana,cherry'] — max 2 elements

// Negative limit (PHP 7.0+)
$parts = explode(',', $csv, -1);
// ['apple', 'banana'] — removes last N elements

// implode / join — array to string
$result = implode(', ', $fruits);  // 'apple, banana, cherry'
$result = implode('', $fruits);    // 'applebananacherry'

// implode with single argument (array only, PHP 7.4+)
$result = implode($fruits);  // Deprecated! Always pass both arguments

// str_split — split into chunks
$chars = str_split('Hello');    // ['H', 'e', 'l', 'l', 'o']
$chunks = str_split('Hello', 2); // ['He', 'll', 'o']

// chunk_split — insert separator every N chars
echo chunk_split('abcdefgh', 3, '-');  // 'abc-def-gh-'

// wordwrap
$long = 'The quick brown fox jumped over the lazy dog';
echo wordwrap($long, 15, "\n", true);

Multibyte (mb_*) функции

<?php
declare(strict_types=1);

// ALWAYS set encoding
mb_internal_encoding('UTF-8');

$russian = 'Привет, Мир!';

// Length
echo strlen($russian);     // 21 (bytes)
echo mb_strlen($russian);  // 12 (characters)

// Substring
echo mb_substr($russian, 0, 6);  // Привет

// Position
echo mb_strpos($russian, 'Мир');  // 8

// Case
echo mb_strtoupper($russian);  // ПРИВЕТ, МИР!
echo mb_strtolower($russian);  // привет, мир!

// Detect encoding
echo mb_detect_encoding($russian);  // UTF-8

// Convert encoding
$windows = mb_convert_encoding($russian, 'Windows-1251', 'UTF-8');
$back = mb_convert_encoding($windows, 'UTF-8', 'Windows-1251');

// mb_str_split (PHP 7.4+)
$chars = mb_str_split('Привет');  // ['П', 'р', 'и', 'в', 'е', 'т']

Запомни: Для любой работы с UTF-8 строками (кириллица, иероглифы и т.д.) используйте mb_* функции. Стандартные strlen(), substr(), strpos() работают с БАЙТАМИ и дадут неверные результаты для многобайтовых кодировок.

Форматирование

<?php
declare(strict_types=1);

// sprintf — formatted string
echo sprintf('Name: %s, Age: %d', 'Alice', 25);
// Name: Alice, Age: 25

// Format specifiers
echo sprintf('%05d', 42);        // 00042 (zero-padded)
echo sprintf('%.2f', 3.14159);   // 3.14 (2 decimal places)
echo sprintf('%10s', 'right');   //      right (right-aligned)
echo sprintf('%-10s|', 'left');  // left      | (left-aligned)
echo sprintf('%+d', 42);         // +42 (with sign)
echo sprintf('%x', 255);         // ff (hexadecimal)
echo sprintf('%o', 8);           // 10 (octal)
echo sprintf('%b', 10);          // 1010 (binary)
echo sprintf('%%');               // % (literal percent)

// Argument swapping
echo sprintf('%2$s is %1$d years old', 25, 'Alice');
// Alice is 25 years old

// number_format
echo number_format(1234567.891, 2, '.', ',');
// 1,234,567.89

echo number_format(1234567.891, 2, ',', ' ');
// 1 234 567,89 (European format)

Вопросы с экзамена ZCE

Проверь себя

5 из 100

Какие из сравнений вернут true? ```php var_dump( 't' == t, 1 === "1time", "top" == 0, "top" === 0, 1 == "1time" ); ```

Выберите все правильные варианты

Что выведет следующий PHP-скрипт? ```php $dom = new DOMDocument(); $dom->load('book.xml'); $a = $dom->documentElement; print_r($a); ```

Что нужно подставить вместо `?????` в коде? ```php $msg = "The Quick Brown Foxed Jumped Over the Lazy Dog"; $state = true; $retval = ""; for ($i = 0; (isset(?????)); $i++) { if ($state) $retval .= strtolower(?????); else $retval .= strtoupper(?????); $state = !$state; } print $retval; ```

Что выведет следующий код? ```php $a = "0"; echo strlen($a); echo empty($a) ? $a : 5; echo $a ?: 5; ```

Что вернёт `strlen('Мир')` для UTF-8?

Code Challenges

Проверка палиндрома

Напишите функцию, которая проверяет, является ли строка палиндромом (без учёта регистра и пробелов).

Test Cases

1. Input: racecar→ Expected: true
2. Input: Race Car→ Expected: true
3. Input: hello→ Expected: false
4. Input: A man a plan a canal Panama→ Expected: true

Проверка анаграммы

Напишите функцию, которая проверяет, являются ли две строки анаграммами (без учёта регистра и пробелов).

Test Cases

1. Input: "listen", "silent"→ Expected: true
2. Input: "Hello", "olleh"→ Expected: true
3. Input: "hello", "world"→ Expected: false
4. Input: "Astronomer", "Moon starer"→ Expected: true

Подсчёт гласных

Напишите функцию, которая подсчитывает количество гласных (a, e, i, o, u) в строке (без учёта регистра).

Test Cases

1. Input: hello→ Expected: 2
2. Input: AEIOU→ Expected: 5
3. Input: rhythm→ Expected: 0
4. Input: Programming→ Expected: 3

Группировка анаграмм

Напишите функцию, которая группирует строки по анаграммам. Результат — массив групп.

Test Cases

1. Input: ["eat","tea","tan","ate","nat","bat"]→ Expected: [["eat","tea","ate"],["tan","nat"],["bat"]]
2. Input: [""]→ Expected: [[""]]
3. Input: ["a"]→ Expected: [["a"]]