ฉันจะจัดการคำเตือนของฟังก์ชัน file_get_contents () ใน PHP ได้อย่างไร


312

ฉันเขียนโค้ด PHP เช่นนี้

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

แต่เมื่อฉันลบ "http: //" ออกจาก$siteฉันได้รับคำเตือนต่อไปนี้:

คำเตือน: file_get_contents (www.google.com) [function.file-get-content]: ไม่สามารถเปิดสตรีม:

ฉันลองtryแล้วcatchแต่มันใช้งานไม่ได้


2
วิธีการที่น่าสนใจเช่น: stackoverflow.com/questions/6718598/…
Hugo Stieglitz

เกี่ยวข้อง: stackoverflow.com/q/2002610
Fr0zenFyr

ใช้ลองจับกับ set_error_handler ฟังก์ชั่นตามที่กล่าวไว้ที่นี่stackoverflow.com/a/3406181/1046909
MingalevME

2
หากคุณลบ http: // จาก url คุณจะค้นหาไฟล์ "www.google.com" บนดิสก์ในเครื่องของคุณ
Rauli Rajande

วิธีนี้จะได้รับความสนใจและ upvotes มาก ทำไมคุณจะลบข้อมูลโปรโตคอล แม้ในปี 2008 คุณมี FTP และ HTTPS
Daniel W.

คำตอบ:


507

ขั้นตอนที่ 1: ตรวจสอบรหัสส่งคืน: if($content === FALSE) { // handle error here... }

ขั้นตอนที่ 2: ระงับคำเตือนโดยวางโอเปอเรเตอร์ควบคุมข้อผิดพลาด (เช่น@) ไว้ข้างหน้าการเรียกไปยังfile_get_contents () : $content = @file_get_contents($site);


86
อย่าลืมใช้การเปรียบเทียบอย่างเข้มงวด: ถ้า ($ content === FALSE) หากไฟล์มี "0" มันจะทำให้เกิดการลบที่ผิดพลาด
Aram Kocharyan

7
สวัสดีนี่ไม่ได้ผลสำหรับฉันการเพิ่ม @ ยังทำให้ E_WARNING ถูกจับโดยตัวจัดการข้อผิดพลาดระดับโลก (ไม่ใช่ของฉัน) และสคริปต์ของฉันจะตายก่อนที่ฉันจะมีโอกาสจัดการกับค่าส่งคืน ความคิดใด ๆ TNX
Sagi Mann

1
ตรวจพบผลข้างเคียง: หากไฟล์ไม่มีอยู่สคริปต์จะหยุดที่บรรทัด @file_get_contents
Dax

สิ่งนี้ไม่ได้ผลสำหรับฉันแม้ว่านี่จะเป็นทางออกที่ถูกต้องก็ตาม ฉันมีการเตือนการหมดเวลาโดยไม่ได้รับข้อมูล แต่ $ content === FALSE ไม่ใช่ "ทริกเกอร์" ($ ไซต์ถูกเรียกจากเซิร์ฟเวอร์ localhost โปรดทราบว่าฉันมีข้อมูลอย่างรวดเร็วหากฉันวาง URL ลงในเบราว์เซอร์)
Oliver

4
แม้ว่าคำตอบจะเก่ามาก แต่ฉันก็ยังแนะนำให้เพิ่มหมายเหตุลงในคำตอบของคุณว่าการใช้@อาจส่งผลเสียต่อประสิทธิภาพการทำงาน ดูคำตอบนี้ในโพสต์ที่เกี่ยวข้องซึ่งอธิบายได้ค่อนข้างดี
Fr0zenFyr

148

นอกจากนี้คุณยังสามารถตั้งค่าตัวจัดการข้อผิดพลาดของคุณเป็นฟังก์ชั่นที่ไม่ระบุชื่อที่เรียกข้อยกเว้นและใช้ลอง / จับข้อยกเว้นที่

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

ดูเหมือนว่าจะมีรหัสมากมายที่จะตรวจจับข้อผิดพลาดเพียงเล็กน้อย แต่ถ้าคุณใช้ข้อยกเว้นในแอปของคุณคุณจะต้องทำสิ่งนี้เพียงครั้งเดียววิธีที่ด้านบน (ตัวอย่างเช่นไฟล์ config ที่รวมอยู่) และจะ แปลงข้อผิดพลาดทั้งหมดของคุณเป็นข้อยกเว้นตลอด


เป็นหนึ่งในการปรับปรุง PHP ที่ยิ่งใหญ่ที่สุดที่ฉันเคยเห็น ขอบคุณ enobrev
Tomasz Smykowski

@enobrev ทำไมคุณใส่ค่าเดียวกันทั้งหมายเลขข้อผิดพลาดและความรุนแรง
Pacerier

ไม่มีเหตุผลเฉพาะนอกเหนือจากวิธีการเสนอสิ่งที่มีประโยชน์ใน $ exception-> getCode () เนื่องจาก set_error_handler ไม่ได้เสนอตัวแปรหมายเลขข้อผิดพลาด (น่าเสียดาย)
enobrev

1
@enobrev อย่าลืมคืนค่าตัวจัดการข้อผิดพลาดภายในฟังก์ชั่นที่ไม่ระบุชื่อก่อนโยนข้อยกเว้น สามารถจัดการข้อยกเว้นและในกรณีนั้นตัวจัดการยังคงตั้งค่าให้โยนข้อยกเว้นนี้ซึ่งอาจเกิดขึ้นโดยไม่คาดคิดและแนะนำแปลก ๆ ยากที่จะดีบั๊กพฤติกรรมเมื่อมีข้อผิดพลาดอื่นในการจัดการข้อยกเว้น
Josef Sábl

1
ฉันอยากจะแนะนำให้รวม restore_error_handler () โทรในที่สุด block
peschanko

67

วิธีที่ฉันโปรดปรานในการทำเช่นนี้ค่อนข้างง่าย:

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

ฉันพบสิ่งนี้หลังจากการทดลองกับtry/catchจาก @enobrev ด้านบน แต่สิ่งนี้จะช่วยให้รหัสยาว (และ IMO อ่านง่ายขึ้น) น้อยลง เราเพียงแค่ใช้error_get_lastเพื่อรับข้อความของข้อผิดพลาดล่าสุดและfile_get_contentsส่งกลับค่าเท็จเมื่อล้มเหลวดังนั้น "ถ้า" สามารถจับได้ง่าย


2
นี่คือทางออกที่ง่ายที่สุดและดีที่สุดสำหรับปัญหานี้! อาจทำให้@file_get_contentsการรายงานข้อผิดพลาดกับเบราว์เซอร์ถูกระงับ
EDP

1
ผมยอมรับว่าในคำตอบทั้งหมดนี้เป็นเพียงที่เหมาะสมหนึ่ง - ถ้าเราต้องการขยายไปใช้@file_get_contentsในการปราบปรามการเตือนและการ=== FALSEทดสอบค่าผลการใช้
kostix

11
วิธีนี้จะทำให้เกิดข้อผิดพลาดสำหรับคำขอที่ประสบความสำเร็จซึ่งจะไม่ส่งคืนเนื้อหาหรือส่งคืนข้อความที่ประเมินว่าเป็นเท็จ ควรเป็นif (false !== ($data = file_get_contents ()))
GordonM

เอกสารไม่ได้ทำให้มันชัดเจน แต่ใช้ @ สามารถทำให้เกิดการerror_get_lastที่จะกลับไม่มีอะไรในประสบการณ์ของฉัน
เกล็นชมิดท์

33

คุณสามารถเติม @: $content = @file_get_contents($site);

สิ่งนี้จะกำจัดคำเตือนใด ๆ - ใช้เท่าที่จำเป็น! . ดูตัวควบคุมข้อผิดพลาด

แก้ไข: เมื่อคุณลบ 'http: //' คุณจะไม่ค้นหาหน้าเว็บอีกต่อไป แต่ไฟล์ในดิสก์ของคุณชื่อ "www.google ..... "


นั่นเป็นสิ่งเดียวที่ใช้งานได้จริง - ฉันไม่สามารถระงับข้อความ "ไม่สามารถเปิดสตรีม" ได้ด้วยวิธีอื่น
โอลาฟ

21

อีกทางเลือกหนึ่งคือการระงับข้อผิดพลาดและยังโยนข้อยกเว้นที่คุณสามารถจับได้ในภายหลัง สิ่งนี้มีประโยชน์อย่างยิ่งหากมีการเรียก file_get_contents () หลายครั้งในรหัสของคุณเนื่องจากคุณไม่จำเป็นต้องระงับและจัดการการโทรทั้งหมดด้วยตนเอง แต่สามารถเรียกใช้ฟังก์ชันนี้ได้หลายครั้งในบล็อก 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

นี่คือวิธีที่ฉันทำ ... ไม่จำเป็นต้องลองบล็อก catch ... วิธีแก้ปัญหาที่ดีที่สุดคือวิธีที่ง่ายที่สุด ... สนุก!

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

4
-1: ใช้งานได้หากคุณได้รับข้อผิดพลาด 404 หรือบางอย่าง แต่ไม่ใช่ถ้าคุณไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้เลย (เช่นชื่อโดเมนผิด) ฉันคิดว่า$http_response_headerไม่มีการอัปเดตในกรณีนี้เนื่องจากไม่ได้รับการตอบกลับ HTTP
นาธานรีด

1
ตามที่ @NathanReed กล่าวว่าคุณควรตรวจสอบว่า $ content นั้นไม่ใช่เท็จ (พร้อม ===) เพราะนั่นคือสิ่งที่จะได้รับคืนหากคำขอไม่สามารถเชื่อมต่อได้เลย
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
}

มันใช้งานไม่ได้ หาก$urlไม่พบ 404 คำเตือนจะยังคงปรากฏขึ้น
Raptor

Raptor ใช่ฉันได้ปรับปรุงคำตอบด้วย stream_context_create (); ไม่มีอะไรดีไปกว่านี้ ... "@" ไม่แนะนำ
RafaSashi

1
ignore_errorsสั่งให้บริบท HTTP ไม่แปลรหัสสถานะการตอบกลับHTTP > = 400 เป็นข้อผิดพลาดเท่านั้น ในขณะที่เกี่ยวข้องเล็กน้อยที่ไม่ตอบคำถามของการจัดการข้อผิดพลาด PHP
อาทิตย์

ขอบคุณสำหรับignore_errorsตัวเลือก! นี่คือสิ่งที่ฉันต้องการ!
Modder

6

นี่คือวิธีที่ฉันจัดการ:

$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

สิ่งที่ดีที่สุดคือการตั้งค่าตัวจัดการข้อผิดพลาดและตัวจัดการข้อยกเว้นของคุณซึ่งจะทำสิ่งที่มีประโยชน์เช่นการเข้าสู่ระบบในไฟล์หรือส่งอีเมลที่สำคัญ http://www.php.net/set_error_handler


1

คุณสามารถใช้สคริปต์นี้

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

สิ่งนี้ต้องการการเปรียบเทียบที่เข้มงวด: if ($url === true)...เพราะถ้าคุณได้รับการตอบสนอง0หรือว่างเปล่ามันจะทำให้เกิดข้อผิดพลาดในการเชื่อมต่อ
Daniel W.


1

วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการเติม @ ก่อนที่ file_get_contents คือ i อี .:

$content = @file_get_contents($site); 

1

บางสิ่งเช่นนี้

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]);
}


-2

คุณควรใช้ฟังก์ชัน file_exists () ก่อนที่จะใช้ file_get_contents () ด้วยวิธีนี้คุณจะหลีกเลี่ยงคำเตือน php

$file = "path/to/file";

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

สิ่งนี้จะใช้งานได้ถ้าคุณเรียกไฟล์ในเครื่องและคุณมีสิทธิ์ที่ถูกต้องในการตรวจสอบไฟล์ในเครื่องถ้ามีอยู่จริง
rubo77

-3

เปลี่ยนไฟล์ php.ini

allow_url_fopen = On

allow_url_include = On

อย่าทำอย่างนี้ โดยเฉพาะอย่างยิ่งไม่อนุญาตให้รวม URL อย่าเชื่อฉัน มันถูกปิดการใช้งานโดยค่าเริ่มต้นด้วยเหตุผลที่ดีมาก # c99
Daniel W.

-3

วิธีนี้จะพยายามรับข้อมูลหากไม่สามารถใช้งานได้จะจับข้อผิดพลาดและอนุญาตให้คุณทำทุกอย่างที่คุณต้องการภายในการตรวจจับ

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 ไม่ได้ทำให้เกิดข้อยกเว้นเสมอ
marlar

คุณต้องการแก้ไขคำตอบและบอกเราว่า file_get_content มีข้อผิดพลาดเกิดขึ้นกี่ครั้ง
Ravinder Payal

1
ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
Jay Blanchard

-3

คุณควรตั้งค่า

allow_url_use = On 

ในของคุณที่php.iniจะหยุดรับคำเตือน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.