Основы
Переменные, типы и константы
Переменные PHP начинаются с $ и являются динамически типизированными. PHP 7.4+ поддерживает типизированные свойства. Используйте define() для констант времени выполнения и const для констант времени компиляции (быстрее). PHP 8.1 представил enum — типизированную систему перечислений, превосходящую константы классов. Всегда объявляйте типы, где возможно (PHP 7+), для раннего обнаружения ошибок и лучшей поддержки IDE.
<?php
$name = "Alice"; // string
$age = 30; // integer
$price = 19.99; // float (double)
$active = true; // boolean
$items = [1, 2, 3]; // array
$null = null; // null
// constants
define("MAX_USERS", 100); // runtime constant
const PI = 3.14159; // compile-time constant
echo MAX_USERS; // no $ prefix
// PHP 8.1+ enums
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
}
$s = Status::Active;Echo, print и отладка
echo — языковая конструкция (не функция) — самая быстрая для вывода. print возвращает 1, поэтому может использоваться в выражениях. printf/sprintf используют C-стиль спецификаторов формата (%s строка, %d int, %f float, %x hex). var_dump() — основной инструмент отладки — показывает типы и значения. error_log() пишет в лог ошибок PHP или syslog. В продакшене никогда не показывайте отладочный вывод пользователям.
<?php
// echo: no return, multiple args (fastest)
echo "Hello", " ", "World";
// print: returns 1, single arg
print "Hello World";
// printf: formatted output
printf("Name: %s, Age: %d, Price: %.2f", "Alice", 30, 19.99);
// debugging output
print_r($array); // human-readable
var_dump($variable); // type + value (detailed)
var_export($array, true); // valid PHP code (for caching)
// sprintf: return formatted string (don't print)
$log = sprintf("[%s] %s", date('H:i:s'), "Started");
error_log($log); // log to error logОператоры и сравнения
Всегда используйте === (строгое сравнение) для избежания багов приведения типов. == преобразует типы перед сравнением, что даёт неожиданные результаты (0 == 'abc' было true в PHP 7). Оператор корабля (<=>) возвращает -1/0/1 — полезен для usort. Оператор объединения с null (??) — идиоматичный способ предоставить значения по умолчанию. Null-safe оператор (?->) (PHP 8+) сокращённо обрабатывает цепочки методов на null, заменяя многословные проверки isset().
<?php
// arithmetic
$sum = 10 + 3; // 13
$mod = 10 % 3; // 1
$pow = 2 ** 3; // 8 (PHP 5.6+)
// comparison: == vs ===
echo (0 == "abc"); // true (loose, PHP 7-); false (PHP 8+)
echo (0 === "abc"); // false (strict — type + value)
echo ("1" == 1); // true (loose)
echo ("1" === 1); // false (strict)
// spaceship operator (PHP 7+)
echo 1 <=> 2; // -1 (less than)
echo 2 <=> 2; // 0 (equal)
echo 3 <=> 2; // 1 (greater than)
// null coalescing
$name = $input ?? "default"; // if $input is null
$deep = $data['user']['name'] ?? "Anonymous";
// null safe operator (PHP 8+)
$country = $user?->getAddress()?->country; // null if any step is nullСуперглобалы и веб
Суперглобалы — встроенные ассоциативные массивы, доступные во всех областях видимости. $_GET и $_POST содержат пользовательский ввод — ВСЕГДА санитизируйте/валидируйте перед использованием. filter_input() безопаснее прямого доступа. Никогда не доверяйте значениям $_SERVER, которые могут быть подделаны клиентами (например, HTTP_USER_AGENT). Всегда вызывайте exit после header('Location:') — иначе PHP продолжит выполнение. Начинайте сессии с session_start() до любого вывода.
<?php
// superglobals available everywhere
$_GET['name']; // query string params
$_POST['email']; // form POST data
$_REQUEST['x']; // GET + POST + COOKIE
$_SERVER['HTTP_HOST']; // server/env info
$_SERVER['REQUEST_METHOD']; // GET, POST, etc.
$_COOKIE['session']; // cookies
$_FILES['upload']; // file uploads
$_SESSION['user_id']; // session data (after session_start())
// get client IP
$ip = $_SERVER['REMOTE_ADDR'];
// check request method
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
}
// redirect
header("Location: /dashboard");
exit; // always exit after redirectInclude и require
include/require выполняют указанный файл. require вызывает фатальную ошибку при отсутствии файла (используйте для критичных зависимостей); include только предупреждает (используйте для опциональных шаблонов). Варианты _once отслеживают включённые файлы для предотвращения двойного включения — необходимы для определений функций/классов. Автозагрузчик Composer (require_once 'vendor/autoload.php') устраняет ручное управление include. Файлы могут возвращать значения, что полезно для конфигурации.
<?php
// include: warning on failure, continues
include 'header.php';
include_once 'config.php'; // only once
// require: fatal error on failure, stops
require 'database.php';
require_once 'vendor/autoload.php'; // Composer autoload
// _once variants prevent re-declaration errors
// use require for critical files (DB config, autoloaders)
// use include for optional files (templates)
// return values from included files
$config = include 'config.php';
// config.php: return ['db' => 'mysql://...', 'debug' => true];Строки
Строковые функции
В PHP более 100 строковых функций. strpos() возвращает false, если не н айдено — используйте === false для проверки (0 — валидная позиция). str_replace() может принимать массивы для поиска/замены. substr() поддерживает отрицательные смещения (с конца). Для мультибайтных строк (UTF-8) используйте mb_* эквиваленты (mb_strlen, mb_substr) — strlen считает байты, а не символы. Всегда устанавливайте default_charset='UTF-8' и используйте mb_* функции для не-ASCII текста.
<?php
$s = "Hello, World";
// length and case
echo strlen($s); // 12
echo str_word_count($s); // 2
echo strtoupper($s); // HELLO, WORLD
echo strtolower($s); // hello, world
echo ucfirst("hello"); // Hello
echo ucwords("hello world"); // Hello World
// search and replace
echo strpos($s, "World"); // 7 (false if not found)
echo str_replace("o", "0", $s); // Hell0, W0rld
echo substr($s, 0, 5); // Hello
echo substr($s, -5); // World
echo strrev($s); // dlroW ,olleH
// trim
echo trim(" hi "); // "hi"
echo ltrim(" hi"); // "hi"
echo rtrim("hi "); // "hi"Интерполяция строк и heredoc
Строки в двойных кавычках интерполируют переменные; в одинарных — нет (используйте одинарные для литерального текста — немного быстрее). Используйте {$var} для сложных выражений (свойства объекта, доступ к массиву, вызовы методов). Heredoc (<<<ID) идеален для многострочных строк вроде SQL или HTML — интерполирует переменные. Nowdoc (<<<'ID') — неинтерпретируемая версия, полезная для regex-шаблонов с обратными слэшами.
<?php
$name = "Alice";
$age = 30;
// double quotes: variable interpolation
echo "Hello, $name!"; // Hello, Alice!
echo "Hello, {$name}!"; // Hello, Alice! (braces for clarity)
echo "Age: {$age}"; // Age: 30
// single quotes: no interpolation (faster)
echo 'Hello, $name'; // Hello, $name (literal)
// complex expressions need braces
echo "Result: {$obj->method()}";
echo "Item: {$array['key']}";
// heredoc: multi-line, interpolates
$sql = <<<SQL
SELECT * FROM users
WHERE name = '$name'
AND age > $age
SQL;
// nowdoc: multi-line, NO interpolation (like single quotes)
$regex = <<<'REGEX'
\d{3}-\d{4}
REGEX;sprintf и форматирование
sprintf() необходима для безопасного построения форматированных строк — в отличие от интерполяции строк, она обрабатывает преобразования типов и заполнение. Используйте %d для целых чисел (не %s) для числового форматирования. number_format() форматирует числа с разделителями разрядов — критично для отображения валюты. Всегда используйте sprintf для SQL-фрагментов в подготовленных запросах (хотя подготовленные запросы всё равно требуются для пользовательского ввода).
<?php
// sprintf: format string (returns, doesn't print)
$formatted = sprintf(
"%-10s | %5d | %8.2f",
"Alice", 42, 19.99
);
echo $formatted; // "Alice | 42 | 19.99"
// format specifiers:
// %s string, %d int, %f float, %x hex, %b binary, %c char
// %5d right-padded to width 5
// %-5d left-padded
// %05d zero-padded
// %.2f 2 decimal places
// %8.2f width 8, 2 decimals
// numbered placeholders
echo sprintf("Hi %1$s, bye %1$s", "Alice"); // Hi Alice, bye Alice
// number_format
echo number_format(1234567.891, 2); // 1,234,567.89
echo number_format(1234567.89, 2, ',', '.'); // European formatRegex (PCRE)
PHP использует PCRE (Perl-Compatible Regular Expressions) с разделителями /pattern/. preg_match возвращает 1 при совпадении, 0 при отсутствии (используйте ===, не ==, так как 0 falsy). Всегда валидируйте пользовательский ввод regex, но не полагайтесь только на него — используйте filter_var() для email, URL. preg_replace мощный, но может быть медленным на больших строках. Используйте [^...] для белого списка символов, а не чёрного списка. Флаг i делает сопоставление нечувствительным к регистру.
<?php
// preg_match: test pattern (returns 0 or 1)
if (preg_match('/^[a-z]+$/i', "Hello")) {
echo "alphabetic";
}
// capture groups
preg_match('/(d{4})-(d{2})-(d{2})/', "2024-01-15", $matches);
// $matches[0] = "2024-01-15" (full match)
// $matches[1] = "2024" (group 1)
// $matches[2] = "01"
// $matches[3] = "15"
// preg_match_all: all matches
preg_match_all('/d+/', "a1 b22 c333", $matches);
// $matches[0] = ["1", "22", "333"]
// preg_replace: substitute
$clean = preg_replace('/[^a-z0-9]/i', '', "Hello, World!"); // HelloWorld
// preg_split: split by pattern
$parts = preg_split('/[s,]+/', "one, two,three four");
// ["one", "two", "three", "four"]Мультибайтность и кодировки
Строковые функции PHP по умолчанию байт-ориентированные, а не символьно-ориентированные — они ломаются на мультибайтных символах (UTF-8, китайский, эмодзи). Всегда используйте mb_* функции (mb_strlen, mb_substr, mb_strpos, mb_strtoupper) для не-ASCII текста. Устанавливайте mb_internal_encoding('UTF-8') в начале приложения. Используйте JSON_UNESCAPED_UNICODE для сохранения китайского/эмодзи читаемым в JSON-выводе. Это частый источник багов в международных приложениях.
<?php
// UTF-8 strings: use mb_* functions
$text = "Café"; // 4 chars, 5 bytes (é = 2 bytes)
echo strlen($text); // 5 (bytes!)
echo mb_strlen($text); // 4 (characters!)
echo substr($text, 0, 3); // "Caf" (might break UTF-8!)
echo mb_substr($text, 0, 3); // "Caf" (safe)
// case conversion
echo strtoupper("straße"); // "STRAßE" (wrong!)
echo mb_strtoupper("straße"); // "STRAßE" (correct, locale-aware)
// encoding detection
$encoding = mb_detect_encoding($text);
$utf8 = mb_convert_encoding($text, 'UTF-8', 'auto');
// set internal encoding
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
// JSON with UTF-8
$json = json_encode($data, JSON_UNESCAPED_UNICODE);Массивы
Индексные и ассоциативные массивы
Массивы PHP — фактически упорядоченные hash maps — они работают и как списки, и как словари. Индексные массивы автоматически назначают числовые ключи; ассоциативные используют строковые ключи. isset() возвращает false для null-значений; array_key_exists() возвращает true даже для null. unset() удаляет элемент, но не переиндексирует. Для истинного списка (без пробелов) используйте array_values() для переиндексации после удаления. В PHP 8.1+ есть тип массива readonly.
<?php
// indexed array (numeric keys)
$nums = [10, 20, 30];
$nums[] = 40; // append
echo $nums[0]; // 10
echo count($nums); // 4
// associative array (string keys)
$user = [
"name" => "Alice",
"age" => 30,
"email" => "[email protected]",
];
echo $user["name"]; // Alice
$user["phone"] = "555-1234"; // add key
// mixed keys
$mixed = [0 => "a", "name" => "b", 5 => "c"];
// check key existence
if (isset($user["email"])) { /* ... */ }
if (array_key_exists("name", $user)) { /* ... */ }
// remove element
unset($user["phone"]);Многомерность и итерация
Многомерные массивы — массивы массивов. foreach — идиоматичный способ итерации — быстрее и читаемее циклов for. Используйте &$value для изменения элементов на месте (всегда снимайте ссылку после цикла во избежание багов). array_column() извлекает один столбец из 2D-массива — крайне полезно для преобразования наборов результатов БД. Массивы PHP сохраняют порядок вставки.
<?php
$users = [
["name" => "Alice", "age" => 30],
["name" => "Bob", "age" => 25],
["name" => "Carol", "age" => 35],
];
// iterate with key + value
foreach ($users as $index => $user) {
echo "$index: {$user['name']} ({$user['age']})\n";
}
// modify by reference
foreach ($users as &$user) {
$user['age'] += 1; // increment each age
}
unset($user); // break reference!
// nested iteration
$matrix = [[1, 2], [3, 4], [5, 6]];
foreach ($matrix as $row) {
foreach ($row as $cell) {
echo $cell . " ";
}
echo "\n";
}
// extract column
$names = array_column($users, 'name'); // ["Alice", "Bob", "Carol"]Функции массивов: map, filter, reduce
array_map, array_filter и array_reduce — функциональное трио для массивов. Стрелочные функции (fn() =>) делают их лаконичными. array_filter сохраняет ключи — используйте array_values() для переиндексации при необходимости. array_merge переиндексирует числовые ключи, но сохраняет строковые (поздние значения перезаписывают). array_column, array_chunk и array_slice необходимы для манипуляции данными. Эти функции — основа обработки данных в PHP.