Каков наилучший способ проверить, существует ли URL-адрес в PHP?

Каков наилучший способ увидеть URL-адрес, и ответ не является 404?

Вы можете использовать get_headers($url)

Пример 2 из руководства:

 <?php // By default get_headers uses a GET request to fetch the headers. If you // want to send a HEAD request instead, you can do so using a stream context: stream_context_set_default( array( 'http' => array( 'method' => 'HEAD' ) ) ); print_r(get_headers('http://example.com')); // gives Array ( [0] => HTTP/1.1 200 OK [Date] => Sat, 29 May 2004 12:28:14 GMT [Server] => Apache/1.3.27 (Unix) (Red-Hat/Linux) [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT [ETag] => "3f80f-1b6-3e1cb03b" [Accept-Ranges] => bytes [Content-Length] => 438 [Connection] => close [Content-Type] => text/html ) 

Первый элемент массива будет содержать код состояния ответа HTTP. Вы должны разобрать это.

Обратите внимание, что функция get_headers в примере выдаст запрос HTTP HEAD, что означает, что он не получит тело URL-адреса. Это более эффективно, чем использование запроса GET, который также возвращает тело.

Также обратите внимание, что, установив контекст по умолчанию , любые последующие вызовы, используя контекст HTTP-потока, теперь выдадут HEAD-запросы. Поэтому не забудьте сбросить контекст по умолчанию, чтобы снова использовать GET, когда закончите.

PHP также предоставляет переменную $ http_response_header

Массив $http_response_header похож на get_headers() . При использовании HTTP-обертки $http_response_header будет заполняться заголовками HTTP-ответа. $http_response_header будет создан в локальной области.

Если вы хотите загрузить содержимое удаленного ресурса, вы не хотите выполнять два запроса (один, чтобы узнать, существует ли ресурс и один из них), но только один. В этом случае используйте file_get_contents для извлечения содержимого, а затем проверьте заголовки из этой переменной.

@Gordon – вот более полная библиотека, основанная на вашем ответе. Он включает в себя некоторую предварительную проверку правильности URL-адреса, некоторую дополнительную обработку ошибок и синтаксический анализ возвращаемых заголовков. Он также следует за любыми цепочками перенаправления для разумного количества шагов.

 class cLib { static $lasterror = 'No error set yet'; /** * @brief See with a URL is valid - ie a page can be successfully retrieved from it without error * @param string $url The URL to be checked * @param int $nredirects The number of redirects check so far * @return boolean True if OK, false if the URL cannot be fetched */ static function checkUrl($url, $nredirects = 0) { // First, see if the URL is sensible if (filter_var($url, FILTER_VALIDATE_URL) === false) { self::$lasterror = sprintf('URL "%s" did not validate', $url); return false; } // Now try to fetch it $headers = @get_headers($url); if ($headers == false) { $error = error_get_last(); self::$lasterror = sprintf('URL "%s" could not be read: %s', $url, $error['message']); return false; } $status = $headers[0]; $rbits = explode(' ', $status); if (count($rbits) < 2) { self::$lasterror = sprintf('Cannot parse status "%s" from URL "%s"', $status, $url); return false; } if (in_array($rbits[1], array(301, 302, 304, 307, 308))) { // This URL has been redirected. Follow the redirection chain foreach ($headers as $header) { if (cLib::startsWith($header, 'Location:')) { if (++$nredirects > 10) { self::$lasterror = sprintf('URL "%s" was redirected over 10 times: abandoned check', $url); return false; } return self::checkUrl(trim(substr($header, strlen('Location:'))), $nredirects); } } self::$lasterror = sprintf('URL "%s" was redirected but location could not be identified', $url); return false; } if ($rbits[1] != 200) { self::$lasterror = sprintf('URL "%s" returned status "%s"', $url, $status); return false; } return true; } } 

С извинениями перед @FranciscoLuz – если вы ожидаете ошибок на основе ввода пользователя, метод «@ и error_get_last» кажется мне совершенно разумным – я не вижу, что есть что-то более правильное в использовании set_error_handler.

Кстати, не уверен, что я должен был сделать это как отредактировать ответ @ Гордона, а не как отдельный ответ. Может ли кто-нибудь посоветовать?

 public function isLink($url) { $result = false; if (!filter_var($url, FILTER_VALIDATE_URL) === false) { $getHeaders = get_headers($url); $result = strpos($getHeaders[0], '200') !== false; } return $result; }