Làm cách nào tôi có thể xử lý cảnh báo của hàm file_get_contents () trong PHP?


312

Tôi đã viết một mã PHP như thế này

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

Nhưng khi tôi xóa "http: //" khỏi $sitetôi sẽ nhận được cảnh báo sau:

Cảnh báo: file_get_contents (www.google.com) [function.file-get-nội dung]: không thể mở luồng:

Tôi đã thử trycatchnó không hoạt động.


2
Cũng là một cách tiếp cận thú vị: stackoverflow.com/questions/6718598/ Kẻ
Hugo Stieglitz


Sử dụng tính năng bắt thử với set_error_handler-function như đã nói ở đây stackoverflow.com/a/3406181/1046909
MingalevME

2
Nếu bạn xóa http: // khỏi url, thì bạn đang tìm tệp "www.google.com" trên đĩa cục bộ của mình.
Rauli Rajande

Làm thế nào điều này có thể nhận được rất nhiều sự chú ý và upvotes. Tại sao bạn sẽ loại bỏ thông tin giao thức. Ngay cả trong năm 2008, bạn đã có FTP và HTTPS.
Daniel W.

Câu trả lời:


507

Bước 1: kiểm tra mã trả lại: if($content === FALSE) { // handle error here... }

Bước 2: chặn cảnh báo bằng cách đặt toán tử kiểm soát lỗi (tức là @) trước lệnh gọi đến file_get_contents () : $content = @file_get_contents($site);


86
Hãy nhớ sử dụng so sánh nghiêm ngặt: if ($ content === FALSE). Nếu tệp chứa "0", thì nó sẽ kích hoạt âm tính giả.
Aram Kocharyan

7
Xin chào, điều này không hiệu quả với tôi, thêm @ vẫn khiến E_WARNING bị bắt bởi một trình xử lý lỗi toàn cầu (không phải của tôi) và tập lệnh của tôi chết trước khi tôi có cơ hội xử lý giá trị trả về. Có ý kiến ​​gì không? tnx.
Sagi Mann

1
Đã phát hiện thấy hiệu ứng phụ: nếu tệp không tồn tại, tập lệnh dừng ở dòng @file_get_contents.
Dax

Điều này không hiệu quả với tôi, ngay cả khi đây là giải pháp phù hợp. Tôi có một cảnh báo hết thời gian không nhận được dữ liệu, nhưng $ content === FALSE không được "kích hoạt" ($ site được gọi từ máy chủ localhost, lưu ý rằng tôi có dữ liệu nhanh chóng nếu tôi tự dán url vào trình duyệt).
Oliver

4
Mặc dù câu trả lời đã rất cũ, tôi vẫn đề nghị thêm một ghi chú vào câu trả lời của bạn rằng việc sử dụng @có thể ảnh hưởng tiêu cực đến hiệu suất. Xem câu trả lời này trên một bài liên quan giải thích khá tốt.
Fr0zenFyr

148

Bạn cũng có thể đặt trình xử lý lỗi của mình thành một hàm ẩn danh gọi Ngoại lệ và sử dụng thử / bắt ngoại lệ đó.

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();

Có vẻ như có rất nhiều mã để bắt một lỗi nhỏ, nhưng nếu bạn đang sử dụng ngoại lệ trong ứng dụng của mình, bạn chỉ cần thực hiện việc này một lần, ở trên cùng (ví dụ: trong tệp cấu hình được bao gồm), và nó sẽ chuyển đổi tất cả các lỗi của bạn thành Ngoại lệ trong suốt.


Đó là một trong những cải tiến PHP lớn nhất tôi từng thấy cho đến nay. Cảm ơn bạn
enobrev

@enobrev, Tại sao bạn đặt cùng một giá trị cho cả số lỗi và mức độ nghiêm trọng?
Pacerier

Không có lý do cụ thể nào ngoài phương tiện cung cấp thứ gì đó hữu ích trong $ ngoại lệ-> getCode (), vì set_error_handler không cung cấp biến số lỗi (không may).
enobrev

1
@enobrev Đừng quên khôi phục trình xử lý lỗi bên trong hàm ẩn danh trước khi ném ngoại lệ. Ngoại lệ có thể được xử lý và trong trường hợp đó, trình xử lý vẫn được thiết lập để ném ngoại lệ đặc biệt này có thể đến bất ngờ và đưa ra hành vi kỳ lạ, khó gỡ lỗi, khi có lỗi khác trong xử lý ngoại lệ.
Josef Sábl

1
Tôi khuyên bạn nên bao gồm lệnh gọi restore_error_handler () trong khối cuối cùng
peschanko

67

Cách yêu thích của tôi để làm điều này khá đơn giản:

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";
}

Tôi đã tìm thấy điều này sau khi thử nghiệm try/catchtừ @enobrev ở trên, nhưng điều này cho phép mã ít dài hơn (và IMO, dễ đọc hơn). Chúng tôi chỉ đơn giản sử dụng error_get_lastđể lấy văn bản của lỗi cuối cùng và file_get_contentstrả về sai khi thất bại, vì vậy một "nếu" đơn giản có thể bắt được điều đó.


2
Đây là giải pháp dễ nhất và tốt nhất cho vấn đề này! Có thể làm cho nó @file_get_contentsđể thay thế báo cáo lỗi cho trình duyệt.
EDP

1
Tôi thừa nhận rằng trong số tất cả các câu trả lời, đây là câu trả lời hợp lý duy nhất - nếu chúng tôi tăng cường sử dụng nó @file_get_contentsđể triệt tiêu cảnh báo kiểm tra giá trị kết quả bằng cách sử dụng === FALSE.
kostix

11
Điều này sẽ kích hoạt các lỗi cho các yêu cầu thành công không trả về phần thân hoặc trả lại một yêu cầu đánh giá thành sai. Nên làif (false !== ($data = file_get_contents ()))
GordonM

Tài liệu này không làm cho nó rõ ràng, nhưng sử dụng @ có thể error_get_lastkhông mang lại điều gì trong trải nghiệm của tôi
Glenn Schmidt

33

Bạn có thể đăng ký @: $content = @file_get_contents($site);

Điều này sẽ thay thế bất kỳ cảnh báo - sử dụng một cách tiết kiệm! . Xem Toán tử kiểm soát lỗi

Chỉnh sửa: Khi bạn xóa 'http: //', bạn không còn tìm kiếm một trang web, mà là một tệp trên đĩa của bạn có tên là "www.google ....."


Đó là điều duy nhất thực sự hoạt động - Tôi không thể ngăn chặn thông báo "không mở được luồng" theo bất kỳ cách nào khác.
Olaf

21

Một cách khác là để khắc phục lỗi và cũng đưa ra một ngoại lệ mà bạn có thể bắt gặp sau này. Điều này đặc biệt hữu ích nếu có nhiều lệnh gọi đến file_get_contents () trong mã của bạn, vì bạn không cần phải loại bỏ và xử lý tất cả chúng theo cách thủ công. Thay vào đó, một số cuộc gọi có thể được thực hiện cho chức năng này trong một khối thử / bắt.

// 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

Đây là cách tôi đã làm ... Không cần khối thử bắt ... Giải pháp tốt nhất luôn đơn giản nhất ... Hãy tận hưởng!

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

4
-1: điều này hoạt động nếu bạn gặp lỗi 404 hoặc một cái gì đó, nhưng không hoạt động nếu bạn không kết nối được với máy chủ (ví dụ: tên miền sai). Tôi nghĩ rằng $http_response_headerkhông được cập nhật trong trường hợp đó, vì không nhận được phản hồi HTTP.
Nathan Reed

1
Như @NathanReed nói, bạn nên kiểm tra $ nội dung không phải là sai (với ===) như đó là những gì được trở lại nếu yêu cầu không để kết nối ở tất cả
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
}

Điều này không hoạt động. Nếu $urlkhông tìm thấy 404, cảnh báo sẽ vẫn xuất hiện.
Raptor

Đúng Raptor, tôi đã cải thiện câu trả lời với stream_context_create (); Không có gì tốt hơn ... "@" không được đề xuất
RafaSashi

1
ignore_errorschỉ hướng dẫn ngữ cảnh HTTP không hiểu mã trạng thái phản hồi HTTP > = 400 là lỗi. Mặc dù có liên quan với nhau, nhưng điều đó không trả lời cho câu hỏi xử lý lỗi PHP.
mặt trời

Cảm ơn cho sự ignore_errorslựa chọn! Đây là những gì tôi cần!
Modder

6

Đây là cách tôi xử lý:

$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

Điều tốt nhất sẽ là đặt các trình xử lý lỗi và ngoại lệ của riêng bạn, việc này sẽ làm một cái gì đó hữu ích như đăng nhập nó vào một tệp hoặc gửi email những lỗi quan trọng. http://www.php.net/set_error_handler


1

Bạn có thể sử dụng tập lệnh này

$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";
}

Điều này cần so sánh nghiêm ngặt: if ($url === true)...bởi vì nếu bạn nhận được phản hồi 0hoặc trống, nó sẽ gây ra lỗi kết nối.
Daniel W.

1

Vì PHP 4 sử dụng error_Vporting () :

$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

Cách đơn giản nhất để làm điều này chỉ là trả trước một @ trước file_get_contents, i. e.:

$content = @file_get_contents($site); 

1

đại loại như thế này:

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

Bạn nên sử dụng hàm file_exists () trước để sử dụng file_get_contents (). Với cách này, bạn sẽ tránh được cảnh báo php.

$file = "path/to/file";

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

Điều này sẽ chỉ hoạt động, nếu bạn gọi một tệp cục bộ và bạn có quyền để kiểm tra tệp cục bộ nếu nó tồn tại
rubo77

-3

Thay đổi tệp php.ini

allow_url_fopen = On

allow_url_include = On

Đừng làm điều này. Đặc biệt không cho phép url bao gồm. Đừng tin tôi. Nó đã bị tắt theo mặc định vì một lý do rất tốt # c99.
Daniel W.

-3

Điều này sẽ cố gắng để có được dữ liệu, nếu nó không hoạt động, nó sẽ bắt lỗi và cho phép bạn làm bất cứ điều gì bạn cần trong vòng bắt.

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 không phải lúc nào cũng đưa ra một ngoại lệ
khai báo

Bạn có muốn chỉnh sửa câu trả lời của mình và cho chúng tôi biết vào thời điểm nào file_get_content ném ngoại lệ không?
Ravinder Payal

1
Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
Jay Blanchard

-3

Bạn cũng nên đặt

allow_url_use = On 

trong của bạn php.iniđể ngừng nhận được cảnh báo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.