Перейти к содержимому

4. Типы данных

PHP — динамически типизированный язык, что означает, что тип переменной определяется автоматически в зависимости от присвоенного значения. Однако понимание типов данных критически важно для написания корректного и безопасного кода.

  • Скалярные типы (string, integer, float, boolean)
  • Составные типы (array, object)
  • Специальные типы (resource, NULL)
  • Проверка и преобразование типов
  • Строгая типизация (PHP 7+)
  • Type hinting и return types

Скалярные типы хранят одно значение.

Строка — последовательность символов.

<?php
// Двойные кавычки (обрабатываются переменные и escape-последовательности)
$greeting = "Привет, мир!";
$name = "Алексей";
$message = "Привет, $name!"; // Интерполяция
// Одинарные кавычки (литеральная строка)
$text = 'Это просто текст';
$literal = 'Переменная $name не обработается';
// Heredoc (для многострочных строк с интерполяцией)
$html = <<<HTML
<div class="user">
<h2>$name</h2>
<p>Добро пожаловать!</p>
</div>
HTML;
// Nowdoc (без интерполяции, как одинарные кавычки)
$config = <<<'CONFIG'
server=localhost
port=3306
user=$dbUser
CONFIG;
echo $message;
?>
```text
#### Escape-последовательности
```php
<?php
// Работают только в двойных кавычках
$text = "Строка1\nСтрока2"; // \n - новая строка
$tab = "Колонка1\tКолонка2"; // \t - табуляция
$quote = "Он сказал: \"Привет!\""; // \" - экранирование кавычек
$backslash = "Путь: C:\\xampp\\htdocs"; // \\ - обратный слеш
echo nl2br($text); // Конвертирует \n в <br>
?>
```text
#### Полезные функции для строк
```php
<?php
$str = " Hello, World! ";
// Длина строки
echo strlen($str); // 17
// Убрать пробелы
echo trim($str); // "Hello, World!"
// Верхний/нижний регистр
echo strtoupper($str); // " HELLO, WORLD! "
echo strtolower($str); // " hello, world! "
// Замена
echo str_replace("World", "PHP", $str); // " Hello, PHP! "
// Поиск подстроки
if (strpos($str, "Hello") !== false) {
echo "Найдено!";
}
// Разбить строку на массив
$parts = explode(", ", "apple, banana, orange");
print_r($parts); // ["apple", "banana", "orange"]
// Объединить массив в строку
$fruits = ["apple", "banana", "orange"];
echo implode(", ", $fruits); // "apple, banana, orange"
?>
```text
### Integer (целое число)
Целые числа без дробной части.
```php
<?php
$decimal = 42; // Десятичное
$negative = -15; // Отрицательное
$octal = 0755; // Восьмеричное (начинается с 0)
$hex = 0xFF; // Шестнадцатеричное (начинается с 0x)
$binary = 0b1010; // Двоичное (начинается с 0b)
// PHP_INT_MAX - максимальное значение
echo PHP_INT_MAX; // 9223372036854775807 (64-bit)
// Проверка типа
var_dump(is_int($decimal)); // bool(true)
var_dump(is_int(42.5)); // bool(false)
?>
```text
#### Операции с целыми числами
```php
<?php
$a = 10;
$b = 3;
echo $a + $b; // 13 (сложение)
echo $a - $b; // 7 (вычитание)
echo $a * $b; // 30 (умножение)
echo $a / $b; // 3.333... (деление)
echo $a % $b; // 1 (остаток от деления)
echo $a ** $b; // 1000 (возведение в степень, PHP 5.6+)
// Целочисленное деление
echo intdiv($a, $b); // 3 (PHP 7+)
?>
```text
### Float (число с плавающей точкой)
Числа с дробной частью (также называются double).
```php
<?php
$price = 99.99;
$pi = 3.14159;
$scientific = 1.5e3; // 1500 (научная нотация)
$negative = -0.001;
// Проверка типа
var_dump(is_float($price)); // bool(true)
// Форматирование
echo number_format($price, 2); // "99.99"
echo number_format(1234567.89, 2, ',', ' '); // "1 234 567,89"
// Округление
echo round(3.4); // 3
echo round(3.5); // 4
echo ceil(3.1); // 4 (округление вверх)
echo floor(3.9); // 3 (округление вниз)
?>
```text
#### Осторожно с float!
```php
<?php
// ⚠️ Проблема точности с плавающей точкой
$a = 0.1;
$b = 0.2;
$sum = $a + $b;
var_dump($sum); // float(0.30000000000000004)
// ❌ Неправильно: сравнение float напрямую
if ($sum == 0.3) {
echo "Равно"; // Может не сработать!
}
// ✅ Правильно: сравнение с точностью
$epsilon = 0.00001;
if (abs($sum - 0.3) < $epsilon) {
echo "Равно"; // Работает
}
// ✅ Для денег используйте integer (копейки)
$price_cents = 9999; // 99.99 руб
$display_price = $price_cents / 100;
?>
```text
### Boolean (булев тип)
Логические значения: `true` или `false`.
```php
<?php
$is_active = true;
$is_deleted = false;
// Проверка
var_dump(is_bool($is_active)); // bool(true)
// Преобразование в boolean
var_dump((bool)""); // bool(false) - пустая строка
var_dump((bool)"0"); // bool(false) - строка "0"
var_dump((bool)"false"); // bool(true) - непустая строка!
var_dump((bool)0); // bool(false) - ноль
var_dump((bool)1); // bool(true)
var_dump((bool)-1); // bool(true) - любое не-ноль
var_dump((bool)[]); // bool(false) - пустой массив
var_dump((bool)[1]); // bool(true)
var_dump((bool)null); // bool(false)
?>
```text
#### Falsy values (ложные значения)
Следующие значения считаются `false`:
```php
<?php
// Все эти значения == false
$falsy_values = [
false,
0,
0.0,
"0",
"",
null,
[] // пустой массив
];
foreach ($falsy_values as $val) {
if (!$val) {
echo "Это falsy значение\n";
}
}
?>
```text
## Составные типы
### Array (массив)
Массивы хранят множество значений.
```php
<?php
// Индексированный массив (numeric array)
$fruits = ["apple", "banana", "orange"];
$fruits = array("apple", "banana", "orange"); // Старый синтаксис
echo $fruits[0]; // "apple"
echo $fruits[1]; // "banana"
// Ассоциативный массив (associative array)
$user = [
"name" => "Иван",
"email" => "[email protected]",
"age" => 25
];
echo $user["name"]; // "Иван"
echo $user["email"]; // "[email protected]"
// Многомерный массив
$users = [
[
"name" => "Иван",
"age" => 25
],
[
"name" => "Мария",
"age" => 30
]
];
echo $users[0]["name"]; // "Иван"
echo $users[1]["age"]; // 30
?>
```text
#### Операции с массивами
```php
<?php
$arr = ["a", "b", "c"];
// Добавление элементов
$arr[] = "d"; // В конец
array_push($arr, "e", "f"); // В конец (несколько)
array_unshift($arr, "z"); // В начало
// Удаление элементов
array_pop($arr); // Удалить последний
array_shift($arr); // Удалить первый
unset($arr[2]); // Удалить по индексу
// Подсчет элементов
echo count($arr);
// Проверка существования
if (in_array("b", $arr)) {
echo "Найдено!";
}
if (isset($arr[5])) {
echo "Индекс 5 существует";
}
// Слияние массивов
$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$merged = array_merge($arr1, $arr2); // [1, 2, 3, 4, 5, 6]
?>
```text
Подробнее о массивах мы поговорим в отдельном уроке.
### Object (объект)
Объекты — экземпляры классов.
```php
<?php
class User {
public $name;
public $email;
public function __construct($name, $email) {
$this->name = $name;
$this->email = $email;
}
public function greet() {
return "Привет, меня зовут " . $this->name;
}
}
// Создание объекта
$user = new User("Алексей", "[email protected]");
echo $user->name; // "Алексей"
echo $user->greet(); // "Привет, меня зовут Алексей"
// Проверка типа
var_dump(is_object($user)); // bool(true)
?>
```text
Объекты и ООП мы подробно разберем в разделе про классы.
## Специальные типы
### NULL
NULL представляет отсутствие значения.
```php
<?php
$var = null;
// Переменная становится NULL в трех случаях:
// 1. Явное присваивание
$a = null;
// 2. Переменная объявлена, но не инициализирована
// $b; // null (но вызовет Notice)
// 3. Переменная удалена
$c = 123;
unset($c); // Теперь $c = null
// Проверка на NULL
var_dump(is_null($var)); // bool(true)
var_dump($var === null); // bool(true)
var_dump(isset($var)); // bool(false)
// Оператор объединения с null (PHP 7+)
$username = $_GET['user'] ?? 'Гость';
// Если $_GET['user'] не существует или null, вернет 'Гость'
?>
```text
### Resource (ресурс)
Ресурс — специальная переменная, ссылающаяся на внешний ресурс (файл, БД, изображение).
```php
<?php
// Открытие файла
$file = fopen("data.txt", "r");
var_dump(is_resource($file)); // bool(true)
fclose($file);
// Подключение к БД
$connection = mysqli_connect("localhost", "user", "password", "database");
var_dump(is_resource($connection)); // bool(true)
mysqli_close($connection);
// Работа с изображениями (GD)
$image = imagecreate(200, 100);
var_dump(is_resource($image)); // bool(true)
imagedestroy($image);
?>
```text
## Проверка типов
PHP предоставляет функции для проверки типов:
```php
<?php
$var = "Hello";
// Проверка конкретного типа
is_string($var); // true
is_int($var); // false
is_float($var); // false
is_bool($var); // false
is_array($var); // false
is_object($var); // false
is_null($var); // false
is_resource($var); // false
// Универсальная проверка типа
echo gettype($var); // "string"
// Проверка на скалярный тип
is_scalar($var); // true (string, int, float, bool)
// Проверка на числовой тип
is_numeric("123"); // true
is_numeric("12.5"); // true
is_numeric("abc"); // false
?>
```text
### Функция var_dump() для отладки
```php
<?php
$data = [
"name" => "Иван",
"age" => 25,
"active" => true,
"balance" => 99.99,
"address" => null
];
var_dump($data);
// array(5) {
// ["name"]=>
// string(8) "Иван"
// ["age"]=>
// int(25)
// ["active"]=>
// bool(true)
// ["balance"]=>
// float(99.99)
// ["address"]=>
// NULL
// }
?>
```text
## Преобразование типов
### Автоматическое преобразование (type juggling)
PHP автоматически преобразует типы:
```php
<?php
// Строка + число
$result = "5" + 10;
var_dump($result); // int(15)
// Строка * число
$result = "3" * "4";
var_dump($result); // int(12)
// Конкатенация преобразует в строку
$result = 10 . 20;
var_dump($result); // string(4) "1020"
// Логические операции
$result = "5" > 3;
var_dump($result); // bool(true)
// ⚠️ Осторожно с нечисловыми строками
$result = "hello" + 5;
var_dump($result); // int(5) - "hello" стало 0!
?>
```text
### Явное преобразование (type casting)
```php
<?php
$value = "123.45";
// Приведение типов
$int = (int)$value; // 123
$float = (float)$value; // 123.45
$string = (string)$value; // "123.45"
$bool = (bool)$value; // true
// Альтернативные функции
$int = intval($value); // 123
$float = floatval($value); // 123.45
$string = strval($value); // "123.45"
var_dump($int, $float, $string, $bool);
?>
```text
### Преобразование в массив и объект
```php
<?php
// В массив
$string = "hello";
$array = (array)$string;
var_dump($array); // array(1) { [0]=> string(5) "hello" }
// Объект в массив
$obj = (object)["name" => "Иван", "age" => 25];
$array = (array)$obj;
var_dump($array);
// Массив в объект
$array = ["name" => "Мария", "email" => "[email protected]"];
$obj = (object)$array;
echo $obj->name; // "Мария"
?>
```text
## Строгая типизация (PHP 7+)
С PHP 7 можно включить строгую типизацию.
### Без строгой типизации (по умолчанию)
```php
<?php
function add(int $a, int $b) {
return $a + $b;
}
// PHP автоматически преобразует строки в int
echo add("5", "10"); // 15 (работает)
echo add("5.7", 3); // 8 (преобразует 5.7 в 5)
?>
```text
### Со строгой типизацией
```php
<?php
declare(strict_types=1); // Включаем строгую типизацию
function add(int $a, int $b): int {
return $a + $b;
}
echo add(5, 10); // 15 (работает)
echo add("5", "10"); // TypeError: Argument must be of type int, string given
?>
```text
### Type hints и return types
```php
<?php
declare(strict_types=1);
// Type hints для параметров и return type
function getUserName(int $user_id): string {
// Всегда должен вернуть string
return "User_" . $user_id;
}
// Nullable types (PHP 7.1+)
function findUser(?int $id): ?string {
// Может принять int или null
// Может вернуть string или null
if ($id === null) {
return null;
}
return "User_" . $id;
}
// Union types (PHP 8.0+)
function process(int|float $number): int|float {
// Принимает int ИЛИ float
// Возвращает int ИЛИ float
return $number * 2;
}
// Mixed type (любой тип, PHP 8.0+)
function handleData(mixed $data): mixed {
return $data;
}
echo getUserName(42); // "User_42"
echo findUser(null); // null
echo process(5); // 10
echo process(3.5); // 7.0
?>
```text
## WordPress контекст
В WordPress важно правильно работать с типами данных для безопасности.
### Sanitization (очистка) данных
```php
<?php
// Получаем данные из формы
$post_title = $_POST['title']; // ❌ ОПАСНО
// ✅ Правильно: очистка и валидация
$post_title = sanitize_text_field($_POST['title']);
$post_content = wp_kses_post($_POST['content']);
$user_id = absint($_POST['user_id']); // Приведение к положительному int
$email = sanitize_email($_POST['email']);
$url = esc_url($_POST['website']);
// Создание поста
wp_insert_post([
'post_title' => $post_title,
'post_content' => $post_content,
'post_author' => $user_id,
'post_status' => 'publish'
]);
?>
```text
### Escape вывод
```php
<?php
// Получаем данные
$user_input = get_post_meta(get_the_ID(), 'custom_field', true);
// ❌ ОПАСНО: XSS атака
echo $user_input;
// ✅ Правильно: экранирование
echo esc_html($user_input); // Обычный текст
echo esc_attr($user_input); // Атрибуты HTML
echo esc_url($user_input); // URL
echo esc_js($user_input); // JavaScript
echo wp_kses_post($user_input); // HTML с разрешенными тегами
?>
```text
### Type hinting в WordPress
```php
<?php
/**
* Получить посты определенного типа
*
* @param string $post_type Тип поста
* @param int $number Количество постов
* @return array Массив постов
*/
function get_custom_posts(string $post_type, int $number = 10): array {
$args = [
'post_type' => $post_type,
'posts_per_page' => $number,
'post_status' => 'publish'
];
$query = new WP_Query($args);
return $query->posts;
}
// Использование
$posts = get_custom_posts('post', 5);
?>
```text
## Практика
### Задание 1: Определение типов
Создайте переменные разных типов и выведите их тип с помощью `gettype()` и `var_dump()`.
```php
<?php
$string = "Hello";
$integer = 42;
$float = 3.14;
$boolean = true;
$array = [1, 2, 3];
$null = null;
echo gettype($string) . "<br>";
echo gettype($integer) . "<br>";
// ... и так далее
var_dump($string);
var_dump($integer);
// ... и так далее
?>
```text
### Задание 2: Преобразование типов
Создайте строку `"123.45"` и преобразуйте её во все возможные типы, выведите результаты.
### Задание 3: Калькулятор с типами
Создайте функцию калькулятора с type hints:
```php
<?php
declare(strict_types=1);
function calculate(float $a, float $b, string $operation): float {
switch ($operation) {
case '+':
return $a + $b;
case '-':
return $a - $b;
case '*':
return $a * $b;
case '/':
return $b != 0 ? $a / $b : 0;
default:
return 0;
}
}
echo calculate(10, 5, '+'); // 15
echo calculate(10, 5, '*'); // 50
?>
```text
### Задание 4: Проверка типов
Создайте функцию, которая принимает переменную и выводит её тип и значение.
### Задание 5: Работа с null
Используйте оператор `??` для работы с потенциально отсутствующими значениями.
```php
<?php
$username = $_GET['user'] ?? 'Гость';
$page = $_GET['page'] ?? 1;
$items_per_page = $_GET['limit'] ?? 10;
echo "Пользователь: $username<br>";
echo "Страница: $page<br>";
echo "На странице: $items_per_page<br>";
?>
```text
## Онлайн-редакторы
Протестируйте примеры:
- **PHPSandbox**: https://phpsandbox.io/
- **3v4l**: https://3v4l.org/ (проверьте поведение на разных версиях PHP!)
## Итоги
В этом уроке вы изучили:
✅ **Скалярные типы** — string, integer, float, boolean
✅ **Составные типы** — array, object
✅ **Специальные типы** — NULL, resource
✅ **Проверку типов** — is_*, gettype(), var_dump()
✅ **Преобразование типов** — автоматическое и явное
✅ **Строгую типизацию** — declare(strict_types=1)
✅ **Type hints и return types** — современный PHP
### Следующий шаг
Теперь изучим операторы для работы с этими типами: [Операторы](/php/operators/)
### Ключевые моменты
1. **PHP динамически типизирован** — тип определяется автоматически
2. **Строгая типизация рекомендуется** — меньше ошибок
3. **Осторожно с float** — проблемы с точностью
4. **NULL !== 0 !== ""** — разные falsy значения
5. **В WordPress всегда очищайте данные** — безопасность превыше всего
**Совет:** Используйте `var_dump()` для отладки — это ваш лучший инструмент понимания типов!
---
**Готовы двигаться дальше?** Переходите к следующему уроку: [Операторы](/php/operators/)