Việc sử dụng biểu tượng @ trong PHP là gì?


577

Tôi đã thấy việc sử dụng @trước các chức năng nhất định, như sau:

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

Việc sử dụng biểu tượng này là gì?


3
Cả RichieHulum và Aiden Bell đều đưa ra câu trả lời đúng nhưng vì tôi chỉ có thể đặt một câu trả lời là được chấp nhận, tôi sẽ chọn câu trả lời đầu tiên. Xin lỗi Aiden
sv_in

1
Loại bỏ các lỗi (mặc dù đẹp) có thể gây ra lỗi khi duy trì cơ sở mã ... stackoverflow.com/a/7116175/282343
dennismonsewicz

Câu trả lời:


636

Nó chặn các thông báo lỗi - xem Toán tử kiểm soát lỗi trong hướng dẫn PHP.


46
Đó là một chút rút ra nhanh chóng!
Aiden Bell

6
Vâng; xuống thứ hai! Tôi đã phải kiểm tra câu trả lời để xem ai đến trước :)
Sampson

3
Tôi đã có thời gian để sửa lỗi chính tả của mình sau khi đăng ... và chết tiệt bạn vì đã tăng cường với một liên kết cùng lúc cơn thịnh nộ : P
Aiden Bell

1
Tính năng tuyệt vời .. Nó làm cho việc sử dụng isset()không cần thiết để tránh undefined offsetlỗi.
WM

470

Nó ngăn chặn lỗi.

Xem Toán tử kiểm soát lỗi trong hướng dẫn:

PHP hỗ trợ một toán tử kiểm soát lỗi: dấu tại (@). Khi được thêm vào một biểu thức trong PHP, mọi thông báo lỗi có thể được tạo bởi biểu thức đó sẽ bị bỏ qua.

Nếu bạn đã thiết lập chức năng xử lý lỗi tùy chỉnh với set_error_handler () thì nó vẫn sẽ được gọi, nhưng trình xử lý lỗi tùy chỉnh này có thể (và nên) gọi error_Vporting () sẽ trả về 0 khi cuộc gọi đã kích hoạt lỗi xảy ra trước một @ ...


157
nâng cao chỉ vì câu trả lời khác là nhận được tất cả tình yêu.
ajacian81

10
19 người đứng sau ... mọi người hãy đánh bại RichieHulum: P
Aiden Bell

Câu trả lời này là câu đầu tiên (Trong bối cảnh ai trả lời trước).
Mohd Abdul Mujib

227

Các @biểu tượng là kiểm soát lỗi điều hành (còn gọi là "im lặng" hoặc "đóng-up" nhà điều hành). Nó làm cho PHP ngăn chặn mọi thông báo lỗi (thông báo, cảnh báo, gây tử vong, v.v.) được tạo bởi biểu thức liên quan. Nó hoạt động giống như một toán tử đơn nguyên, ví dụ, nó có quyền ưu tiên và kết hợp. Dưới đây là một số ví dụ:

@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"

Chính xác thì chuyện gì sẽ xảy ra nếu bạn sử dụng trình xử lý lỗi tùy chỉnh thay vì trình xử lý lỗi PHP tiêu chuẩn:

Nếu bạn đã thiết lập chức năng xử lý lỗi tùy chỉnh với set_error_handler () thì nó vẫn sẽ được gọi, nhưng trình xử lý lỗi tùy chỉnh này có thể (và nên) gọi error_Vporting () sẽ trả về 0 khi cuộc gọi đã kích hoạt lỗi xảy ra trước một @ .

Điều này được minh họa trong ví dụ mã sau:

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"

Trình xử lý lỗi không kiểm tra xem @biểu tượng có hiệu lực hay không. Hướng dẫn gợi ý như sau:

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

58

Cũng lưu ý rằng mặc dù các lỗi bị ẩn, mọi trình xử lý lỗi tùy chỉnh (được đặt bằng set_error_handler) vẫn sẽ được thực thi!


34

Giống như đã được trả lời trước đây: @Toán tử loại bỏ tất cả các lỗi trong PHP, bao gồm các thông báo, cảnh báo và thậm chí các lỗi nghiêm trọng.

NHƯNG: Xin vui lòng, thực sự không sử dụng @toán tử.

Tại sao?

Chà, bởi vì khi bạn sử dụng @toán tử để khắc phục lỗi, bạn không có đầu mối nào để bắt đầu khi có lỗi xảy ra. Tôi đã có một số "niềm vui" với mã kế thừa nơi một số nhà phát triển đã sử dụng @toán tử khá thường xuyên. Đặc biệt trong các trường hợp như thao tác tệp, cuộc gọi mạng, v.v ... Đó là tất cả các trường hợp có rất nhiều nhà phát triển khuyên bạn nên sử dụng@ toán tử vì điều này đôi khi nằm ngoài phạm vi khi xảy ra lỗi ở đây (ví dụ: API của bên thứ ba có thể không truy cập được, v.v. ).

Nhưng những gì vẫn không sử dụng nó? Chúng ta hãy nhìn từ hai góc độ:

Là một nhà phát triển: Khi@được sử dụng, tôi hoàn toàn không biết bắt đầu từ đâu. Nếu có hàng trăm hoặc thậm chí hàng ngàn cuộc gọi chức năng với@ lỗi có thể giống như mọi lúc. Không có gỡ lỗi hợp lý có thể trong trường hợp này. Và ngay cả khi đó chỉ là lỗi của bên thứ 3 - thì nó vẫn ổn và bạn đã hoàn thành nhanh chóng. ;--

Là người dùng: Người dùng không quan tâm đến lý do lỗi là gì hay không. Phần mềm ở đó để họ làm việc, để hoàn thành một nhiệm vụ cụ thể, v.v. Họ không quan tâm nếu đó là lỗi của nhà phát triển hay vấn đề của bên thứ ba. Đặc biệt đối với người dùng, tôi thực sự khuyên bạn nên ghi lại tất cả các lỗi, ngay cả khi chúng nằm ngoài phạm vi. Có thể bạn sẽ nhận thấy rằng một API cụ thể thường xuyên ngoại tuyến. Bạn có thể làm gì? Bạn có thể nói chuyện với đối tác API của mình và nếu họ không thể giữ ổn định, có lẽ bạn nên tìm kiếm đối tác khác.

Tóm lại: Bạn nên biết rằng có tồn tại một cái gì đó như @(kiến thức luôn tốt), nhưng đừng sử dụng nó . Nhiều nhà phát triển (đặc biệt là các mã gỡ lỗi từ người khác) sẽ rất biết ơn.


1
Một số cảnh báo chỉ có thể được loại bỏ một cách đáng tin cậy bằng cách sử dụng @ (ví dụ fopen (), trong đó mọi nỗ lực dự đoán kết quả đều phải tuân theo điều kiện cuộc đua), nếu bạn có mã để xử lý tình trạng lỗi theo cách gọn gàng hơn thì usuig @là điều đúng đắn. làm, điều này đặc biệt hữu ích đặc biệt nếu bạn không trả lại text/html(hoặc tương tự) cho khách hàng. (có thể quay lại image/pnghoặc "json")
Jasen

1
Bạn không nên kìm nén cảnh báo - họ nói rằng bạn đã làm sai điều gì đó. Không có điều kiện cuộc đua trong đó bạn không thể kiểm tra hoặc xử lý đúng trạng thái.
Ryan Rentfro

1
Tôi có mã sau đây ở một vài nơi. if( session_status() == PHP_SESSION_NONE ) session_start(); Đó là một ứng dụng kế thừa mà tôi được thừa hưởng và có những nơi mà tập lệnh thiết lập được gọi nhiều lần, vì vậy tôi phải kiểm tra. Điều gì, nếu có, vấn đề sẽ có chỉ đơn giản là sử dụng @session_start();?
Stephen R

Nếu bạn biết những gì bạn đang làm và sử dụng nó một cách tiết kiệm / chiến lược, thì nó đáng để sử dụng. @$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;tốt hơn rất nhiều so với việc thay thế bằng việc kiểm tra ngay lập tức ở mỗi cấp độ và điền vào khi không.
dtbarne

1
Hãy cho tôi một lý do chính đáng tại sao việc thêm 12+ dòng mã và không thêm giá trị mà chỉ làm giảm khả năng đọc và tính ngắn gọn của mã là đáng làm hơn là bạn đọc ở đâu đó một lúc nào đó "bẩn" và có thể bạn có thể thay đổi suy nghĩ của mình.
dtbarne

7

Giả sử chúng ta chưa sử dụng toán tử "@" thì mã của chúng ta sẽ như thế này:

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

Và nếu không tìm thấy tệp chúng tôi đang cố mở thì sao? Nó sẽ hiển thị một thông báo lỗi.

Để chặn thông báo lỗi, chúng tôi đang sử dụng toán tử "@" như:

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

Đây là một ví dụ hoàn hảo cho lý do tại sao PHP có loại @giải pháp này ngay từ đầu. Các ngôn ngữ lập trình khác có xử lý ngoại lệ thống nhất để xử lý loại kịch bản stackoverflow.com/questions/1087365
dreftymac

@dreftymac Chính xác!
Sujeet Kumar

5

Nếu mở thất bại, lỗi cấp độ E_WARNING được tạo. Bạn có thể sử dụng @ để chặn cảnh báo này.


5

@ ngăn chặn các thông báo lỗi.

Nó được sử dụng trong các đoạn mã như:

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

Nếu tên miền " http://www.exaple.com " không thể truy cập được, một lỗi sẽ được hiển thị, nhưng @không có gì không được hiển thị.


1

PHP hỗ trợ một toán tử kiểm soát lỗi: dấu hiệu (@) . Khi được thêm vào một biểu thức trong PHP, mọi thông báo lỗi có thể được tạo bởi biểu thức đó sẽ bị bỏ qua.

Nếu bạn đã thiết lập chức năng xử lý lỗi tùy chỉnh set_error_handler()thì nó vẫn sẽ được gọi, nhưng trình xử lý lỗi tùy chỉnh này có thể (và nên) sẽ gọi error_reporting()lại 0khi cuộc gọi kích hoạt lỗi xảy ra trước một @.

<?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.

?>

Ghi chú:-

1) @ -operator chỉ hoạt động trên các biểu thức.

2) Một quy tắc đơn giản là: nếu bạn có thể lấy giá trị của một cái gì đó, bạn có thể trả trước toán tử @ cho nó. Chẳng hạn, bạn có thể thêm nó vào các biến, hàm và bao gồm các lệnh gọi, hằng, v.v. Bạn không thể thêm nó vào các định nghĩa hàm hoặc lớp hoặc các cấu trúc có điều kiện như if và foreach, v.v.

Cảnh báo:-

Hiện tại tiền tố toán tử kiểm soát lỗi "@" thậm chí sẽ vô hiệu hóa báo cáo lỗi đối với các lỗi nghiêm trọng sẽ chấm dứt thực thi tập lệnh. Trong số những thứ khác, điều này có nghĩa là nếu bạn sử dụng "@" để loại bỏ lỗi từ một chức năng nhất định và nó không khả dụng hoặc bị nhập sai, tập lệnh sẽ chết ngay tại đó mà không có dấu hiệu cho thấy tại sao.


1

Có thể đáng để thêm vào đây, có một vài gợi ý khi sử dụng @ bạn nên biết, để hoàn thành, hãy xem bài đăng này: http://mstd.eu/index.php/2016/06/30/php- quick-fire-what-is-the-icon-used-for-in-php /

  1. Trình xử lý lỗi vẫn được kích hoạt ngay cả khi ký hiệu @ được chuẩn bị trước, điều đó chỉ có nghĩa là mức lỗi 0 được đặt, điều này sẽ phải được xử lý thích hợp trong trình xử lý lỗi tùy chỉnh.

  2. Chuẩn bị bao gồm với @ sẽ đặt tất cả các lỗi trong tệp đính kèm thành mức lỗi là 0


1

@triệt tiêu thông báo lỗi do hàm ném. fopenném lỗi khi tập tin không thoát. @biểu tượng làm cho việc thực thi chuyển sang dòng tiếp theo ngay cả khi tệp không tồn tại. Đề nghị của tôi sẽ không sử dụng điều này trong môi trường cục bộ của bạn khi bạn phát triển mã PHP.

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.