Como posso lidar com o aviso da função file_get_contents () no PHP?


312

Eu escrevi um código PHP como este

$site="http://www.google.com";
$content = file_get_content($site);
echo $content;

Mas quando removo "http: //" $site, recebo o seguinte aviso:

Aviso: file_get_contents (www.google.com) [function.file-get-contents]: falha ao abrir o fluxo:

Eu tentei trye catchmas não funcionou.


2
Também uma abordagem interessante: stackoverflow.com/questions/6718598/...
Hugo Stieglitz


Use try-catch com set_error_handler-function como dito aqui stackoverflow.com/a/3406181/1046909
MingalevME

2
Se você remover http: // do URL, estará procurando um arquivo "www.google.com" no disco local.
Rauli Rajande

Como isso pode receber tanta atenção e votos positivos? Por que você removeu as informações do protocolo. Mesmo em 2008, você tinha FTP e HTTPS.
Daniel W.

Respostas:


507

Etapa 1: verifique o código de retorno: if($content === FALSE) { // handle error here... }

Etapa 2: suprima o aviso colocando um operador de controle de erro (ou seja @) na frente da chamada para file_get_contents () : $content = @file_get_contents($site);


86
Lembre-se de usar uma comparação estrita: if ($ content === FALSE). Se o arquivo contiver "0", ele disparará um falso negativo.
Aram Kocharyan

7
Olá, isso não funcionou para mim, adicionar @ ainda faz com que E_WARNING seja capturado por algum manipulador de erro global (não meu), e meu script morre antes que eu tenha a chance de lidar com o valor de retorno. Alguma ideia? TNX.
Sagi Mann

1
Efeito colateral detectado: se o arquivo não existir, o script será interrompido na linha @file_get_contents.
Dax

Isso não funciona para mim, mesmo que esteja prestes a ser a solução certa. Tenho um aviso de tempo limite sem dados recebidos, mas $ content === FALSE não é "acionado" ($ site sendo chamado de um servidor localhost, observe que tenho dados rapidamente se colar o URL em um navegador).
Oliver

4
Embora a resposta seja muito antiga, ainda sugiro adicionar uma observação à sua resposta de que o uso @pode afetar negativamente o desempenho. Veja esta resposta em uma postagem relacionada que explica bastante bem.
Fr0zenFyr

148

Você também pode definir seu manipulador de erros como uma função anônima que chama uma exceção e usar uma tentativa / captura nessa exceção.

set_error_handler(
    function ($severity, $message, $file, $line) {
        throw new ErrorException($message, $severity, $severity, $file, $line);
    }
);

try {
    file_get_contents('www.google.com');
}
catch (Exception $e) {
    echo $e->getMessage();
}

restore_error_handler();

Parece um monte de código para capturar um pequeno erro, mas se você estiver usando exceções em todo o aplicativo, será necessário fazer isso apenas uma vez, na parte superior (em um arquivo de configuração incluído, por exemplo), e será converta todos os seus erros em exceções por toda parte.


É uma das maiores melhorias em PHP que eu já vi até agora. Obrigado enobrev
Tomasz Smykowski

@enobrev, Por que você coloca o mesmo valor para o número e a gravidade do erro?
Pacerier 16/07/2013

Nenhuma razão específica além de um meio de oferecer algo útil em $ exception-> getCode (), pois set_error_handler não oferece uma variável de número de erro (infelizmente).
enobrev 16/07/2013

1
@enobrev Não se esqueça de restaurar o manipulador de erros dentro da função anônima antes de lançar a exceção. A exceção pode ser manipulada e, nesse caso, o manipulador ainda está definido para lançar essa exceção específica, que pode ser inesperada e introduzir um comportamento estranho e difícil de depurar quando houver outro erro no tratamento de exceções.
Josef Sábl 23/10

1
Eu recomendaria para incluir restore_error_handler call () no bloco finally
peschanko

67

Minha maneira favorita de fazer isso é bastante simples:

if (!$data = file_get_contents("http://www.google.com")) {
      $error = error_get_last();
      echo "HTTP request failed. Error was: " . $error['message'];
} else {
      echo "Everything went better than expected";
}

Descobri isso depois de experimentar o try/catchcódigo do @enobrev acima, mas isso permite um código menos demorado (e IMO, mais legível). Simplesmente usamos error_get_lastpara obter o texto do último erro e file_get_contentsretornamos falso em caso de falha, portanto, um simples "se" pode capturar isso.


2
Essa é a melhor e mais fácil solução para esse problema! Talvez faça @file_get_contentspara suprimir o relatório de erros para o navegador.
EDP

1
Admito que, dentre todas as respostas, essa é a única sensata - se a aumentarmos @file_get_contentspara suprimir o aviso e testar o valor do resultado === FALSE.
Kostix

11
Isso acionará erros para solicitações bem-sucedidas que não retornam um corpo ou retornam um que é avaliado como falso. Deveria serif (false !== ($data = file_get_contents ()))
GordonM:

A documentação não deixar claro, mas usando @ pode causar error_get_lastpara retornar nada na minha experiência
Glenn Schmidt

33

Você pode adicionar um @: $content = @file_get_contents($site);

Isso suprimirá qualquer aviso - use com moderação! . Consulte Operadores de controle de erros

Editar: quando você remove o 'http: //', não está mais procurando uma página da web, mas um arquivo no seu disco chamado "www.google ....."


Essa é a única coisa que realmente funciona - não pude suprimir a mensagem "falha ao abrir o fluxo" de qualquer outra maneira.
Olaf

21

Uma alternativa é suprimir o erro e também lançar uma exceção que você poderá capturar mais tarde. Isso é especialmente útil se houver várias chamadas para file_get_contents () no seu código, pois você não precisa suprimir e manipular todas elas manualmente. Em vez disso, várias chamadas podem ser feitas para essa função em um único bloco try / catch.

// Returns the contents of a file
function file_contents($path) {
    $str = @file_get_contents($path);
    if ($str === FALSE) {
        throw new Exception("Cannot access '$path' to read contents.");
    } else {
        return $str;
    }
}

// Example
try {
    file_contents("a");
    file_contents("b");
    file_contents("c");
} catch (Exception $e) {
    // Deal with it.
    echo "Error: " , $e->getMessage();
}

15

Aqui está como eu fiz isso ... Não há necessidade de bloco try-catch ... A melhor solução é sempre a mais simples ... Aproveite!

$content = @file_get_contents("http://www.google.com");
if (strpos($http_response_header[0], "200")) { 
   echo "SUCCESS";
} else { 
   echo "FAILED";
} 

4
-1: isso funciona se você receber um erro 404 ou algo assim, mas não se você não conseguir se conectar ao servidor (por exemplo, nome de domínio errado). Eu acho que $http_response_headernão é atualizado nesse caso, uma vez que nenhuma resposta HTTP é recebida.
Nathan Reed

1
Como o @NathanReed disse, você deve verificar se o conteúdo $ não é falso (com ===), pois é isso que retorna se a solicitação não conseguir se conectar.
Seb

15
function custom_file_get_contents($url) {
    return file_get_contents(
        $url,
        false,
        stream_context_create(
            array(
                'http' => array(
                    'ignore_errors' => true
                )
            )
        )
    );
}

$content=FALSE;

if($content=custom_file_get_contents($url)) {
    //play with the result
} else {
    //handle the error
}

Isso não funciona. Se $url404 não for encontrado, o aviso ainda aparecerá.
Raptor

Raptor certo, eu melhorei a resposta com stream_context_create (); Nada melhor ... "@" não recomendado
RafaSashi 16/05

1
ignore_errorsinstrui apenas o contexto HTTP a não interpretar os códigos de status de resposta HTTP > = 400 como erros. Embora marginalmente relacionado, isso não responde à questão do tratamento de erros do PHP.
sol

Obrigado pela ignore_errorsopção! Era disso que eu precisava!
Modder

6

Aqui está como eu lido com isso:

$this->response_body = @file_get_contents($this->url, false, $context);
if ($this->response_body === false) {
    $error = error_get_last();
    $error = explode(': ', $error['message']);
    $error = trim($error[2]) . PHP_EOL;
    fprintf(STDERR, 'Error: '. $error);
    die();
}

4

A melhor coisa seria definir seus próprios manipuladores de erro e exceção, o que fará algo útil como registrá-lo em um arquivo ou enviar um e-mail para críticos. http://www.php.net/set_error_handler


1

Você poderia usar este script

$url = @file_get_contents("http://www.itreb.info");
if ($url) {
    // if url is true execute this 
    echo $url;
} else {
    // if not exceute this 
    echo "connection error";
}

Isso exige uma comparação estrita: if ($url === true)...porque se você receber uma resposta 0ou vazio, isso gera um erro de conexão.
Daniel W.

1

Desde o PHP 4 use error_reporting () :

$site="http://www.google.com";
$old_error_reporting = error_reporting(E_ALL ^ E_WARNING);
$content = file_get_content($site);
error_reporting($old_error_reporting);
if ($content === FALSE) {
    echo "Error getting '$site'";
} else {
    echo $content;
}

1

A maneira mais simples de fazer isso é preceder um @ antes de file_get_contents, i. e .:

$content = @file_get_contents($site); 

1

algo assim:

public function get($curl,$options){
    $context = stream_context_create($options);
    $file = @file_get_contents($curl, false, $context);
    $str1=$str2=$status=null;
    sscanf($http_response_header[0] ,'%s %d %s', $str1,$status, $str2);
    if($status==200)
        return $file        
    else 
        throw new \Exception($http_response_header[0]);
}

1
if (!file_get_contents($data)) {
  exit('<h1>ERROR MESSAGE</h1>');
} else {
      return file_get_contents($data);
}

-2

Você deve usar a função file_exists () antes para usar file_get_contents (). Dessa forma, você evitará o aviso php.

$file = "path/to/file";

if(file_exists($file)){
  $content = file_get_contents($file);
}

Este seria apenas o trabalho, se você chamar um arquivo local e você tem as permissões adequadas para verificar o arquivo local, se ela existe
rubo77

-3

Alterar o arquivo php.ini

allow_url_fopen = On

allow_url_include = On

Não faça isso. Especialmente não permita que URL inclua. Não acredite em mim. Ele foi desativado por padrão por um ótimo motivo # c99.
Daniel W.

-3

Isso tentará obter os dados; se não funcionar, detectará o erro e permitirá que você faça o que for necessário dentro do problema.

try {
    $content = file_get_contents($site);
} catch(\Exception $e) {
    return 'The file was not found';
}

-3
try {
   $site="http://www.google.com";
   $content = file_get_content($site);
   echo $content;
} catch (ErrorException $e) {
    // fix the url

}

set_error_handler(function ($errorNumber, $errorText, $errorFile,$errorLine ) 
{
    throw new ErrorException($errorText, 0, $errorNumber, $errorFile, $errorLine);
});

file_get_content nem sempre lançar uma exceção
Marlar

Deseja editar sua resposta e nos informar que em que horários o file_get_content gera exceções?
precisa

1
Embora esse código possa responder à pergunta, fornecer um contexto adicional sobre por que e / ou como esse código responde à pergunta melhora seu valor a longo prazo.
Jay Blanchard

-3

Você também deve definir o

allow_url_use = On 

em sua php.iniparar de receber avisos.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.