Get resource id: примеры (PHP)

Функция get_resource_id в PHP: получение идентификатора ресурса
Раздел: Работа с ресурсами
get_resource_id(resource $resource): int

Функция get_resource_id() появилась в PHP 8.0 и предназначена для получения целочисленного идентификатора переданного ресурса.

Назначение и применение

Эта функция используется в случаях, когда требуется уникальный целочисленный идентификатор для работы с внешними ресурсами, такими как открытые файлы, соединения с базами данных, сокеты или дескрипторы изображений. Она заменяет неявное приведение ресурса к типу integer, которое было возможно в более ранних версиях PHP.

Аргументы функции

Функция принимает один обязательный параметр:

  • $resource - ресурс, для которого необходимо получить идентификатор.

Функция возвращает целое число (int), являющееся внутренним идентификатором ресурса. Это значение не имеет смысла вне контекста текущего процесса PHP.

Получение идентификатора файла

Идентификатор открытого файлового дескриптора.

$file = fopen('test.txt', 'r');
$id = get_resource_id($file);
var_dump($id);
// Ресурс будет автоматически закрыт при завершении скрипта
// или можно закрыть явно: fclose($file);
int(5)
Идентификатор для сокета

Пример с сетевым подключением.

$socket = stream_socket_client('tcp://google.com:80');
if ($socket) {
    echo get_resource_id($socket);
    fclose($socket);
}
6
Проверка типа аргумента

Функция выбрасывает TypeError, если передан не ресурс.

try {
    $id = get_resource_id('not_a_resource');
} catch (TypeError $e) {
    echo $e->getMessage();
}
get_resource_id(): Argument #1 ($resource) must be of type resource, string given

В PHP есть несколько функций для работы с ресурсами, но прямая замена get_resource_id() отсутствует.

is_resource()

Проверяет, является ли переменная ресурсом. Не возвращает идентификатор.

$file = fopen('php://memory', 'r');
var_dump(is_resource($file));
bool(true)
get_resources()

Возвращает массив всех активных ресурсов в системе. Может быть отфильтрован по типу. Возвращает массив ресурсов, а не их идентификаторы.

$file = fopen('php://memory', 'w');
$allResources = get_resources();
print_r($allResources);
Array
(
    [5] => stream resource
)

Выбор функции: get_resource_id() следует использовать, когда необходим именно целочисленный идентификатор для сравнения или логирования. is_resource() применяется для проверки типа переменной. get_resources() полезна для отладки и мониторинга.

Get resource id в Python

В Python функция id() возвращает уникальный идентификатор (целое число) для любого объекта, который постоянен на протяжении его жизни. Аналог более универсальный, так как тип «ресурс» в Python отсутствует.

file_obj = open('test.txt', 'r')
print(id(file_obj))
file_obj.close()
140248640725040
JavaScript (Node.js)

В JavaScript отсутствует прямой аналог. Для файловых дескрипторов в среде Node.js используются числовые идентификаторы, возвращаемые методами вроде fs.openSync(). Они уже являются числами.

const fs = require('fs');
const fd = fs.openSync('test.txt', 'r');
console.log(fd); // Это уже число
fs.closeSync(fd);
3

Get resource id в MySQL

В MySQL нет прямой аналогии на уровне языка запросов. Идентификаторы соединений (Thread ID) можно получить через функцию CONNECTION_ID(), но это относится к сессии, а не к произвольному ресурсу.

SELECT CONNECTION_ID();
+-----------------+
| CONNECTION_ID() |
+-----------------+
|             123 |
+-----------------+

Таким образом, get_resource_id() в PHP является специализированной функцией для работы с внутренним типом «resource».

Передача нересурсного значения

Наиболее частая ошибка — попытка получить идентификатор у переменной, которая не является ресурсом. В PHP 8 это приводит к исключению TypeError.

// Ошибка: передача NULL
$id = get_resource_id(null);
TypeError: get_resource_id(): Argument #1 ($resource) must be of type resource, null given
Использование идентификатора закрытого ресурса

После закрытия ресурса (например, с помощью fclose) его идентификатор может быть переиспользован для нового ресурса. Сравнение идентификаторов, сохраненных ранее, может привести к логическим ошибкам.

$file1 = fopen('test1.txt', 'r');
$id1 = get_resource_id($file1);
fclose($file1);

$file2 = fopen('test2.txt', 'r');
$id2 = get_resource_id($file2);

// $id1 может быть равно $id2, если система переиспользовала номер.
var_dump($id1, $id2);
int(5)
int(5)
Предположение об уникальности между разными типами ресурсов

Идентификаторы уникальны в рамках одного процесса, но система нумерации может быть общей для всех типов ресурсов. Не следует полагаться на префиксы или специальные диапазоны для разных типов.

Появление в PHP 8.0

Функция get_resource_id() была добавлена в PHP 8.0. До этой версии разработчики часто использовали неявное приведение ресурса к целому числу, что было неочевидно и считалось плохой практикой.

// До PHP 8.0 (устаревший способ)
$file = fopen('test.txt', 'r');
$id = (int) $file; // или $id = $file;
echo $id;
fclose($file);

Начиная с PHP 8.0, приведение ресурса к целому числу или строке вызывает ошибку уровня E_WARNING. Поэтому get_resource_id() стала единственным корректным способом получения идентификатора.

// Начиная с PHP 8.0
$file = fopen('test.txt', 'r');
// $id = (int) $file; // Warning: Resource ID#5 used as int
$id = get_resource_id($file); // Правильный способ
Сравнение ресурсов через их идентификаторы

Идентификаторы позволяют сравнивать, ссылаются ли две переменные на один и тот же ресурс.

Пример php
$file1 = fopen('php://memory', 'w');
$file2 = $file1; // Присваивание по ссылке
$file3 = fopen('php://memory', 'w');

var_dump(
    get_resource_id($file1) === get_resource_id($file2),
    get_resource_id($file1) === get_resource_id($file3)
);
bool(true)
bool(false)
Логирование работы с ресурсами

Идентификаторы удобно использовать для отладочных сообщений или логирования.

Пример php
function openConnection($host) {
    $socket = stream_socket_client($host);
    if (!$socket) {
        throw new Exception("Connection failed");
    }
    $id = get_resource_id($socket);
    error_log("Открыто сетевое соединение [ID: $id] с $host");
    return $socket;
}
Работа с массивами ресурсов

Идентификаторы можно использовать как ключи или для поиска в массиве ресурсов.

Пример php
$connections = [];

$conn1 = fopen('php://memory', 'r');
$connections[get_resource_id($conn1)] = ['type' => 'memory', 'created' => time()];

$conn2 = fopen('php://temp', 'r');
$connections[get_resource_id($conn2)] = ['type' => 'temp', 'created' => time()];

print_r($connections);

// Быстрая проверка существования ресурса в массиве по ID
$idToFind = get_resource_id($conn1);
if (isset($connections[$idToFind])) {
    echo "Ресурс с ID $idToFind найден.\n";
}
Array
(
    [5] => Array
        (
            [type] => memory
            [created] => 1678901234
        )
    [6] => Array
        (
            [type] => temp
            [created] => 1678901234
        )
)
Ресурс с ID 5 найден.
Использование с пользовательскими ресурсами

Функция работает и с ресурсами, созданными расширениями PHP.

Пример php
// Пример с модулем curl (если установлен)
$ch = curl_init('https://example.com');
if (is_resource($ch) || $ch instanceof \CurlHandle) {
    // В PHP 8.0+ curl_init может возвращать объект CurlHandle
    // Для ресурса получим ID, для объекта — нет.
    if (is_resource($ch)) {
        echo 'ID ресурса cURL: ' . get_resource_id($ch);
    }
    curl_close($ch);
}

PHP get_resource_id function comments

En
Get resource id Returns an integer identifier for the given resource