Thông báo của hoàng tử: Biến không xác định rõ ràng, Thông báo: Không xác định chỉ số, và Thông báo: Không xác định bù trừ bằng cách sử dụng PHP


1173

Tôi đang chạy tập lệnh PHP và tiếp tục nhận được các lỗi như:

Lưu ý: Biến không xác định: my_variable_name trong C: \ wamp \ www \ mypath \ index.php trên dòng 10

Lưu ý: Chỉ mục không xác định: my_index C: \ wamp \ www \ mypath \ index.php trên dòng 11

Dòng 10 và 11 trông như thế này:

echo "My variable value is: " . $my_variable_name;
echo "My index value is: " . $my_array["my_index"];

Ý nghĩa của các thông báo lỗi này là gì?

Tại sao họ đột nhiên xuất hiện? Tôi đã từng sử dụng kịch bản này trong nhiều năm và tôi chưa bao giờ gặp vấn đề gì.

Làm thế nào để tôi sửa chúng?


Đây là một câu hỏi tham khảo chung để mọi người liên kết thành bản sao, thay vì phải giải thích vấn đề này nhiều lần. Tôi cảm thấy điều này là cần thiết bởi vì hầu hết các câu trả lời trong thế giới thực về vấn đề này rất cụ thể.

Thảo luận về Meta liên quan:



3
biến có thể không được khởi tạo. Bạn đang khởi tạo biến từ một bài đăng hoặc nhận hoặc bất kỳ mảng nào? Nếu đó là trường hợp bạn có thể không có một trường trong mảng đó. Đó là truy cập của bạn.
Anish Silwal

3
@Pekka - Tôi nhận thấy chỉnh sửa thêm "và" Thông báo: offset không xác định "" - Sẽ không có ý nghĩa hơn khi sử dụng "PHP: mật biến không xác định ngoài PHP, vì nó được gắn thẻ là "php". Ngoài ra, URL bị cắt tại and-notice-undef, chỉ là một gợi ý để URL không bị cắt. Thậm chí có thể xóa các trích dẫn (quá nhiều). HoặcPHP: “Undefined variable/index/offset” notices
Funk Forty Niner

2
@Fred Tôi đoán một đối số có thể được tạo cho cả hai biến thể. Đây là một cơ hội mà người mới sẽ nhập toàn bộ dòng, bao gồm cả "Thông báo:" vào truy vấn tìm kiếm của họ, mà tôi chắc chắn là trình tạo lưu lượng truy cập chính cho câu hỏi này. Nếu các thông báo có đầy đủ, điều đó có khả năng cải thiện khả năng hiển thị trong các công cụ tìm kiếm
Pekka

2
@Pekka Tôi hiểu. Tôi chỉ nói rằng bởi vì URL không bị cắt trước đó và bây giờ nó không hoạt động and-notice-undef. Đó chỉ là một (vài) đề nghị. Nó chỉ lặp đi lặp lại chính nó cũng được Notice: Undefined.
Funk Bốn mươi Niner

Câu trả lời:


1066

Chú ý: Biến không xác định

Từ trí tuệ rộng lớn của Hướng dẫn PHP :

Dựa vào giá trị mặc định của một biến chưa được khởi tạo là vấn đề trong trường hợp bao gồm một tệp vào một tệp khác sử dụng cùng một tên biến. Đây cũng là một rủi ro bảo mật lớn khi bật register_globals . Lỗi cấp độ E_NOTICE được ban hành trong trường hợp làm việc với các biến chưa được khởi tạo, tuy nhiên không phải trong trường hợp nối các phần tử vào mảng chưa được khởi tạo. Cấu trúc ngôn ngữ isset () có thể được sử dụng để phát hiện nếu một biến đã được khởi tạo. Ngoài ra và lý tưởng hơn là giải pháp của void () vì nó không tạo ra thông báo lỗi hoặc thông báo lỗi nếu biến không được khởi tạo.

Từ tài liệu PHP :

Không có cảnh báo nào được tạo nếu biến không tồn tại. Điều đó có nghĩa là rỗng () về cơ bản là tương đương ngắn gọn với ! Oseet ($ var) || $ var == sai .

Đây có nghĩa là bạn có thể sử dụng duy nhất empty()để xác định nếu biến được thiết lập, và thêm vào đó nó sẽ kiểm tra biến chống lại những điều sau đây, 0, 0.0, "", "0", null, falsehoặc [].

Thí dụ:

$o = [];
@$var = ["",0,null,1,2,3,$foo,$o['myIndex']];
array_walk($var, function($v) {
    echo (!isset($v) || $v == false) ? 'true ' : 'false';
    echo ' ' . (empty($v) ? 'true' : 'false');
    echo "\n";
});

Kiểm tra đoạn mã trên trong trình soạn thảo PHP trực tuyến 3v4l.org

Mặc dù PHP không yêu cầu khai báo biến, nhưng nó khuyến nghị nó để tránh một số lỗ hổng bảo mật hoặc lỗi mà người ta sẽ quên đưa ra một giá trị cho một biến sẽ được sử dụng sau này trong tập lệnh. Những gì PHP làm trong trường hợp các biến không được khai báo là có lỗi ở mức rất thấp E_NOTICE, một lỗi thậm chí không được báo cáo theo mặc định, nhưng Hướng dẫn khuyên nên cho phép trong quá trình phát triển.

Các cách giải quyết vấn đề:

  1. Khuyến nghị: Khai báo các biến của bạn, ví dụ như khi bạn cố nối thêm một chuỗi vào một biến không xác định. Hoặc sử dụng isset()/ !empty() để kiểm tra nếu chúng được khai báo trước khi tham chiếu chúng, như trong:

    //Initializing variable
    $value = ""; //Initialization value; Examples
                 //"" When you want to append stuff later
                 //0  When you want to add numbers later
    //isset()
    $value = isset($_POST['value']) ? $_POST['value'] : '';
    //empty()
    $value = !empty($_POST['value']) ? $_POST['value'] : '';
    

    Điều này đã trở nên gọn gàng hơn nhiều so với PHP 7.0, bây giờ bạn có thể sử dụng toán tử hợp nhất null :

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
    
  2. Đặt trình xử lý lỗi tùy chỉnh cho E_NOTICE và chuyển hướng các tin nhắn ra khỏi đầu ra tiêu chuẩn (có thể đến tệp nhật ký):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
  3. Vô hiệu hóa E_NOTICE khỏi báo cáo. Một cách nhanh chóng để loại trừ chỉ E_NOTICElà:

    error_reporting( error_reporting() & ~E_NOTICE )
  4. Loại bỏ lỗi với toán tử @ .

Lưu ý: Chúng tôi khuyên bạn nên thực hiện chỉ điểm 1.

Lưu ý: Chỉ mục không xác định / Không xác định bù

Thông báo này xuất hiện khi bạn (hoặc PHP) cố gắng truy cập vào một chỉ mục không xác định của một mảng.

Các cách giải quyết vấn đề:

  1. Kiểm tra nếu chỉ mục tồn tại trước khi bạn truy cập nó. Đối với điều này, bạn có thể sử dụng isset()hoặc array_key_exists():

    //isset()
    $value = isset($array['my_index']) ? $array['my_index'] : '';
    //array_key_exists()
    $value = array_key_exists('my_index', $array) ? $array['my_index'] : '';
    
  2. Cấu trúc ngôn ngữ list()có thể tạo ra điều này khi nó cố gắng truy cập vào một chỉ mục mảng không tồn tại:

    list($a, $b) = array(0 => 'a');
    //or
    list($one, $two) = explode(',', 'test string');
    

Hai biến được sử dụng để truy cập hai phần tử mảng, tuy nhiên chỉ có một phần tử mảng, chỉ mục 0, vì vậy điều này sẽ tạo ra:

Lưu ý: Không xác định bù: 1

$_POST/ $_GET/ $_SESSIONbiến

Các thông báo ở trên xuất hiện thường xuyên khi làm việc với $_POST, $_GEThoặc $_SESSION. Cho $_POST$_GETbạn chỉ cần kiểm tra xem chỉ mục có tồn tại hay không trước khi bạn sử dụng chúng. Đối với $_SESSIONbạn phải chắc chắn rằng bạn đã bắt đầu phiên session_start()và chỉ mục cũng tồn tại.

Cũng lưu ý rằng cả 3 biến là superglobals và là chữ hoa.

Liên quan:


7
@ dieelpower44 Một vài suy nghĩ: "Toán tử im lặng" ( @) có một số vấn đề về hiệu suất. Ngoài ra, vì nó loại bỏ tất cả các lỗi trong một phạm vi cụ thể, sử dụng nó mà không cần quan tâm có thể che giấu các tin nhắn bạn muốn bạn nhìn thấy.
IMSoP

6
Ẩn các vấn đề KHÔNG phải là cách để giải quyết vấn đề. Các mục số 2 ... # 4 chỉ có thể được sử dụng trên các máy chủ sản xuất, không nói chung.
Salman A

1
Có thể tắt thông báo nội tuyến (không phải trong trình xử lý) khi cũng sử dụng trình xử lý lỗi tùy chỉnh? $var = @$_GET['nonexisting'];vẫn gây ra thông báo ..
Alph.Dev

18
Tại sao nên sử dụng 1. $value = isset($_POST['value']) ? $_POST['value'] : '';thay vì sử dụng 4. $value = @$_POST['value'];?
forsvunnet

@twistedpixel 4 cách đó là độc lập, đó không phải là hướng dẫn 4 bước. Vì vậy, nếu bạn đã chọn sử dụng cách 4, điều đó có nghĩa là bạn chưa thực hiện 3 cách đầu tiên, vì vậy bạn chưa khắc phục được bất kỳ lỗi nào.
Aycan Yaşıt

141

Thử những thứ này xem

Q1: thông báo này có nghĩa là $ varname không được xác định ở phạm vi hiện tại của tập lệnh.

Câu 2: Sử dụng các điều kiện hiện tại (), trống () trước khi sử dụng bất kỳ biến đáng ngờ nào hoạt động tốt.

// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? '';

// pre-7 PHP versions
$user_name = '';
if (!empty($_SESSION['user_name'])) {
     $user_name = $_SESSION['user_name'];
}

Hoặc, như một giải pháp nhanh chóng và bẩn thỉu:

// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);

Lưu ý về các phiên:


Nếu sử dụng E_NOTICEtừ php.initệp cấu hình, hãy thực hiệnerror_reporting = (E_ALL & ~E_NOTICE)
ahmd0


Từ câu trả lời ở trên, tôi đã thử ngay lập tức, Array_key_exists nhưng chúng không hoạt động. Tôi đã thử câu trả lời của bạn, .empty (), và nó hoạt động. Cảm ơn rât nhiều!
ewef

63

Toán tử hiển thị lỗi@

Đối với các thông báo không mong muốn và dư thừa, người ta có thể sử dụng @toán tử chuyên dụng để » ẩn « các thông báo biến / chỉ mục không xác định.

$var = @($_GET["optional_param"]);
  • Điều này thường được khuyến khích. Những người mới đến có xu hướng lạm dụng nó.
  • Nó rất không phù hợp với mã nằm sâu trong logic ứng dụng (bỏ qua các biến không được khai báo ở nơi bạn không nên), ví dụ như đối với các tham số hàm hoặc trong các vòng lặp.
  • Có một xu hướng tăng so với isset?:hoặc ??siêu supression tuy nhiên. Thông báo vẫn có thể được đăng nhập. Và người ta có thể hồi sinh @thông báo -hidden với:set_error_handler("var_dump");
    • Ngoài ra, bạn không nên thường xuyên sử dụng / đề nghị if (isset($_POST["shubmit"]))trong mã ban đầu của mình.
    • Những người mới đến sẽ không phát hiện ra những lỗi chính tả như vậy. Nó chỉ tước đi các Thông báo PHP cho những trường hợp đó. Thêm @hoặc issetchỉ sau khi xác minh chức năng.
    • Khắc phục nguyên nhân trước. Không phải thông báo.

  • @chủ yếu được chấp nhận cho $_GET/ $_POSTtham số đầu vào, đặc biệt nếu chúng là tùy chọn .

Và vì điều này bao gồm phần lớn các câu hỏi như vậy, chúng ta hãy mở rộng về các nguyên nhân phổ biến nhất:

$_GET/ $_POST/ $_REQUESTđầu vào không xác định

  • Điều đầu tiên bạn làm khi gặp chỉ số / offset không xác định, là kiểm tra lỗi chính tả:
    $count = $_GET["whatnow?"];

    • Đây có phải là một tên khóa dự kiến ​​và hiện diện trên mỗi yêu cầu trang?
    • Tên biến chỉ thị mảng là phân biệt chữ hoa chữ thường trong PHP.
  • Thứ hai, nếu thông báo không có nguyên nhân rõ ràng, hãy sử dụng var_dumphoặc print_rđể xác minh tất cả các mảng đầu vào cho nội dung hiện tại của chúng:

    var_dump($_GET);
    var_dump($_POST);
    //print_r($_REQUEST);
    

    Cả hai sẽ tiết lộ nếu tập lệnh của bạn được gọi với quyền hoặc bất kỳ tham số nào cả.

  • Thay thế hoặc sử dụng thêm devtools trình duyệtF12 của bạn ( ) và kiểm tra tab mạng để biết các yêu cầu và tham số:

    công cụ phát triển trình duyệt / tab mạng

    Các tham số POST và đầu vào GET sẽ được hiển thị riêng.

  • Đối với $_GETcác tham số, bạn cũng có thể nhìn trộm QUERY_STRINGvào

    print_r($_SERVER);

    PHP có một số quy tắc để kết hợp các tên tham số không chuẩn vào các siêu lớp. Apache cũng có thể viết lại. Bạn cũng có thể xem $_COOKIEScác tiêu đề yêu cầu HTTP thô và được cung cấp theo cách đó.

  • Rõ ràng hơn là nhìn vào thanh địa chỉ trình duyệt của bạn để biết các tham số GET :

    http://example.org/script.php?id=5&sort=desc

    Các name=valuecặp sau ?dấu chấm hỏi là tham số truy vấn (GET) của bạn. Do đó, URL này chỉ có thể mang lại $_GET["id"]$_GET["sort"].

  • Cuối cùng kiểm tra <form><input> khai báo của bạn , nếu bạn mong đợi một tham số nhưng không nhận được.

    • Đảm bảo mỗi đầu vào cần thiết có một <input name=FOO>
    • Các thuộc tính id=hoặc title=không đủ.
    • Một method=POSThình thức nên dân cư $_POST.
    • Trong khi đó một method=GET(hoặc bỏ nó đi) sẽ mang lại $_GETcác biến.
    • Cũng có thể một biểu mẫu cung cấp action=script.php?get=paramqua $ _GET và các method=POSTtrường còn lại trong $ _POST cùng với.
    • Với các cấu hình PHP hiện đại (≥ 5.6), việc sử dụng lại trở nên khả thi (không phải là mốt) $_REQUEST['vars'], điều này làm cho các thông số GET và POST trở nên khả thi .
  • Nếu bạn đang sử dụng mod_rewrite, thì bạn nên kiểm tra cả hai access.logcũng như cho phép RewriteLogtìm ra các tham số vắng mặt.

$_FILES

  • Kiểm tra độ tỉnh táo tương tự áp dụng cho tải lên tập tin và $_FILES["formname"].
  • Hơn nữa kiểm tra enctype=multipart/form-data
  • Cũng như method=POSTtrong <form>tuyên bố của bạn .
  • Xem thêm: Lỗi chỉ mục không xác định PHP $ _FILES?

$_COOKIE

  • Các $_COOKIEmảng không bao giờ được dân cư ngay sau khi setcookie(), nhưng chỉ trên bất kỳ yêu cầu của followup HTTP.
  • Ngoài ra, thời gian hiệu lực của chúng hết hạn, chúng có thể bị ràng buộc với tên miền phụ hoặc đường dẫn riêng lẻ và người dùng và trình duyệt chỉ có thể từ chối hoặc xóa chúng.

2
Nếu bạn tò mò tác động hiệu suất là gì, bài viết này tóm tắt nó tốt, derickrethans.nl/iêu .
Gajus

@GajusKuizinas Đã có một vài thay đổi kể từ năm 2009, đặc biệt là php.net/ChangeLog-5.php#5.4.0 thay đổi kết quả một cách quyết liệt (xem "Toán tử Zend, hiệu suất" và "(im lặng) toán tử").
mario

Cảm ơn @mario, thú vị. Bây giờ, nếu ai đó đủ tốt để đánh giá hai ... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs Theo thử nghiệm này, dường như giống hệt nhau (chú ý rằng thay đổi tỷ lệ).
Gajus

47

Nói chung là do "lập trình xấu", và khả năng xảy ra lỗi ngay bây giờ hoặc sau này.

  1. Nếu đó là một lỗi, trước tiên hãy gán một biến thích hợp cho biến: $ varname = 0;
  2. Nếu đôi khi nó thực sự chỉ được xác định, hãy kiểm tra nó : if (isset($varname)), trước khi sử dụng nó
  3. Nếu đó là vì bạn đánh vần sai, chỉ cần sửa nó
  4. Thậm chí có thể chuyển các cảnh báo trong cài đặt PHP của bạn

5
Xin đừng tắt cảnh báo. Trong các ngôn ngữ chặt chẽ hơn, chúng thường có nghĩa là "có thể có lỗi, tốt hơn là bạn nên kiểm tra dòng này hai lần" - trong một ngôn ngữ được cho phép như PHP, chúng thường có nghĩa là "mã này là rác rưởi và có thể bị lỗi, tôi sẽ cố gắng thực hiện một số ý nghĩa của nó nhưng tốt hơn bạn nên sửa lỗi này càng sớm càng tốt ".

5
Mặc dù tôi đồng ý với ba điểm đầu tiên, # 4 đơn giản là sai. Che giấu một vấn đề sẽ không làm cho nó biến mất, và nó thậm chí có thể gây ra nhiều vấn đề hơn trên đường.
Valentin Flachsel

1
@ Hoàn toàn đúng, nhưng trong một số trường hợp (Kịch bản mua, không có kiến ​​thức kỹ thuật, cần chạy vào ngày mai ...) đó là giải pháp băng keo - thực sự tồi tệ, luôn cần nhấn mạnh, nhưng là một lựa chọn
Pekka

Băng keo là tốt ... đôi khi. Các cảnh báo trong lịch sử đã được đưa ra trong các cài đặt PHP tiêu chuẩn, nhưng các cài đặt defult đã trở nên nghiêm ngặt hơn. Quá tệ, nhiều người quay lại các cài đặt cũ, để không làm phiền khách hàng.
Erik

41

Điều đó có nghĩa là bạn đang kiểm tra, đánh giá hoặc in một biến mà bạn chưa gán bất cứ thứ gì. Nó có nghĩa là bạn có một lỗi đánh máy, hoặc bạn cần kiểm tra xem biến đó đã được khởi tạo thành thứ gì đó trước tiên. Kiểm tra các đường dẫn logic của bạn, nó có thể được đặt trong một đường dẫn nhưng không phải trong một đường dẫn khác.


34

Tôi không muốn tắt thông báo vì nó hữu ích, nhưng muốn tránh gõ quá nhiều.

Giải pháp của tôi là chức năng này:

function ifexists($varname)
{
  return(isset($$varname)?$varname:null);
}

Vì vậy, nếu tôi muốn tham chiếu đến $ name và echo nếu tồn tại, tôi chỉ cần viết:

<?=ifexists('name')?>

Đối với các phần tử mảng:

function ifexistsidx($var,$index)
{
  return(isset($var[$index])?$var[$index]:null);
}

Trong trang nếu tôi muốn tham khảo $ _REQUEST ['name']:

<?=ifexistsidx($_REQUEST,'name')?>

2
Hàm ifexists () của bạn không hoạt động với tôi trong PHP 5.3. Các biến của trình gọi không có sẵn trong phạm vi cục bộ của hàm (xem Phạm vi biến ), trừ khi chúng là Superglobals hoặc bạn sử dụng $ GLOBALS , vì vậy $foo = "BABAR"; ifexists('foo');nói chung sẽ trả về null. (Chữ nghiêng là chương php.net.)
skierpage

bây giờ bạn sẽ nhận được "xin chào từ" ... vấn đề là gì? chỉ cần kiểm tra giá trịif( !empty($user) and !empty($location) ) echo "hello $user ..."
gcb

27

Cách tốt nhất để nhận chuỗi đầu vào là:

$value = filter_input(INPUT_POST, 'value');

Lớp lót này gần như tương đương với:

if (!isset($_POST['value'])) {
    $value = null;
} elseif (is_array($_POST['value'])) {
    $value = false;
} else {
    $value = $_POST['value'];
}

Nếu bạn hoàn toàn muốn giá trị chuỗi , giống như:

$value = (string)filter_input(INPUT_POST, 'value');

25

Đó là vì biến '$ user_location' không được xác định. Nếu bạn đang sử dụng bất kỳ vòng lặp if nào bên trong mà bạn đang khai báo biến '$ user_location' thì bạn cũng phải có một vòng lặp khác và định nghĩa tương tự. Ví dụ:

$a=10;
if($a==5) { $user_location='Paris';} else { }
echo $user_location;

Đoạn mã trên sẽ tạo ra lỗi vì vòng lặp if không được thỏa mãn và trong vòng lặp khác '$ user_location' không được xác định. Tuy nhiên, PHP được yêu cầu lặp lại biến. Vì vậy, để sửa đổi mã, bạn phải làm như sau:

$a=10;
if($a==5) { $user_location='Paris';} else { $user_location='SOMETHING OR BLANK'; }
echo $user_location;

25

Trả lời "" Tại sao chúng đột nhiên xuất hiện? Tôi đã từng sử dụng kịch bản này trong nhiều năm và tôi chưa bao giờ gặp vấn đề gì. "

Điều rất phổ biến đối với hầu hết các trang web hoạt động theo báo cáo lỗi "mặc định" là "Hiển thị tất cả các lỗi, nhưng không phải là 'thông báo' và 'không dùng nữa'". Điều này sẽ được đặt trong php.ini và áp dụng cho tất cả các trang web trên máy chủ. Điều này có nghĩa là những "thông báo" được sử dụng trong các ví dụ sẽ bị loại bỏ (ẩn) trong khi các lỗi khác, được coi là nghiêm trọng hơn, sẽ được hiển thị / ghi lại.

Cài đặt quan trọng khác là các lỗi có thể bị ẩn (nghĩa là display_errorsđược đặt thành "tắt" hoặc "syslog").

Điều sẽ xảy ra trong trường hợp này là hoặc error_reportingđã được thay đổi thành hiển thị các thông báo (theo ví dụ) và / hoặc các cài đặt đã được thay đổi display_errorstrên màn hình (trái ngược với việc loại bỏ chúng / ghi nhật ký chúng).

Tại sao họ đã thay đổi?

Câu trả lời rõ ràng / đơn giản nhất là ai đó đã điều chỉnh một trong hai cài đặt này trong php.ini hoặc phiên bản nâng cấp của PHP hiện đang sử dụng một php.ini khác trước đó. Đó là nơi đầu tiên để tìm.

Tuy nhiên, cũng có thể ghi đè các cài đặt này trong

  • .htconf (cấu hình máy chủ web, bao gồm vhost và cấu hình phụ) *
  • .htaccess
  • trong chính mã php

và bất kỳ trong số này cũng có thể đã được thay đổi.

Ngoài ra còn có sự phức tạp thêm rằng cấu hình máy chủ web có thể bật / tắt các lệnh .htaccess, vì vậy nếu bạn có các lệnh trong .htaccess đột nhiên bắt đầu / ngừng hoạt động thì bạn cần kiểm tra xem.

(.htconf / .htaccess cho rằng bạn đang chạy dưới dạng apache. Nếu chạy dòng lệnh này sẽ không áp dụng; nếu chạy IIS hoặc máy chủ web khác thì bạn sẽ cần kiểm tra các cấu hình đó cho phù hợp)

Tóm lược

  • Kiểm tra error_reportingdisplay_errorschỉ thị php trong php.ini không thay đổi hoặc bạn không sử dụng php.ini khác trước đó.
  • Kiểm tra error_reportingdisplay_errorschỉ thị php trong .htconf (hoặc vhosts, v.v.) không thay đổi
  • Kiểm tra error_reportingdisplay_errorschỉ thị php trong .htaccess không thay đổi
  • Nếu bạn có lệnh trong .htaccess, hãy kiểm tra xem chúng có còn được cho phép trong tệp .htconf không
  • Cuối cùng kiểm tra mã của bạn; có thể là một thư viện không liên quan; để xem nếu error_reportingdisplay_errorschỉ thị php đã được đặt ở đó.

20

cách khắc phục nhanh là gán biến của bạn thành null ở đầu mã của bạn

$user_location = null;

16

Tôi đã sử dụng để nguyền rủa lỗi này, nhưng nó có thể hữu ích để nhắc nhở bạn thoát khỏi đầu vào của người dùng.

Chẳng hạn, nếu bạn nghĩ đây là mã thông minh, tốc ký:

// Echo whatever the hell this is
<?=$_POST['something']?>

...Nghĩ lại! Một giải pháp tốt hơn là:

// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>

(Tôi sử dụng html()chức năng tùy chỉnh để thoát ký tự, số dặm của bạn có thể thay đổi)


15

Trong PHP 7.0, giờ đây có thể sử dụng toán tử kết hợp Null:

echo "My index value is: " . ($my_array["my_index"] ?? '');

Tương đương với:

echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');

Hướng dẫn sử dụng PHP PHP 7.0


Điều này cũng hoạt động tốt trong nếu báo cáo. if (is_array($my_array['idontexist'] ?? '')) { dosomething(); }
một lập trình viên

Mã của bạn thực sự là một lỗi bỏ qua tốt đẹp: ?? - chỉ kiểm tra isset(), nếu bạn vượt qua is_array()- đó là một boolean, hành vi không mong muốn sẽ theo sau.
elpiel

14

Tôi sử dụng hàm hữu ích exst () tự động khai báo các biến.

Mã của bạn sẽ là -

$greeting = "Hello, ".exst($user_name, 'Visitor')." from ".exst($user_location);


/** 
 * Function exst() - Checks if the variable has been set 
 * (copy/paste it in any place of your code)
 * 
 * If the variable is set and not empty returns the variable (no transformation)
 * If the variable is not set or empty, returns the $default value
 *
 * @param  mixed $var
 * @param  mixed $default
 * 
 * @return mixed 
 */

function exst( & $var, $default = "")
{
    $t = "";
    if ( !isset($var)  || !$var ) {
        if (isset($default) && $default != "") $t = $default;
    }
    else  {  
        $t = $var;
    }
    if (is_string($t)) $t = trim($t);
    return $t;
}

14

Trong một ngôn ngữ rất đơn giản .
Lỗi là bạn đang sử dụng một biến $user_locationkhông được xác định trước đó và nó không có bất kỳ giá trị nào. Vì vậy, tôi khuyên bạn nên khai báo biến này trước khi sử dụng , Ví dụ:


$user_location = '';
Hoặc là
$user_location = 'Los Angles';
Đây là một lỗi rất phổ biến mà bạn có thể gặp phải. Vì vậy, đừng lo lắng chỉ cần khai báo biến và Thưởng thức Mã hóa .


8

Tại sao không giữ mọi thứ đơn giản?

<?php
error_reporting(E_ALL); // making sure all notices are on

function idxVal(&$var, $default = null) {
         return empty($var) ? $var = $default : $var;
  }

echo idxVal($arr['test']);         // returns null without any notice
echo idxVal($arr['hey ho'], 'yo'); // returns yo and assigns it to array index, nice

?>

8

TẠI SAO CHUYỆN NÀY ĐANG XẢY RA?

Theo thời gian, PHP đã trở thành một ngôn ngữ tập trung vào bảo mật hơn. Các cài đặt được sử dụng để tắt theo mặc định giờ được bật theo mặc định. Một ví dụ hoàn hảo về điều này là E_STRICT, được bật theo mặc định kể từ phiên bản PHP 5.4.0 .

Hơn nữa, theo tài liệu PHP, theo mặc định, E_NOTICEbị vô hiệu hóa trong php.ini. Tài liệu PHP khuyên bạn nên bật nó cho mục đích gỡ lỗi . Tuy nhiên, khi tôi tải xuống PHP từ kho lưu trữ Ubuntu và từ stack stack Windows của BitNami, tôi thấy một thứ khác.

; Common Values:
;   E_ALL (Show all errors, warnings and notices including coding standards.)
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

Lưu ý rằng error_reportingthực sự được đặt thành giá trị sản xuất theo mặc định, không phải là giá trị "mặc định" theo mặc định. Điều này hơi khó hiểu và không được ghi lại bên ngoài php.ini, vì vậy tôi chưa xác thực điều này trên các bản phân phối khác.

Tuy nhiên, để trả lời câu hỏi của bạn, lỗi này bật lên khi nó không bật lên trước vì:

  1. Bạn đã cài đặt PHP và các cài đặt mặc định mới có phần tài liệu kém nhưng không loại trừ E_NOTICE.

  2. E_NOTICEcác cảnh báo như các biến không xác định và các chỉ mục không xác định thực sự giúp làm cho mã của bạn sạch hơn và an toàn hơn. Tôi có thể nói với bạn rằng, nhiều năm trước, việc E_NOTICEkích hoạt đã buộc tôi phải khai báo các biến của mình. Nó làm cho việc học C trở nên dễ dàng hơn rất nhiều, việc không khai báo các biến lớn hơn nhiều phiền toái.

TÔI CÓ THỂ LÀM GÌ VỚI NÓ?

  1. Tắt E_NOTICEbằng cách sao chép "Giá trị mặc định" E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDvà thay thế nó bằng giá trị hiện không bị thiếu sau khi đăng nhập bằng error_reporting =. Khởi động lại Apache hoặc PHP nếu sử dụng CGI hoặc FPM. Hãy chắc chắn rằng bạn đang chỉnh sửa php.ini "đúng". Cái đúng sẽ là Apache nếu bạn đang chạy PHP với Apache, fpm hoặc php-fpm nếu chạy PHP-FPM, cgi nếu chạy PHP-CGI, v.v. Đây không phải là phương pháp được đề xuất, nhưng nếu bạn có mã kế thừa thì sẽ cực kỳ khó chỉnh sửa, đó có thể là lựa chọn tốt nhất của bạn.

  2. Tắt E_NOTICEcấp độ tập tin hoặc thư mục. Điều này có thể tốt hơn nếu bạn có một số mã kế thừa nhưng muốn làm mọi thứ theo cách "đúng" theo cách khác. Để làm điều này, bạn nên tham khảo Apache2, Nginx hoặc bất cứ máy chủ nào bạn chọn. Trong Apache, bạn sẽ sử dụng php_valuebên trong <Directory>.

  3. Viết lại mã của bạn để sạch hơn. Nếu bạn cần làm điều này trong khi chuyển sang môi trường sản xuất hoặc không muốn ai đó thấy lỗi của mình, hãy đảm bảo rằng bạn đang vô hiệu hóa bất kỳ lỗi hiển thị nào và chỉ ghi nhật ký lỗi của bạn (xem display_errorslog_errorstrong php.ini và cài đặt máy chủ của bạn) .

Để mở rộng trên tùy chọn 3: Đây là lý tưởng. Nếu bạn có thể đi tuyến đường này, bạn nên. Nếu ban đầu bạn không đi tuyến đường này, hãy xem xét việc di chuyển tuyến đường này cuối cùng bằng cách kiểm tra mã của bạn trong môi trường phát triển. Trong khi bạn đang ở đó, hãy loại bỏ ~E_STRICT~E_DEPRECATEDđể xem những gì có thể đi sai trong tương lai. Bạn sẽ thấy RẤT NHIỀU lỗi lạ, nhưng nó sẽ ngăn bạn gặp bất kỳ vấn đề khó chịu nào khi bạn cần nâng cấp PHP trong tương lai.

Ý NGH MEA LÀ GÌ?

Undefined variable: my_variable_name- Điều này xảy ra khi một biến chưa được xác định trước khi sử dụng. Khi tập lệnh PHP được thực thi, bên trong nó chỉ thừa nhận một giá trị null. Tuy nhiên, trong kịch bản nào bạn sẽ cần kiểm tra một biến trước khi nó được xác định? Cuối cùng, đây là một đối số cho "mã cẩu thả". Là một nhà phát triển, tôi có thể nói với bạn rằng tôi yêu nó khi tôi thấy một dự án nguồn mở nơi các biến được định nghĩa là cao trong phạm vi của chúng khi chúng có thể được xác định. Nó giúp dễ dàng hơn để nói những biến nào sẽ xuất hiện trong tương lai và làm cho việc đọc / tìm hiểu mã dễ dàng hơn.

function foo()
{
    $my_variable_name = '';

    //....

    if ($my_variable_name) {
        // perform some logic
    }
}

Undefined index: my_index- Điều này xảy ra khi bạn cố gắng truy cập một giá trị trong một mảng và nó không tồn tại. Để ngăn chặn lỗi này, thực hiện kiểm tra có điều kiện.

// verbose way - generally better
if (isset($my_array['my_index'])) {
    echo "My index value is: " . $my_array['my_index'];
}

// non-verbose ternary example - I use this sometimes for small rules.
$my_index_val = isset($my_array['my_index'])?$my_array['my_index']:'(undefined)';
echo "My index value is: " . $my_index_val;   

Một tùy chọn khác là khai báo một mảng trống ở đầu hàm của bạn. Không phải lúc nào cũng khả thi.

$my_array = array(
    'my_index' => ''
);

//...

$my_array['my_index'] = 'new string';

(mẹo bổ sung)

  • Khi tôi gặp phải những vấn đề này và các vấn đề khác, tôi đã sử dụng NetBeans IDE (miễn phí) và nó đã cho tôi một loạt các cảnh báo và thông báo. Một số trong số họ cung cấp lời khuyên rất hữu ích. Đây không phải là một yêu cầu và tôi không sử dụng IDE nữa ngoại trừ các dự án lớn. Tôi là một vimngười nhiều hơn những ngày này :).

6

chỉ mục không xác định có nghĩa là trong một mảng bạn yêu cầu cho chỉ mục mảng không có sẵn chẳng hạn

<?php 

$newArray[] = {1,2,3,4,5};
print_r($newArray[5]);

?>

biến không xác định có nghĩa là bạn đã sử dụng hoàn toàn không phải là biến hiện có hoặc không được xác định hoặc khởi tạo bởi tên đó chẳng hạn

<?php print_r($myvar); ?>

offset không xác định có nghĩa là trong mảng bạn đã yêu cầu khóa không tồn tại. Và giải pháp cho việc này là kiểm tra trước khi sử dụng

php> echo array_key_exists(1, $myarray);

4

Về phần này của câu hỏi:

Tại sao họ đột nhiên xuất hiện? Tôi đã từng sử dụng kịch bản này trong nhiều năm và tôi chưa bao giờ gặp vấn đề gì.

Không có câu trả lời chắc chắn nhưng đây là một số giải thích có thể có về lý do tại sao cài đặt có thể 'đột ngột' thay đổi:

  1. Bạn đã nâng cấp PHP lên phiên bản mới hơn, có thể có các giá trị mặc định khác cho error_Vporting, display_errors hoặc các cài đặt có liên quan khác.

  2. Bạn đã xóa hoặc giới thiệu một số mã (có thể là phụ thuộc) để đặt các cài đặt có liên quan trong thời gian chạy bằng cách sử dụng ini_set()hoặc error_reporting()(tìm kiếm các mã này trong mã)

  3. Bạn đã thay đổi cấu hình máy chủ web (giả sử apache ở đây): .htaccesstệp và cấu hình vhost cũng có thể thao tác cài đặt php.

  4. Thông thường các thông báo không được hiển thị / báo cáo (xem hướng dẫn sử dụng PHP ) vì vậy có thể khi thiết lập máy chủ, không thể tải tệp php.ini vì một số lý do (quyền truy cập tệp ??) và bạn đã cài đặt mặc định . Sau đó, 'lỗi' đã được giải quyết (một cách tình cờ) và bây giờ, nó CÓ THỂ tải tệp php.ini chính xác với tập tin error_Vporting để hiển thị các thông báo.


3

Nếu làm việc với các lớp, bạn cần đảm bảo rằng bạn tham chiếu các biến thành viên bằng cách sử dụng $this:

class Person
{
    protected $firstName;
    protected $lastName;

    public function setFullName($first, $last)
    {
        // Correct
        $this->firstName = $first;

        // Incorrect
        $lastName = $last;

        // Incorrect
        $this->$lastName = $last;
    }
}

3

Một lý do khác khiến một thông báo chỉ mục không xác định sẽ bị ném, đó là một cột bị bỏ qua khỏi truy vấn cơ sở dữ liệu.

I E:

$query = "SELECT col1 FROM table WHERE col_x = ?";

Sau đó cố gắng truy cập nhiều cột / hàng bên trong một vòng lặp.

I E:

print_r($row['col1']);
print_r($row['col2']); // undefined index thrown

hoặc trong một whilevòng lặp:

while( $row = fetching_function($query) ) {

    echo $row['col1'];
    echo "<br>";
    echo $row['col2']; // undefined index thrown
    echo "<br>";
    echo $row['col3']; // undefined index thrown

}

Một điều khác cần lưu ý là trên * NIX OS và Mac OS X, mọi thứ đều phân biệt chữ hoa chữ thường.

Tham khảo ý kiến ​​của Q & A theo dõi trên Stack:


3

Sử dụng một ternary là đơn giản, dễ đọc và sạch sẽ:

Pre PHP 7
Gán một biến cho giá trị của một biến khác nếu nó được đặt, khác gánnull(hoặc bất kỳgiá trị mặc định nào bạn cần):

$newVariable = isset($thePotentialData) ? $thePotentialData : null;

PHP 7+
Tương tự ngoại trừ sử dụng Toán tử kết hợp Null . Không còn cần phải gọi isset()vì điều này đã được tích hợp và không cần cung cấp biến để trả về vì nó được giả định là trả về giá trị của biến đang được kiểm tra:

$newVariable = $thePotentialData ?? null;

Cả hai sẽ dừng các Thông báo từ câu hỏi OP và cả hai đều tương đương chính xác với:

if (isset($thePotentialData)) {
    $newVariable = $thePotentialData;
} else {
    $newVariable = null;
}

 
Nếu bạn không yêu cầu thiết lập một biến mới thì bạn có thể trực tiếp sử dụng giá trị trả về của ternary, chẳng hạn như với echo, đối số hàm, v.v .:

Tiếng vọng:

echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';

Chức năng:

$foreName = getForeName(isset($userId) ? $userId : null);

function getForeName($userId)
{
    if ($userId === null) {
        // Etc
    }
}

Ở trên sẽ hoạt động tương tự với các mảng, bao gồm các phiên, v.v., thay thế biến được kiểm tra bằng vd:
$_SESSION['checkMe']
hoặc tuy nhiên nhiều cấp độ sâu bạn cần, ví dụ:
$clients['personal']['address']['postcode']


 

Ức chế:

Có thể loại bỏ các Thông báo PHP bằng @hoặc giảm mức báo cáo lỗi của bạn, nhưng nó không khắc phục được sự cố , nó chỉ đơn giản là dừng nó được báo cáo trong nhật ký lỗi. Điều này có nghĩa là mã của bạn vẫn cố sử dụng một biến không được đặt, điều này có thể có hoặc không có nghĩa là một cái gì đó không hoạt động như dự định - tùy thuộc vào mức độ quan trọng của giá trị bị thiếu.

Bạn thực sự nên kiểm tra vấn đề này và xử lý nó một cách thích hợp, hoặc phục vụ một thông điệp khác hoặc thậm chí chỉ trả về giá trị null cho mọi thứ khác để xác định trạng thái chính xác.

Nếu bạn chỉ quan tâm đến Thông báo không có trong nhật ký lỗi, thì như một tùy chọn, bạn có thể chỉ cần bỏ qua nhật ký lỗi.


1

Một nguyên nhân phổ biến của một biến không tồn tại sau khi biểu mẫu HTML đã được gửi là phần tử biểu mẫu không được chứa trong <form>thẻ:

Ví dụ: Phần tử không có trong <form>

<form action="example.php" method="post">
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>

<select name="choice">
    <option value="choice1">choice 1</option>
    <option value="choice2">choice 2</option>
    <option value="choice3">choice 3</option>
    <option value="choice4">choice 4</option>
</select>

Ví dụ: Phần tử hiện có trong <form>

<form action="example.php" method="post">
    <select name="choice">
        <option value="choice1">choice 1</option>
        <option value="choice2">choice 2</option>
        <option value="choice3">choice 3</option>
        <option value="choice4">choice 4</option>
    </select>
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>

0

Có lẽ bạn đang sử dụng phiên bản PHP cũ cho đến và bây giờ đã nâng cấp PHP, đó là lý do nó hoạt động mà không có bất kỳ lỗi nào cho đến nay từ nhiều năm nay. cho đến khi PHP4 không có lỗi nếu bạn đang sử dụng biến mà không xác định nó nhưng kể từ PHP5 trở đi, nó sẽ ném lỗi cho các mã như được đề cập trong câu hỏi.


0

Khi xử lý các tệp, cần có một mã hóa phù hợp và phương thức POST, điều này sẽ kích hoạt thông báo chỉ mục không xác định nếu không được bao gồm trong biểu mẫu.

Hướng dẫn nêu cú pháp cơ bản sau:

HTML

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

PHP

<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);

print "</pre>";

?>

Tài liệu tham khảo:


0

Tôi đã hỏi một câu hỏi về điều này và tôi đã được giới thiệu bài viết này với thông điệp:

Câu hỏi này đã có câu trả lời ở đây:

Thông báo của hoàng tử: Biến không xác định rõ ràng, Thông báo: Không xác định chỉ số, và Thông báo: Không xác định bù trừ bằng cách sử dụng PHP

Tôi đang chia sẻ câu hỏi và giải pháp của tôi ở đây:

Đây là lỗi:

nhập mô tả hình ảnh ở đây

Dòng 154 là vấn đề. Đây là những gì tôi có trong dòng 154:

153    foreach($cities as $key => $city){
154        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

Tôi nghĩ vấn đề là tôi đang viết nếu điều kiện cho biến $city, đó không phải là khóa mà là giá trị trong $key => $city. Đầu tiên, bạn có thể xác nhận nếu đó là nguyên nhân của cảnh báo? Thứ hai, nếu đó là vấn đề, tại sao tôi không thể viết một điều kiện dựa trên giá trị? Có phải là với chìa khóa mà tôi cần phải viết điều kiện?

CẬP NHẬT 1: Vấn đề là khi thực thi $citiesCounterArray[$key], đôi khi khóa $keytương ứng với một khóa không tồn tại trong $citiesCounterArraymảng, nhưng đó không phải lúc nào cũng dựa trên dữ liệu của vòng lặp của tôi. Những gì tôi cần là đặt một điều kiện để nếu $keytồn tại trong mảng, sau đó chạy mã, nếu không, bỏ qua nó.

CẬP NHẬT 2: Đây là cách tôi sửa nó bằng cách sử dụng array_key_exists():

foreach($cities as $key => $city){
    if(array_key_exists($key, $citiesCounterArray)){
        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

0

Những lỗi này xảy ra bất cứ khi nào chúng ta đang sử dụng một biến không được đặt.

Cách tốt nhất để xử lý những vấn đề này là thiết lập báo cáo lỗi trong khi phát triển.

Để đặt báo cáo lỗi trên:

ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');
error_reporting(E_ALL);

Trên các máy chủ sản xuất, báo cáo lỗi bị tắt, do đó, chúng tôi không nhận được các lỗi này.

Tuy nhiên, trên máy chủ phát triển, chúng tôi có thể đặt báo cáo lỗi.

Để thoát khỏi lỗi này, chúng ta xem ví dụ sau:

if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

Chúng ta có thể khởi tạo các biến NULLtrước khi gán giá trị của chúng hoặc sử dụng chúng.

Vì vậy, chúng ta có thể sửa đổi mã là:

$test = NULL;
if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

Điều này sẽ không làm phiền bất kỳ logic chương trình nào và sẽ không tạo Thông báo ngay cả khi $testkhông có giá trị.

Vì vậy, về cơ bản, luôn luôn tốt hơn để đặt báo cáo lỗi BẬT để phát triển.

Và sửa tất cả các lỗi.

Và trên sản xuất, báo cáo lỗi nên được đặt thành tắt.


-1

Những thông báo đó là do bạn không có biến được sử dụng definedmy_indexkhóa không có trong $my_arraybiến.

Những thông báo đó được kích hoạt mỗi lần, bởi vì thông báo của bạn codekhông chính xác, nhưng có lẽ bạn không có báo cáo về thông báo.

Giải quyết các lỗi:

$my_variable_name = "Variable name"; // defining variable
echo "My variable value is: " . $my_variable_name;

if(isset($my_array["my_index"])){
    echo "My index value is: " . $my_array["my_index"]; // check if my_index is set 
}

Một cách khác để có được điều này:

ini_set("error_reporting", false)

-2

Trong PHP bạn cần nắm tay để xác định biến sau đó bạn có thể sử dụng nó.
Chúng ta có thể kiểm tra biến được định nghĩa hay không theo cách rất hiệu quả!.

//If you only want to check variable has value and value has true and false value.
//But variable must be defined first.

if($my_variable_name){

}

//If you want to check variable is define or undefine
//Isset() does not check that variable has true or false value
//But it check null value of variable
if(isset($my_variable_name)){

}

Giải thích đơn giản

//It will work with :- true,false,NULL
$defineVarialbe = false;
if($defineVarialbe){
    echo "true";
}else{
    echo "false";
}

//It will check variable is define or not and variable has null value.
if(isset($unDefineVarialbe)){
    echo "true";
}else{
    echo "false";
}
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.