Как в PHP проверить, ведёт ли ссылка на реальную страницу
Проверка ссылки в PHP: основные подходы
Наиболее эффективное и гибкое решение для проверки доступности URL в PHP - использование библиотеки cURL. Она позволяет управлять таймаутами, обрабатывать редиректы, получать заголовки и тело ответа, а также работать с HTTPS и различными методами запросов.
$url = 'https://example.com';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true, // получаем только заголовки
CURLOPT_TIMEOUT => 10, // таймаут в секундах
CURLOPT_FOLLOWLOCATION => true, // следовать редиректам
CURLOPT_MAXREDIRS => 5,
CURLOPT_SSL_VERIFYPEER => true, // проверка SSL сертификата
]);
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
echo 'Ошибка cURL: ' . $error;
} elseif ($httpCode >= 200 && $httpCode < 400) {
echo 'Ссылка доступна. Код ответа: ' . $httpCode;
} else {
echo 'Ссылка недоступна. Код ответа: ' . $httpCode;
}
Php проверить ссылку (проверить ссылку в php)
Типичные проблемы и их решение:
- Ошибка SSL: если сертификат самоподписан или устарел, можно временно отключить проверку (
CURLOPT_SSL_VERIFYPEER => false), но это снижает безопасность. - Таймаут: при медленных сайтах увеличить
CURLOPT_TIMEOUTили использоватьCURLOPT_CONNECTTIMEOUTотдельно. - Редиректы: если сайт делает много перенаправлений, увеличить
CURLOPT_MAXREDIRS. - Заблокированный User-Agent: некоторые серверы требуют определённый заголовок; установить
CURLOPT_USERAGENT.
Цель использования cURL - надёжная проверка любого HTTP/HTTPS URL с полным контролем параметров запроса.
Как проверить ссылку с помощью get_headers?
Функция get_headers() возвращает массив заголовков ответа сервера. Это простой способ, не требующий дополнительных расширений.
$url = 'https://example.com';
$headers = @get_headers($url);
if ($headers && strpos($headers[0], '200') !== false) {
echo 'Ссылка работает (код 200 OK)';
} else {
echo 'Ссылка не отвечает или вернула ошибку';
}
Id ссылки php (идентификатор ссылки в php)
Проблемы:
- По умолчанию
get_headers()не следует редиректам. Чтобы получить финальный код, нужно вызвать её с флагомstream_context_set_defaultили использовать обёртку. - На многих хостингах отключена директива
allow_url_fopen, тогда функция вернётfalse. - Нет контроля таймаута - может зависнуть надолго.
Применяется для быстрой проверки, когда не требуется тонкая настройка.
Как использовать file_get_contents с контекстом для проверки?
Можно создать потоковый контекст и прочитать только первые байты, чтобы не загружать весь контент.
$url = 'https://example.com';
$opts = [
'http' => [
'method' => 'HEAD',
'timeout' => 5,
'follow_location' => 1,
'max_redirects' => 3,
],
'ssl' => [
'verify_peer' => true,
]
];
$context = stream_context_create($opts);
$result = @file_get_contents($url, false, $context);
if ($result !== false) {
echo 'Ссылка доступна';
} else {
echo 'Ошибка при открытии URL';
}
активная ссылка php (создание активной ссылки в php)
Ошибки:
allow_url_fopenдолжен быть включён.- При HEAD-запросе некоторые серверы могут отвечать некорректно, лучше использовать GET с небольшим лимитом на чтение.
Случай применения - когда cURL недоступен, но требуется минимальный контроль.
Как проверить существование домена через DNS?
Иногда достаточно убедиться, что домен разрешается в IP. Для этого используется checkdnsrr().
$domain = 'example.com';
if (checkdnsrr($domain, 'A')) {
echo 'DNS запись найдена';
} else {
echo 'Домен не существует или не имеет A-записи';
}
Php ссылки (работа с url и ссылками в php)
Нюансы:
- Функция не проверяет, работает ли веб-сервер - только DNS.
- На Windows до PHP 5.3 эта функция не поддерживалась.
Применение: предварительная фильтрация URL перед более дорогой проверкой.
Как проверить формат URL с помощью filter_var?
filter_var() с флагом FILTER_VALIDATE_URL проверяет синтаксис URL, но не его доступность.
$url = 'https://example.com';
if (filter_var($url, FILTER_VALIDATE_URL)) {
echo 'URL корректен по формату';
} else {
echo 'Некорректный URL';
}
Php адрес страницы (адрес страницы в php)
Ограничения:
- Допускает несуществующие домены (например,
https://nonexistent123456.com). - Не проверяет протокол - любая строка с
://может считаться валидной.
Используется для первичной валидации ввода пользователя.
Как выполнить проверку через сокет?
Можно открыть TCP-соединение к хосту на порт 80 или 443. Это низкоуровневый способ.
$url = 'example.com';
$host = parse_url($url, PHP_URL_HOST);
$port = 80;
$fp = @fsockopen($host, $port, $errno, $errstr, 5);
if ($fp) {
echo 'Хост доступен по порту ' . $port;
fclose($fp);
} else {
echo 'Ошибка: ' . $errstr;
}
Недостатки:
- Не проверяет HTTP-ответ, только TCP-соединение.
- Не обрабатывает HTTPS автоматически - нужен отдельный поток с SSL.
Применяется для быстрой проверки, работает ли сервер вообще.
Расширенные примеры проверки ссылок
1. cURL с детальной обработкой ошибок и редиректов
function checkUrl($url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => '/path/to/cacert.pem', // путь к корневым сертификатам
CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Bot)',
]);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['success' => false, 'error' => $error];
}
$httpCode = $info['http_code'];
$finalUrl = $info['url']; // конечный URL после редиректов
return [
'success' => $httpCode >= 200 && $httpCode < 400,
'code' => $httpCode,
'final_url' => $finalUrl,
'redirect_count' => $info['redirect_count'],
];
}
// Пример вызова
$result = checkUrl('https://example.com/redirect');
print_r($result);
Array
(
[success] => 1
[code] => 200
[final_url] => https://example.com/target
[redirect_count] => 2
)
В примере функция возвращает не только булевый результат, но и конечный URL, что полезно для анализа редиректов.
2. Проверка с помощью get_headers и обработка редиректов через контекст
$url = 'https://example.com';
$opts = [
'http' => [
'method' => 'GET',
'timeout' => 10,
'follow_location' => 1,
'max_redirects' => 3,
'ignore_errors' => true, // не генерировать предупреждения при ошибках HTTP
]
];
$context = stream_context_create($opts);
$headers = @get_headers($url, 1, $context);
if ($headers && isset($headers[0])) {
$statusLine = $headers[0];
preg_match('/\d{3}/', $statusLine, $matches);
$code = (int)$matches[0];
echo 'HTTP код: ' . $code;
if ($code >= 200 && $code < 400) {
echo ' - ссылка рабочая';
} else {
echo ' - ссылка не отвечает';
}
} else {
echo 'Не удалось получить заголовки';
}
HTTP код: 200 - ссылка рабочая
Использование ignore_errors => true позволяет избежать предупреждений о кодах 4xx/5xx.
3. Многопоточная проверка нескольких URL с помощью curl_multi
$urls = [
'https://example1.com',
'https://example2.com',
'https://example3.com',
];
$multi = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_NOBODY => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => true,
]);
curl_multi_add_handle($multi, $ch);
$handles[$i] = $ch;
}
$active = null;
do {
$status = curl_multi_exec($multi, $active);
} while ($status === CURLM_CALL_MULTI_PERFORM || $active);
foreach ($handles as $i => $ch) {
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
echo "URL $i: код $code, ошибка: $error\n";
curl_multi_remove_handle($multi, $ch);
curl_close($ch);
}
curl_multi_close($multi);
URL 0: код 200, ошибка: URL 1: код 404, ошибка: URL 2: код 0, ошибка: Connection timed out after 5000 milliseconds
Параллельная проверка ускоряет работу при большом количестве ссылок.
4. Проверка ссылки с использованием fsockopen для HTTPS
$url = 'https://example.com';
$host = parse_url($url, PHP_URL_HOST);
$port = 443;
$context = stream_context_create([
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
]
]);
$fp = @stream_socket_client(
"ssl://$host:$port",
$errno,
$errstr,
5,
STREAM_CLIENT_CONNECT,
$context
);
if ($fp) {
// отправляем простой HEAD-запрос
$request = "HEAD / HTTP/1.1\r\nHost: $host\r\nConnection: close\r\n\r\n";
fwrite($fp, $request);
$response = fread($fp, 4096);
fclose($fp);
echo 'Ответ получен: ' . substr($response, 0, 50);
} else {
echo 'Ошибка соединения: ' . $errstr;
}
Ответ получен: HTTP/1.1 200 OK Date: Mon, 12 Feb 2024 12:00:00 GMT Server: Apache
Такой метод может быть полезен, если нет cURL и allow_url_fopen отключён.
5. Валидация URL с учётом списка разрешённых доменов
$allowedHosts = ['example.com', 'sub.example.com'];
$url = 'https://example.com/page';
$parsed = parse_url($url);
if ($parsed === false || !isset($parsed['host'])) {
echo 'Некорректный URL';
} elseif (!in_array($parsed['host'], $allowedHosts)) {
echo 'Домен не разрешён';
} else {
echo 'URL прошёл проверку домена';
// далее можно проверить доступность с помощью cURL
}
URL прошёл проверку домена
Такой подход применяется, когда нужно ограничить проверку только доверенными источниками.