Переменные
Основы переменных
Все переменные в PHP начинаются со знака $. Имена чувствительны к регистру и следуют тем же правилам, что и идентификаторы: начинаются с буквы или подчёркивания, далее буквы, цифры, подчёркивания.
<?php
declare(strict_types=1);
// Naming conventions
$userName = 'Alice'; // camelCase — preferred for variables
$order_total = 100.50; // snake_case — also used, but be consistent
$_private = 'internal'; // leading underscore — sometimes for "private"
// Variables are case-sensitive
$name = 'Alice';
$Name = 'Bob'; // Different variable!
Присваивание по значению и по ссылке
По умолчанию переменные присваиваются по значению -- создаётся копия. Для присваивания по ссылке используется оператор &:
<?php
declare(strict_types=1);
// Assignment by value (copy)
$a = 'Hello';
$b = $a;
$b = 'World';
echo $a; // 'Hello' — original unchanged
// Assignment by reference
$name = 'Alice';
$ref = &$name;
$ref = 'Bob';
echo $name; // 'Bob' — original changed!
// unset() removes reference, not the value
unset($ref);
echo $name; // 'Bob' — value still exists
Ловушка экзамена:
unset()на переменной-ссылке удаляет только саму ссылку, но не исходную переменную и не значение. Послеunset($ref)переменная$nameпродолжает существовать.
unset() и множественное удаление
<?php
declare(strict_types=1);
$a = 1;
$b = 2;
$c = 3;
// Remove multiple variables at once
unset($a, $b, $c);
// After unset — variable is undefined
// echo $a; // Warning: Undefined variable $a
Области видимости (Scope)
PHP имеет три области видимости: глобальную, локальную (функция) и статическую.
Глобальная и локальная область
<?php
declare(strict_types=1);
$globalVar = 'I am global';
function showVar(): void
{
// Cannot access $globalVar here!
// echo $globalVar; // Warning: Undefined variable
$localVar = 'I am local';
echo $localVar; // Works
}
showVar();
echo $globalVar; // Works
// echo $localVar; // Warning: Undefined variable
Запомни: В PHP функции НЕ имеют автоматического доступа к переменным внешней области видимости. Это отличает PHP от JavaScript и Python. Каждая функция имеет собственную изолированную область.
Ключевое слово global и $GLOBALS
<?php
declare(strict_types=1);
$counter = 0;
function increment(): void
{
global $counter;
$counter++;
}
// Alternative: $GLOBALS superglobal array
function incrementAlt(): void
{
$GLOBALS['counter']++;
}
increment();
echo $counter; // 1
incrementAlt();
echo $counter; // 2
Ловушка экзамена:
global $varсоздаёт ссылку на глобальную переменную внутри функции. Если сделатьunset($var)внутри функции -- удалится только локальная ссылка, глобальная переменная останется.$GLOBALS-- суперглобальный массив, доступный везде безglobal.
Замыкания и use
<?php
declare(strict_types=1);
$message = 'Hello';
// Closure captures variable by VALUE (copy at time of creation)
$greet = function (string $name) use ($message): string {
return "{$message}, {$name}!";
};
$message = 'Goodbye';
echo $greet('Alice'); // 'Hello, Alice!' — captured old value
// Capture by REFERENCE
$count = 0;
$increment = function () use (&$count): void {
$count++;
};
$increment();
$increment();
echo $count; // 2
// Arrow functions (PHP 7.4+) — auto-capture by VALUE
$multiplier = 3;
$multiply = fn(int $x): int => $x * $multiplier;
echo $multiply(5); // 15
Ловушка экзамена: Обычные замыкания (
function() use ($var)) захватывают переменную по значению на момент создания замыкания. Стрелочные функции (fn() =>) также захватывают по значению, но автоматически (безuse). Для захвата по ссылке нужен&-- работает только в обычных замыканиях.
Статические переменные
Статическая переменная существует только в локальной области функции, но не теряет значение между вызовами:
<?php
declare(strict_types=1);
function counter(): int
{
static $count = 0;
return ++$count;
}
echo counter(); // 1
echo counter(); // 2
echo counter(); // 3
// $count is not accessible here — it's local to the function
Статические инициализаторы (PHP 8.3+)
<?php
declare(strict_types=1);
function getCache(): SplFixedArray
{
// PHP 8.3+: static initializers can use new and expressions
static $cache = new SplFixedArray(100);
return $cache;
}
function getConfig(): array
{
// PHP 8.3+: expressions in static initializers
static $config = ['timeout' => 30 * 60, 'retries' => 2 + 1];
return $config;
}
Запомни: До PHP 8.3 статические переменные можно было инициализировать только скалярными значениями и массивами. С PHP 8.3+ поддерживаются выражения, включая
new, вызовы функций и арифметические операции.
Variable Variables (Переменные переменных)
PHP позволяет использовать значение одной переменной как имя другой:
<?php
declare(strict_types=1);
$varName = 'hello';
$$varName = 'world';
echo $hello; // 'world'
// Chained variable variables
$a = 'b';
$b = 'c';
$c = 'value';
echo $$$a; // 'value' ($$$a → $$b → $c → 'value')
// Dynamic variable naming
for ($i = 0; $i < 3; $i++) {
${'item_' . $i} = "Value {$i}";
}
echo $item_0; // 'Value 0'
echo $item_1; // 'Value 1'
echo $item_2; // 'Value 2'
Ловушка экзамена: Variable variables не работают с суперглобалами (
$_GET,$_POSTи т.д.) напрямую. Также$$внутри строки в двойных кавычках интерпретируется неоднозначно -- используйте${$var}для ясности. На практике variable variables считаются антипаттерном -- используйте массивы.
Предопределённые переменные (Superglobals)
Суперглобалы -- особые массивы, доступные в любой области видимости без global:
$_GET и $_POST
<?php
declare(strict_types=1);
// URL: /search?q=php&page=2
$query = $_GET['q'] ?? ''; // 'php'
$page = (int)($_GET['page'] ?? 1); // 2
// POST form data
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
// $_REQUEST = $_GET + $_POST + $_COOKIE (order depends on php.ini)
$value = $_REQUEST['key'] ?? 'default';
$_SERVER
<?php
declare(strict_types=1);
// Common $_SERVER keys
$_SERVER['REQUEST_METHOD']; // GET, POST, PUT, DELETE
$_SERVER['HTTP_HOST']; // example.com
$_SERVER['REQUEST_URI']; // /path?query=1
$_SERVER['REMOTE_ADDR']; // Client IP address
$_SERVER['SERVER_PORT']; // 80, 443
$_SERVER['DOCUMENT_ROOT']; // /var/www/html
$_SERVER['SCRIPT_NAME']; // /index.php
$_SERVER['SCRIPT_FILENAME']; // /var/www/html/index.php
$_SERVER['SERVER_PROTOCOL']; // HTTP/1.1
$_SERVER['HTTPS']; // 'on' if HTTPS
$_SERVER['HTTP_USER_AGENT']; // Browser user agent string
$_SERVER['HTTP_REFERER']; // Previous page URL (if sent)
$_SERVER['QUERY_STRING']; // Raw query string: "q=php&page=2"
$_SESSION и $_COOKIE
<?php
declare(strict_types=1);
// Sessions
session_start();
$_SESSION['user_id'] = 42;
$userId = $_SESSION['user_id'] ?? null;
unset($_SESSION['user_id']);
session_destroy();
// Cookies
setcookie('theme', 'dark', time() + 86400, '/', '', true, true);
$theme = $_COOKIE['theme'] ?? 'light';
$_FILES
<?php
declare(strict_types=1);
// File upload structure
// $_FILES['avatar'] contains:
// 'name' => 'photo.jpg' — original filename
// 'type' => 'image/jpeg' — MIME type (DO NOT trust!)
// 'size' => 245678 — file size in bytes
// 'tmp_name' => '/tmp/phpX1Y2Z3' — temporary path on server
// 'error' => UPLOAD_ERR_OK — error code (0 = success)
// 'full_path' => 'photos/photo.jpg' — PHP 8.1+: relative path from browser
if ($_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
move_uploaded_file(
$_FILES['avatar']['tmp_name'],
'/uploads/' . basename($_FILES['avatar']['name']),
);
}
$_ENV и CLI-переменные
<?php
declare(strict_types=1);
// Environment variables
$dbHost = $_ENV['DB_HOST'] ?? 'localhost';
// Alternative: getenv('DB_HOST')
// CLI arguments
// php script.php arg1 arg2
$argc; // 3 (count: script name + 2 args)
$argv; // ['script.php', 'arg1', 'arg2']
// Raw request body (not available in $_POST for JSON)
$json = file_get_contents('php://input');
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
Проверка существования переменных
isset(), empty(), is_null()
Три функции с разным поведением. Таблица ниже -- одна из самых важных для экзамена:
<?php
declare(strict_types=1);
$a = null;
$b = '';
$c = 0;
$d = '0';
$e = [];
$f = false;
// isset() empty() is_null()
// $a (null) false true true
// $b ('') true true false
// $c (0) true true false
// $d ('0') true true false
// $e ([]) true true false
// $f (false) true true false
// $undef false true true (+ Warning)
<?php
declare(strict_types=1);
// isset() — true if variable exists AND is NOT null
$user = ['name' => 'Alice', 'age' => null];
isset($user['name']); // true
isset($user['age']); // false (null!)
isset($user['email']); // false (not set)
// empty() — true for null, '', 0, '0', [], false, 0.0
empty(''); // true
empty(' '); // false! (space is not empty)
empty('0'); // true! (this catches many developers off guard)
// is_null() — strictly checks for null
is_null(null); // true
is_null(''); // false
is_null(0); // false
Ловушка экзамена:
empty('0')возвращаетtrue! Строка'0'считается пустой. Это одна из самых частых ошибок.isset()не вызывает Warning для неопределённых переменных, аis_null()-- вызывает.isset()возвращаетfalseдляnull, даже если переменная существует.
Типизация переменных
В PHP переменные не имеют типа -- значения имеют тип. Переменная может менять тип в любой момент:
<?php
declare(strict_types=1);
$value = 42;
echo gettype($value); // 'integer'
echo get_debug_type($value); // 'int' (PHP 8.0+, more precise)
$value = 'now a string';
echo get_debug_type($value); // 'string'
Приведение типов (Type Casting)
<?php
declare(strict_types=1);
$str = '42abc';
// Explicit casting
$int = (int) $str; // 42
$float = (float) $str; // 42.0
$bool = (bool) $str; // true
$arr = (array) $str; // ['42abc']
// intval() with different bases
$hex = intval('0xFF', 16); // 255
$oct = intval('077', 8); // 63
$bin = intval('1010', 2); // 10
// settype() — modifies variable in place
$var = '100';
settype($var, 'int');
echo $var; // 100 (now integer)
Запомни:
get_debug_type()(PHP 8.0+) предпочтительнееgettype(). Он возвращает точные имена типов (int,string,bool) вместо устаревших (integer,string,boolean). Для объектов возвращает FQCN класса.
compact() и extract()
compact()
Создаёт массив из переменных и их значений:
<?php
declare(strict_types=1);
$name = 'John';
$age = 30;
$city = 'Moscow';
$data = compact('name', 'age', 'city');
// ['name' => 'John', 'age' => 30, 'city' => 'Moscow']
// Useful for passing data to templates/views
// $this->render('profile.html', compact('name', 'age', 'city'));
extract()
Обратная операция -- создаёт переменные из массива:
<?php
declare(strict_types=1);
$data = ['city' => 'Moscow', 'country' => 'Russia', 'code' => 7];
extract($data);
echo $city; // 'Moscow'
echo $country; // 'Russia'
echo $code; // 7
// IMPORTANT: extract() with flags for safety
extract($data, EXTR_SKIP); // Don't overwrite existing variables
extract($data, EXTR_PREFIX_ALL, 'data'); // $data_city, $data_country
Ловушка экзамена:
extract()без флагов может перезаписать существующие переменные, что считается небезопасным. Никогда не используйтеextract()на непроверенных данных (например,extract($_GET)-- это уязвимость!). В современном PHP предпочитайте явную деструктуризацию массивов.