Типы данных в PHP: от целых чисел до объектов

Раздел: Основы PHP -> Типы данных

Типы данных и их размеры в PHP

PHP поддерживает несколько типов данных, каждый из которых занимает определённый объём памяти. Размеры зависят от архитектуры системы (32- или 64-битная) и версии интерпретатора. Ниже приведены основные типы и их приблизительные размеры:

  • int - 4 или 8 байт (целое число).
  • float - 8 байт (число с плавающей запятой).
  • string - зависит от длины (каждый символ 1 байт для ASCII, до 4 байт для UTF-8) плюс служебные данные.
  • bool - 1 байт.
  • array - зависит от количества элементов и их типов (хеш-таблица).
  • object - зависит от класса и свойств.
  • null - 0 байт (специальное значение).
  • resource - указатель на внешний ресурс (8 байт).
  • callable - как функция (занимает память как строка или массив).

Для наглядного определения типа и размера используется функция var_dump(). Пример:


$number = 42;
var_dump($number);
$pi = 3.1415;
var_dump($pi);
$text = "Hello";
var_dump($text);
$flag = true;
var_dump($flag);
  

Type php type size (типы данных и их размеры php)

Результат вывода (на 64-битной системе):

int(42)
float(3.1415)
string(5) "Hello"
bool(true)
  

Json types php (php: типы данных json)

Также можно измерить текущее потребление памяти с помощью memory_get_usage(). Однако размер переменной не равен разнице до и после присваивания из-за внутреннего менеджмента памяти.

Как узнать точный размер переменной в PHP?

Прямого способа нет, но можно оценить, используя сериализацию. Функция strlen(serialize($var)) показывает длину сериализованной строки, что косвенно указывает на размер данных.


$data = ['a' => 1, 'b' => 2];
echo strlen(serialize($data));
// Вывод: 30 (примерно)
  

Проблема: Сериализация добавляет служебные символы, поэтому результат не равен реальному размеру в памяти. Для точного анализа используйте профилировщики (Xdebug, Blackfire).

Как определить тип переменной без var_dump?

Функция gettype() возвращает название типа строкой. А функции is_int(), is_string() и другие проверяют принадлежность к конкретному типу.


$value = 3.14;
echo gettype($value);                // double
var_dump(is_float($value));          // bool(true)
var_dump(is_int($value));            // bool(false)
  

Ошибка: gettype() для чисел с плавающей запятой возвращает double (а не float), хотя в PHP это одно и то же. Не стоит путать с float в документации.

Как преобразовать один тип в другой?

Используется явное приведение типа: (int), (string), (bool) и т.д. Также функции intval(), floatval(), strval().


$number = "123";
$int = (int) $number;
echo $int;                 // 123
echo gettype($int);        // integer
  

Проблема: Приведение строки, не содержащей числа, даёт 0. Например, (int) "abc" вернёт 0. Это может привести к неожиданным ошибкам.

Как избежать ошибок из-за автоматического преобразования типов?

В PHP 7+ можно включить строгую типизацию объявлением declare(strict_types=1); в начале файла. Тогда передача аргументов неверного типа вызовет TypeError.


<?php
declare(strict_types=1);

function sum(int $a, int $b): int {
    return $a + $b;
}

echo sum(5, 10);        // 15
echo sum('5', 10);      // TypeError: Argument 1 must be int
?>
  

Ошибка: Без strict_types PHP автоматически преобразует строку '5' в число. Это может скрывать логические ошибки.

Какие типичные проблемы возникают при работе с типами данных?

  • Потеря точности float: Сравнение чисел с плавающей запятой через == может дать ложный результат из-за погрешностей. Используйте эпсилон-сравнение.
  • Переполнение int: В 32-битных системах целое число больше 2^31-1 становится float. В 64-битных - до 2^63-1.
  • Сравнение типов: Использование == вместо === приводит к неявному преобразованию (например 0 == 'abc' даёт true).
  • Ресурсы: Тип resource - это указатель, который может стать недействительным после закрытия (например, файл).

Для избегания проблем рекомендуется всегда использовать строгое сравнение === и явно указывать типы аргументов.

Расширенные примеры работы с типами данных

Измерение размера разных типов с memory_get_usage

Функция memory_get_usage() возвращает текущее выделение памяти. Измерение разницы до и после создания переменной даёт приблизительный размер, но учёт внутренних структур сложен.

Пример

$before = memory_get_usage();
$int = 1000;
$after = memory_get_usage();
echo "Разница: " . ($after - $before) . " bytes\n";

$before = memory_get_usage();
$float = 3.14159265358979;
$after = memory_get_usage();
echo "Разница для float: " . ($after - $before) . " bytes\n";

$before = memory_get_usage();
$string = "a" . str_repeat("b", 100);
$after = memory_get_usage();
echo "Разница для строки (101 сим): " . ($after - $before) . " bytes\n";

$before = memory_get_usage();
$largeArray = range(1, 1000);
$after = memory_get_usage();
echo "Разница для массива на 1000 элементов: " . ($after - $before) . " bytes\n";

Результат (пример на 64-битной системе):

Разница: 48 bytes
Разница для float: 48 bytes
Разница для строки (101 сим): 200 bytes
Разница для массива на 1000 элементов: 59176 bytes

Сравнение размера разных типов массивов

Массивы с одинаковым количеством элементов, но разными типами значений, занимают разный объём.

Пример

function arrayMemory($array) {
    $before = memory_get_usage();
    $tmp = $array; // копия?
    $after = memory_get_usage();
    return $after - $before;
}

$intArray = range(1, 100);
$floatArray = array_map(function($n) { return $n * 1.5; }, range(1, 100));
$stringArray = array_map(function($n) { return "value_$n"; }, range(1, 100));

echo "Массив int: " . arrayMemory($intArray) . " bytes\n";
echo "Массив float: " . arrayMemory($floatArray) . " bytes\n";
echo "Массив string: " . arrayMemory($stringArray) . " bytes\n";

Результат (пример):

Массив int: 7640 bytes
Массив float: 7640 bytes
Массив string: 10976 bytes

Размер объекта с разным количеством свойств

Создание объекта с одним свойством и с десятью.

Пример

class SimpleClass {
    public $prop1;
}

class TenProps {
    public $p1, $p2, $p3, $p4, $p5, $p6, $p7, $p8, $p9, $p10;
}

$obj1 = new SimpleClass();
$obj1->prop1 = 42;
$obj2 = new TenProps();
for ($i = 1; $i <= 10; $i++) {
    $obj2->{"p$i"} = $i * 10;
}

echo "Объект с 1 свойством: " . strlen(serialize($obj1)) . " (сериализация)\n";
echo "Объект с 10 свойствами: " . strlen(serialize($obj2)) . " (сериализация)\n";

Результат:

Объект с 1 свойством: 35 (сериализация)
Объект с 10 свойствами: 137 (сериализация)

Влияние ссылок на размер массива

Массив, содержащий ссылки на другие переменные, может занимать меньше памяти, так как не копирует данные.

Пример

$bigString = str_repeat('x', 100000);
$before = memory_get_usage();
$arrayWithReference = [&$bigString];
$after = memory_get_usage();
echo "Массив со ссылкой: " . ($after - $before) . " bytes\n";

$before = memory_get_usage();
$arrayWithCopy = [$bigString];
$after = memory_get_usage();
echo "Массив с копией: " . ($after - $before) . " bytes\n";

Результат:

Массив со ссылкой: 136 bytes
Массив с копией: 100280 bytes

типы данных и их размеры PHP - comments

En
Type php type size (php)