การใช้สัญลักษณ์ @ ใน PHP คืออะไร?


577

ฉันได้เห็นการใช้@ด้านหน้าฟังก์ชั่นบางอย่างดังต่อไปนี้:

$fileHandle = @fopen($fileName, $writeAttributes);

การใช้สัญลักษณ์นี้คืออะไร?


3
ทั้ง RichieHindle และ Aiden Bell ให้คำตอบที่ถูกต้อง แต่เนื่องจากฉันสามารถตั้งค่าคำตอบเดียวเท่านั้นที่ยอมรับฉันจะเลือกคำตอบแรก ขออภัย Aiden
sv_in

1
การระงับข้อผิดพลาด (แม้ว่าจะดี) อาจทำให้เกิดข้อผิดพลาดได้เมื่อทำการบำรุงรักษา codebase ... stackoverflow.com/a/7116175/282343
dennismonsewicz

คำตอบ:


636

มันระงับข้อความแสดงข้อผิดพลาด - ดูผู้ควบคุมข้อผิดพลาดในคู่มือ PHP


46
นั่นเป็นบิตของการวาดอย่างรวดเร็ว!
Aiden Bell

6
ใช่; ลงไปที่สอง! ฉันได้ไปตรวจสอบคำตอบ-ID ที่จะดูว่าใครเข้ามาในครั้งแรก :)
จอห์น

3
ฉันมีเวลาที่จะแก้ไขการสะกดคำปราบปรามของฉันหลังจากโพสต์ ... และไอ้คุณเพื่อปรับปรุงด้วยการเชื่อมโยงในเวลาเดียวกันrages : P
Aiden Bell

1
คุณสมบัติเจ๋ง .. มันทำให้การใช้งานของisset()ไม่จำเป็นเพื่อหลีกเลี่ยงundefined offsetข้อผิดพลาด
WM

470

มันหยุดข้อผิดพลาด

ดูตัวควบคุมข้อผิดพลาดในคู่มือ:

PHP รองรับตัวควบคุมข้อผิดพลาดหนึ่งตัว: ที่เครื่องหมาย (@) เมื่อผนวกกับนิพจน์ใน PHP ข้อความแสดงข้อผิดพลาดที่อาจสร้างขึ้นโดยนิพจน์นั้นจะถูกละเว้น

หากคุณตั้งค่าฟังก์ชันตัวจัดการข้อผิดพลาดแบบกำหนดเองด้วยset_error_handler ()มันจะยังคงถูกเรียก แต่ตัวจัดการข้อผิดพลาดแบบกำหนดเองนี้สามารถ (และควร) เรียกerror_reporting ()ซึ่งจะส่งกลับ 0 เมื่อการเรียกที่เรียกใช้ข้อผิดพลาดถูกนำหน้าด้วย @ ...


157
upvoted เพียงเพราะคำตอบอื่น ๆ คือการได้รับความรักทั้งหมด
ajacian81

10
ข้างหลัง 19 คน ... เราจะต้องเอาชนะ RichieHindle: P
Aiden Bell

คำตอบนี้เป็นคำตอบแรก (ตามบริบทกับผู้ที่ตอบก่อน)
Mohd Abdul Mujib

227

@สัญลักษณ์คือควบคุมความผิดพลาดผู้ประกอบการ (aka "ความเงียบ" หรือ "ปิดขึ้น" ผู้ประกอบการ) มันทำให้ PHP ระงับข้อความแสดงข้อผิดพลาด (การแจ้งเตือนคำเตือนร้ายแรง ฯลฯ ) ที่สร้างขึ้นโดยการแสดงออกที่เกี่ยวข้อง มันทำงานเหมือนกับโอเปอเรเตอร์ unary ตัวอย่างเช่นมันมีลำดับความสำคัญและการเชื่อมโยง ด้านล่างเป็นตัวอย่าง:

@echo 1 / 0;
// generates "Parse error: syntax error, unexpected T_ECHO" since 
// echo is not an expression

echo @(1 / 0);
// suppressed "Warning: Division by zero"

@$i / 0;
// suppressed "Notice: Undefined variable: i"
// displayed "Warning: Division by zero"

@($i / 0);
// suppressed "Notice: Undefined variable: i"
// suppressed "Warning: Division by zero"

$c = @$_POST["a"] + @$_POST["b"];
// suppressed "Notice: Undefined index: a"
// suppressed "Notice: Undefined index: b"

$c = @foobar();
echo "Script was not terminated";
// suppressed "Fatal error: Call to undefined function foobar()"
// however, PHP did not "ignore" the error and terminated the
// script because the error was "fatal"

จะเกิดอะไรขึ้นหากคุณใช้ตัวจัดการข้อผิดพลาดที่กำหนดเองแทนตัวจัดการข้อผิดพลาด PHP มาตรฐาน:

หากคุณตั้งค่าฟังก์ชันตัวจัดการข้อผิดพลาดแบบกำหนดเองด้วย set_error_handler () มันจะยังคงถูกเรียก แต่ตัวจัดการข้อผิดพลาดแบบกำหนดเองนี้สามารถ (และควร) เรียก error_reporting () ซึ่งจะส่งกลับ 0 เมื่อการเรียกที่เรียกใช้ข้อผิดพลาดถูกนำหน้าด้วย @ .

นี่คือตัวอย่างในตัวอย่างรหัสต่อไปนี้:

function bad_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    echo "[bad_error_handler]: $errstr";
    return true;
}
set_error_handler("bad_error_handler");
echo @(1 / 0);
// prints "[bad_error_handler]: Division by zero"

ตัวจัดการข้อผิดพลาดไม่ได้ตรวจสอบว่า@สัญลักษณ์มีผล คู่มือแนะนำต่อไปนี้:

function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    if(error_reporting() !== 0) {
        echo "[better_error_handler]: $errstr";
    }
    // take appropriate action
    return true;
}

58

โปรดทราบว่าแม้จะมีข้อผิดพลาดถูกซ่อนอยู่ตัวจัดการข้อผิดพลาดแบบกำหนดเองใด ๆ (ตั้งค่าด้วยset_error_handler) จะยังคงถูกใช้งาน!


34

เช่นเดียวกับที่บางคนตอบก่อนหน้านี้: @โอเปอเรเตอร์ระงับข้อผิดพลาดทั้งหมดใน PHP รวมถึงประกาศคำเตือนและแม้แต่ข้อผิดพลาดที่สำคัญ

แต่: ได้ โปรดอย่าใช้ตัว@ดำเนินการเลย

ทำไม?

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

แต่ประเด็นที่ยังไม่ได้ใช้คืออะไร ลองมาดูจากสองมุมมอง:

ในฐานะนักพัฒนาซอฟต์แวร์:เมื่อ@มีการใช้งานฉันไม่ทราบว่าจะเริ่มจากตรงไหน หากมีการเรียกใช้ฟังก์ชั่นหลายร้อยหรือหลายพันครั้งโดยมี@ข้อผิดพลาดอาจเหมือนกับทุกครั้ง ไม่สามารถทำการดีบักอย่างสมเหตุสมผลในกรณีนี้ และแม้ว่ามันจะเป็นเพียงข้อผิดพลาดของบุคคลที่สาม - แต่ก็ไม่เป็นไรและคุณก็ทำได้เร็ว ;-) ยิ่งไปกว่านั้นควรเพิ่มรายละเอียดให้เพียงพอในบันทึกข้อผิดพลาดดังนั้นนักพัฒนาสามารถตัดสินใจได้อย่างง่ายดายว่ารายการบันทึกเป็นสิ่งที่ต้องตรวจสอบเพิ่มเติมหรือหากเป็นเพียงความล้มเหลวของบุคคลที่ 3 ที่อยู่นอกขอบเขตของนักพัฒนา

ในฐานะผู้ใช้:ผู้ใช้ไม่สนใจเลยว่าอะไรคือสาเหตุของข้อผิดพลาดหรือไม่ มีซอฟต์แวร์สำหรับให้พวกเขาทำงานเพื่อทำงานให้เสร็จ ฯลฯ โดยเฉพาะพวกเขาไม่สนใจว่ามันเป็นความผิดของนักพัฒนาหรือปัญหาของบุคคลที่สาม โดยเฉพาะอย่างยิ่งสำหรับผู้ใช้ฉันขอแนะนำให้บันทึกข้อผิดพลาดทั้งหมดแม้ว่าจะอยู่นอกขอบเขตก็ตาม บางทีคุณอาจสังเกตว่า API เฉพาะนั้นออฟไลน์บ่อยๆ คุณทำอะไรได้บ้าง? คุณสามารถพูดคุยกับคู่ค้า API ของคุณและหากพวกเขาไม่สามารถรักษาความมั่นคงไว้ได้คุณควรมองหาพันธมิตรรายอื่น

ในระยะสั้น:คุณควรจะรู้ว่ามีบางสิ่งบางอย่างเช่น@(ความรู้อยู่เสมอดี) แต่เพียงไม่ได้ใช้มัน นักพัฒนาหลายคน (โดยเฉพาะอย่างยิ่งรหัสการแก้จุดบกพร่องจากผู้อื่น) จะขอบคุณมาก


1
คำเตือนบางอย่างสามารถระงับได้อย่างน่าเชื่อถือโดยใช้ @ (เช่น fopen () ซึ่งความพยายามใด ๆ ที่จะทำนายผลลัพธ์ขึ้นอยู่กับสภาพการแข่งขัน) หากคุณมีรหัสที่จะจัดการกับข้อผิดพลาดในลักษณะที่@เป็นระเบียบเรียบร้อยแล้วทำสิ่งนี้มีประโยชน์อย่างยิ่งโดยเฉพาะถ้าคุณไม่ส่งคืนtext/html(หรือคล้ายกัน) ให้กับลูกค้า (อาจกลับมาimage/pngหรือ "json")
Jasen

1
คุณไม่ควรระงับคำเตือน - พวกเขากำลังระบุว่าคุณทำอะไรผิด ไม่มีสภาพการแข่งขันที่คุณไม่สามารถตรวจสอบหรือจัดการสถานะได้อย่างถูกต้อง
Ryan Rentfro

1
ฉันมีรหัสต่อไปนี้ในบางที่ if( session_status() == PHP_SESSION_NONE ) session_start(); มันเป็นแอพที่ฉันสืบทอดมาและมีหลายที่ที่สคริปต์การตั้งค่าถูกเรียกหลายครั้งดังนั้นฉันต้องทดสอบ หากมีปัญหาจะเกิดขึ้นเพียงแค่ใช้@session_start();อะไร?
Stephen R

หากคุณรู้ว่าคุณกำลังทำอะไรอยู่และใช้งานอย่างไม่ จำกัด / อย่างมีกลยุทธ์ก็ควรใช้ @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;ดีกว่าทางเลือกอื่น ๆ ของการมีการตรวจสอบของผู้ออกบัตรในแต่ละระดับและกรอกข้อมูลในกรณีที่ไม่ใช่
dtbarne

1
ขอให้ฉันเหตุผลที่ดีว่าทำไมการเพิ่มโค้ด 12+ บรรทัดและไม่เพิ่มค่าใด ๆ แต่การลดความสามารถในการอ่านและความกระชับของโค้ดนั้นมีค่ามากกว่าที่คุณอ่านบางครั้งว่า "สกปรกธรรมดา" และบางทีคุณอาจเปลี่ยนใจได้
dtbarne

7

สมมติว่าเราไม่ได้ใช้โอเปอเรเตอร์ "@" ดังนั้นรหัสของเราจะเป็นดังนี้:

$fileHandle = fopen($fileName, $writeAttributes);

และถ้าไฟล์ที่เราพยายามเปิดไม่พบ? มันจะแสดงข้อความผิดพลาด

ในการระงับข้อความแสดงข้อผิดพลาดเราใช้ตัวดำเนินการ "@" เช่น:

$fileHandle = @fopen($fileName, $writeAttributes);

นี่เป็นตัวอย่างที่สมบูรณ์แบบสำหรับสาเหตุที่ PHP มี@วิธีแก้ปัญหาแบบนี้ตั้งแต่แรก ภาษาการเขียนโปรแกรมอื่นมีการจัดการข้อยกเว้นอย่างสม่ำเสมอเพื่อจัดการสถานการณ์stackoverflow.com/questions/1087365
dreftymac

@dreftymac แน่นอน!
Sujeet Kumar

5

หากการเปิดล้มเหลวข้อผิดพลาดของระดับ E_WARNING จะถูกสร้างขึ้น คุณอาจใช้ @ เพื่อระงับคำเตือนนี้


5

@ ไม่แสดงข้อความผิดพลาด

มันถูกใช้ในตัวอย่างโค้ดเช่น:

@file_get_contents('http://www.exaple.com');

หากไม่สามารถเข้าถึงโดเมน " http://www.exaple.com " ข้อผิดพลาดจะปรากฏ แต่@ไม่มีสิ่งใดปรากฏขึ้น


1

PHP สนับสนุนผู้ประกอบการควบคุมความผิดพลาดที่หนึ่ง: (@)เครื่องหมาย เมื่อผนวกกับนิพจน์ใน PHP ข้อความแสดงข้อผิดพลาดที่อาจสร้างขึ้นโดยนิพจน์นั้นจะถูกละเว้น

หากคุณได้ตั้งค่าฟังก์ชั่นจัดการข้อผิดพลาดที่กำหนดเองด้วยset_error_handler()แล้วมันจะยังคงได้รับการเรียก แต่จัดการข้อผิดพลาดที่กำหนดเองสามารถ (และควร) โทรerror_reporting()ซึ่งจะกลับมาเมื่อมีสายที่เรียกข้อผิดพลาดที่ถูกนำหน้าด้วย0@

<?php
/* Intentional file error */
$my_file = @file ('non_existent_file') or
    die ("Failed opening file: error was '$php_errormsg'");

// this works for any expression, not just functions:
$value = @$cache[$key];
// will not issue a notice if the index $key doesn't exist.

?>

บันทึก:-

1) @ -operator ใช้งานได้กับนิพจน์เท่านั้น

2) กฎง่ายๆคือถ้าคุณสามารถนำค่าของบางสิ่งมาคุณสามารถเพิ่มตัวดำเนินการ @ ให้กับมันได้ ตัวอย่างเช่นคุณสามารถเติมลงในตัวแปรฟังก์ชั่นและรวมถึงการโทรค่าคงที่และอื่น ๆ คุณไม่สามารถเติมให้ฟังก์ชันหรือคำจำกัดความของคลาสหรือโครงสร้างที่มีเงื่อนไขเช่น if and foreach และอื่น ๆ

คำเตือน:-

ปัจจุบันคำนำหน้าโอเปอเรเตอร์ควบคุมข้อผิดพลาด "@" จะปิดใช้งานการรายงานข้อผิดพลาดเพื่อหาข้อผิดพลาดที่สำคัญซึ่งจะยุติการทำงานของสคริปต์ เหนือสิ่งอื่นใดซึ่งหมายความว่าหากคุณใช้ "@" เพื่อระงับข้อผิดพลาดจากฟังก์ชั่นบางอย่างและไม่สามารถใช้งานได้หรือมีการพิมพ์ผิดสคริปต์จะตายที่นั่นโดยไม่มีข้อบ่งชี้ว่าทำไม


1

มันอาจจะคุ้มที่จะเพิ่มที่นี่มีตัวชี้ไม่กี่เมื่อใช้ @ คุณควรทราบสำหรับการทำงานลงอย่างสมบูรณ์ดูโพสต์นี้: http://mstd.eu/index.php/2016/06/30/php- ไฟอย่างรวดเร็วสิ่งที่เป็นที่สัญลักษณ์ที่ใช้สำหรับใน PHP /

  1. ตัวจัดการข้อผิดพลาดยังคงทำงานอยู่แม้ว่าจะมีสัญลักษณ์ @ เตรียมไว้แล้วก็หมายความว่าตั้งค่าระดับความผิดพลาดเป็น 0 ซึ่งจะต้องจัดการอย่างเหมาะสมในตัวจัดการข้อผิดพลาดที่กำหนดเอง

  2. การเตรียมการรวมด้วย @ จะตั้งข้อผิดพลาดทั้งหมดในไฟล์รวมเป็นระดับข้อผิดพลาดที่ 0


1

@ไม่แสดงข้อความแสดงความผิดพลาดที่เกิดจากฟังก์ชัน fopenโยนข้อผิดพลาดเมื่อไฟล์ไม่ออก @สัญลักษณ์ทำให้การดำเนินการเพื่อย้ายไปยังบรรทัดถัดไปแม้ไฟล์จะไม่มีอยู่ ข้อเสนอแนะของฉันจะไม่ใช้สิ่งนี้ในสภาพแวดล้อมท้องถิ่นของคุณเมื่อคุณพัฒนาโค้ด PHP

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