W3docs

Функция PHP dns_get_record(): всё, что нужно знать

Функция PHP dns_get_record() позволяет получать различные типы DNS-записей для доменного имени. Узнайте, как её использовать.

Когда вашему коду нужно найти почтовый сервер для домена, проверить, что имя хоста разрешается, или прочитать SPF/TXT-записи для проверки доставляемости электронной почты, вам необходим доступ к системе доменных имён (DNS). Встроенная функция PHP dns_get_record() выполняет такой запрос на уровне протокола и возвращает записи в виде PHP array — без необходимости вызывать dig.

В этой главе рассматриваются сигнатура функции, типы записей, которые она может получать, точная структура возвращаемого array, способ чтения авторитативной и дополнительной секций DNS-ответа, а также подводные камни (в особенности разница между DNS_ANY и комбинацией конкретных констант).

Уведомление об устаревании. dns_get_record() была помечена как устаревшая в PHP 8.3 и запланирована к удалению в следующем выпуске. В новом коде предпочтительнее использовать расширение getdns, стороннюю библиотеку резолвера (например, react/dns), или более узкие вспомогательные функции checkdnsrr() и gethostbyname(), когда вам нужен лишь ответ да/нет или единственная A-запись. Концепции, описанные ниже, по-прежнему применимы к этим альтернативам.

Что делает dns_get_record()

dns_get_record() запрашивает DNS для одного доменного имени и возвращает совпадающие ресурсные записи в виде array ассоциативных array. Вы выбираете, какой тип записи получить (A, MX, TXT и т.д.). В отличие от gethostbyname(), которая разрешает имя хоста только в один IPv4-адрес, dns_get_record() открывает доступ к полной записи — TTL, приоритет, цель и специфичные для типа поля.

Синтаксис

dns_get_record(
    string $hostname,
    int $type = DNS_ANY,
    array &$authoritative_name_servers = null,
    array &$additional_records = null,
    bool $raw = false
): array|false
ПараметрОписание
$hostnameДоменное имя для поиска, например "php.net".
$typeКонстанта DNS_*, выбирающая тип записи. Необязательный; по умолчанию DNS_ANY. Можно объединять константы с помощью OR — `DNS_A
&$authoritative_name_serversЗаполняется по ссылке авторитативными записями (NS) из секции authority DNS-ответа.
&$additional_recordsЗаполняется по ссылке дополнительными (glue) записями, которые возвращает сервер.
$rawКогда true, запрашивает только точный $type и возвращает записи в сыром виде. По умолчанию false.

Функция возвращает array записей или false в случае ошибки (например, когда хост не существует или резолвер недоступен).

Базовый запрос

Каждая возвращаемая запись — это ассоциативный array. Каждая запись содержит ключи host, class, type и ttl; остальные ключи зависят от типа записи.

<?php

$records = dns_get_record("php.net", DNS_A);

print_r($records);

Типичный результат выглядит так (IP-адрес и TTL могут отличаться):

Array
(
    [0] => Array
        (
            [host] => php.net
            [class] => IN
            [ttl] => 3600
            [type] => A
            [ip] => 185.85.0.29
        )
)

Поскольку результат — это обычный array, вы итерируете его с помощью foreach и читаете поля каждой записи напрямую:

<?php

foreach (dns_get_record("php.net", DNS_A) as $record) {
    echo $record['host'] . " -> " . $record['ip'] . "\n";
}

Распространённые типы записей

Передайте одну из этих констант DNS_* в качестве аргумента $type. Специфичные для типа ключи, которые можно ожидать, перечислены рядом с каждой.

КонстантаЗаписьСпецифичные для типа ключи
DNS_AIPv4-адресip
DNS_AAAAIPv6-адресipv6
DNS_MXПочтовый обменникpri, target
DNS_NSАвторитативный сервер имёнtarget
DNS_CNAMEКаноническое имя (псевдоним)target
DNS_TXTТекстовая запись (SPF, верификация)txt, entries
DNS_SOAНачало зоны полномочийmname, rname, serial, …
DNS_ANYЛюбой тип, возвращаемый резолверомварьируется

Чтобы получить несколько типов за один раз, объедините константы с помощью побитового оператора OR (|):

<?php

// A + MX records in a single call
$records = dns_get_record("php.net", DNS_A | DNS_MX);

foreach ($records as $record) {
    echo $record['type'] . "\n";
}

Подводный камень — DNS_ANY vs комбинирование констант. DNS_ANY отправляет единственный запрос ANY, и многие резолверы и авторитативные серверы теперь отклоняют или усекают его (RFC 8482). Если вам нужны конкретные записи, объединяйте точные константы через OR (DNS_A | DNS_MX | DNS_TXT) вместо использования DNS_ANY — это надёжнее и эффективнее.

Чтение авторитативных и дополнительных записей

Третий и четвёртый параметры заполняются по ссылке. Они открывают доступ к секциям authority и additional DNS-ответа, что полезно, когда вам нужны серверы имён, ответившие на запрос, или glue A-записи для цели MX:

<?php

$authns = [];
$addtl  = [];

$records = dns_get_record("php.net", DNS_MX, $authns, $addtl);

echo "MX records: "         . count($records) . "\n";
echo "Authoritative NS: "   . count($authns)  . "\n";
echo "Additional records: " . count($addtl)   . "\n";

Обработка ошибок

dns_get_record() возвращает false, когда запрос завершается неудачей. Всегда проверяйте это перед итерацией, иначе foreach над false вызовет предупреждение:

<?php

$records = dns_get_record("definitely-not-a-real-domain.invalid", DNS_A);

if ($records === false || $records === []) {
    echo "No records found.\n";
} else {
    print_r($records);
}

Для простой проверки «существует ли эта запись?» функция checkdnsrr() легковеснее, поскольку возвращает boolean вместо построения полного array записей.

Практический пример: проверка MX домена электронной почты

Распространённый реальный случай использования — подтверждение того, что адрес электронной почты принадлежит домену, который действительно может принимать почту, — удобно делать после того, как filter_var() проверил формат адреса:

<?php

function domainCanReceiveMail(string $email): bool
{
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }

    $domain = substr(strrchr($email, "@"), 1);
    $mx = dns_get_record($domain, DNS_MX);

    return is_array($mx) && count($mx) > 0;
}

var_dump(domainCanReceiveMail("[email protected]")); // bool(true)

Проверка формата и существования MX необходима, но недостаточна — они не доказывают, что конкретный почтовый ящик существует. Это дешёвый первичный фильтр, который отсеивает опечатки и одноразовые домены до попытки отправки.

Заключение

dns_get_record() предоставляет PHP прямой структурированный доступ к DNS-данным: выберите тип записи с помощью константы DNS_*, итерируйте возвращаемый array и читайте специфичные для типа поля. Предпочитайте объединение точных констант через OR вместо DNS_ANY, всегда защищайтесь от возврата false и обращайтесь к checkdnsrr() или gethostbyname(), когда вам нужен более узкий ответ. Поскольку функция находится на пути к удалению из PHP, изолируйте DNS-запросы за небольшим вспомогательным методом, чтобы позднее можно было перейти на расширение getdns или библиотеку резолвера без изменения остального кода.

Практика

Практика
Какова цель функции dns_get_record() в PHP?
Какова цель функции dns_get_record() в PHP?
Was this page helpful?