This error message is meant to help a PHP programmer to spot a typo or a mistake when accessing a variable (or an array element) that doesn't exist. So a good programmer:
此错误消息旨在帮助PHP程序员在访问不存在的变量(或数组元素)时发现拼写错误或错误。所以,一个好的程序员:
- Makes sure that every variable or array key is already defined by the time it's going to be used. In case a variable is needed to be used inside a function, it must be passed to that function as a parameter.
- Pays attention to this error and proceeds to fix it, just like with any other error. It may indicate a spelling error or that some procedure didn't return the data it should.
- Only on a rare occasion, when things are not under the programmer's control, a code can be added to circumvent this error. But by no means it should be a mindless habit.
Notice / Warning: Undefined variable
Although PHP does not require a variable declaration, it does recommend it in order to avoid some security vulnerabilities or bugs where one would forget to give a value to a variable that will be used later in the script. What PHP does in the case of undeclared variables is issue an error of E_WARNING
level.
虽然PHP不需要变量声明,但它确实建议使用它,以避免一些安全漏洞或错误,其中一个会忘记为稍后将在脚本中使用的变量赋值。PHP在未声明变量的情况下所做的是发出一个E_Error级别的错误。
This warning helps a programmer to spot a misspelled variable name or a similar kind of mistake (like a variable was assigned a value inside of a condition that evaluated to false). Besides, there are other possible issues with uninitialized variables. As it's stated in the PHP manual,
此警告有助于程序员发现拼写错误的变量名或类似的错误(例如,在计算结果为FALSE的条件中为变量赋值)。此外,对于未初始化的变量,还有其他可能的问题。正如PHP手册中所述,
Relying on the default value of an uninitialized variable is problematic in the case of including one file into another which uses the same variable name.
Which means that a variable may get a value from the included file, and this value will be used instead of null
that one expects accessing a non-initialized variable, which may lead to unpredictable results. To avoid that, all variables in a PHP file are best to be initialized before use.
这意味着变量可能会从包含的文件中获得一个值,并且将使用该值而不是访问未初始化的变量所期望的NULL,这可能会导致不可预测的结果。为了避免这种情况,最好在使用前对PHP文件中的所有变量进行初始化。
Ways to deal with the issue:
处理这个问题的方法:
Recommended: Declare every variable before use. This way you will see this error only when you actually make a mistake, trying to use a non-existent variable - the very reason this error message exists.
//Initializing a variable
$value = ""; //Initialization value; 0 for int, [] for array, etc.
echo $value; // no error
echo $vaule; // an error pinpoints a misspelled variable name
a special case when a variable is defined but is not visible in a function. Functions in PHP have own variable scope, and if you need to use in a function a variable from outside, its value must be passed as a function's parameter:
当变量已定义但在函数中不可见时的特殊情况。PHP中的函数有自己的变量作用域,如果需要在函数中使用外部变量,它的值必须作为函数的参数传递:
function test($param) {
return $param + 1;
}
$var = 0;
echo test($var); // now $var's value is accessible inside through $param
Suppress the error with null coalescing operator. But remember that this way PHP won't be able to notify you about using wrong variable name.
// Null coalescing operator
echo $value ?? '';
For the ancient PHP versions (< 7.0) isset() with ternary can be used
echo isset($value) ? $value : '';
Be aware though, that it's still essentially an error suppression, though for just one particular error. So it may prevent PHP from helping you by marking an unitialized variable.
Suppress the error with the @ operator. Left here for the historical reasons but seriously, it just shouldn't happen.
Note: It's strongly recommended to implement just point 1.
注意:强烈建议只实现第1点。
Notice: Undefined index / Undefined offset / Warning: Undefined array key
This notice/warning appears when you (or PHP) try to access an undefined index of an array.
当您(或PHP)尝试访问数组的未定义索引时,会出现此通知/警告。
Internal arrays
When dealing with internal arrays, that are defined in your code, the attitude should be exactly the same: just initialize all keys before use. this way this error will do its intended job: notify a programmer about a mistake in their code. So the approach is the same:
在处理代码中定义的内部数组时,态度应该完全相同:只需在使用前初始化所有键。这样,该错误将完成其预期的任务:通知程序员他们的代码中存在错误。因此,方法是相同的:
Recommended: Declare your array elements:
建议:声明数组元素:
//Initializing a variable
$array['value'] = ""; //Initialization value; 0 for int, [] for array, etc.
echo $array['value']; // no error
echo $array['vaule']; // an error indicates a misspelled key
A special case is when some function returns either an array or some other value such as null
or false
. Then it has to be tested before trying to access the array elements, such as
一种特殊情况是,当某个函数返回数组或其他值(如NULL或FALSE)时。然后,在尝试访问数组元素之前必须对其进行测试,例如
$row = $stmt->fetch();
if ($row) { // the record was found and can be worked with
echo $row['name'];
}
Outside arrays
With outside arrays (such as $_POST
/ $_GET
/ $_SESSION
or JSON input) the situation is a bit different, because programmer doesn't have the control over such arrays' contents. So checking for some key existence or even assigning a default value for a missing key could be justified.
对于外部数组(如$_POST/$_GET/$_SESSION或JSON输入),情况略有不同,因为程序员无法控制此类数组的内容。因此,检查某个键是否存在,甚至为缺失的键指定一个缺省值可能是合理的。
when a PHP script contains an HTML form, it is natural that on the first load there is no form contents. Therefore such a script should check if a form was submitted
当一个PHP脚本包含一个HTML表单时,在第一次加载时自然没有表单内容。因此,这样的脚本应该检查是否提交了表单
// for POST forms check the request method
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// process the form
}
// for GET forms / links check the important field
if (isset($_GET['search'])) {
// process the form
}
some HTML form elements, such as checkboxes, aren't sent to the server if not checked. In this case it is justified to use a null coalescing operator to assign a default value
如果不选中某些HTML表单元素,例如复选框,则不会将其发送到服务器。在这种情况下,使用空合并运算符分配缺省值是合理的
$agreed = $_POST['terms'] ?? false;
optional QUERY STRING elements or cookies should be treated the same way
应以相同的方式处理可选的查询字符串元素或Cookie
$limit = $_GET['limit'] ?? 20;
$theme = $_COOKIE['theme'] ?? 'light';
But assignments should be done at the very beginning of the script. Validate all input, assign it to local variables, and use them all the way in the code. So every variable you're going to access would deliberately exist.
但是作业应该在剧本的一开始就完成。调用所有输入,将其分配给局部变量,并在代码中一直使用它们。所以你要访问的每个变量都是故意存在的。
Related:
相关:
Try these
试试这些吧
Q1: this notice means $varname is not
defined at current scope of the
script.
Q2: Use of isset(), empty() conditions before using any suspicious variable works well.
// 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'];
}
Or, as a quick and dirty solution:
或者,作为一个快速和肮脏的解决方案:
// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);
Note about sessions:
关于会话的注意事项:
For undesired and redundant notices, one could use the dedicated @
operator to »hide« undefined variable/index messages.
对于不需要的和多余的通知,可以使用专用的@运算符?隐藏?未定义的变量/索引消息。
$var = @($_GET["optional_param"]);
- This is usually discouraged. Newcomers tend to way overuse it.
- It's very inappropriate for code deep within the application logic (ignoring undeclared variables where you shouldn't), e.g. for function parameters, or in loops.
- There's one upside over the
isset?:
or ??
super-supression however. Notices still can get logged. And one may resurrect @
-hidden notices with: set_error_handler("var_dump");
- Additonally you shouldn't habitually use/recommend
if (isset($_POST["shubmit"]))
in your initial code.
- Newcomers won't spot such typos. It just deprives you of PHPs Notices for those very cases. Add
@
or isset
only after verifying functionality.
-
Fix the cause first. Not the notices.
先解决问题。不是通知。
@
is mainly acceptable for $_GET
/$_POST
input parameters, specifically if they're optional.
And since this covers the majority of such questions, let's expand on the most common causes:
由于这涵盖了这类问题的大部分,让我们来扩展一下最常见的原因:
$_GET
/ $_POST
/ $_REQUEST
undefined input
First thing you do when encountering an undefined index/offset, is check for typos:
$count = $_GET["whatnow?"];
遇到未定义的索引/偏移量时,您要做的第一件事是检查打字错误:$count=$_get[“Whatnow?”];
- Is this an expected key name and present on each page request?
- Variable names and array indicies are case-sensitive in PHP.
Secondly, if the notice doesn't have an obvious cause, use var_dump
or print_r
to verify all input arrays for their curent content:
其次,如果通知没有明显的原因,请使用var_ump或print_r验证所有输入数组的当前内容:
var_dump($_GET);
var_dump($_POST);
//print_r($_REQUEST);
Both will reveal if your script was invoked with the right or any parameters at all.
两者都将显示您的脚本是否使用正确的参数或任何参数调用。
Alternativey or additionally use your browser devtools (F12) and inspect the network tab for requests and parameters:
或者,使用浏览器DevTools(F12)并检查网络选项卡中的请求和参数:
POST parameters and GET input will be be shown separately.
POST参数和GET输入将分别显示。
For $_GET
parameters you can also peek at the QUERY_STRING
in
对于$_GET参数,您还可以查看中的Query_STRING
print_r($_SERVER);
PHP has some rules to coalesce non-standard parameter names into the superglobals. Apache might do some rewriting as well.
You can also look at supplied raw $_COOKIES
and other HTTP request headers that way.
PHP有一些规则将非标准参数名合并到超全局变量中。Apache也可以进行一些重写。您还可以通过这种方式查看提供的原始$_COOKIES和其他HTTP请求头。
More obviously look at your browser address bar for GET parameters:
更明显的是,查看您的浏览器地址栏以获取参数:
http://example.org/script.php?id=5&sort=desc
Http://example.org/script.php?id=5&sort=desc
The name=value
pairs after the ?
question mark are your query (GET) parameters. Thus this URL could only possibly yield $_GET["id"]
and $_GET["sort"]
.
?后的名称=值对问号是您的查询(获取)参数。因此,该URL可能只产生$_GET[“id”]和$_GET[“Sort”]。
Finally check your <form>
and <input>
declarations, if you expect a parameter but receive none.
最后,如果您需要一个参数,但没有收到参数,请检查您的
- Ensure each required input has an
<input name=FOO>
- The
id=
or title=
attribute does not suffice.
- A
method=POST
form ought to populate $_POST
.
- Whereas a
method=GET
(or leaving it out) would yield $_GET
variables.
- It's also possible for a form to supply
action=script.php?get=param
via $_GET and the remaining method=POST
fields in $_POST alongside.
- With modern PHP configurations (≥ 5.6) it has become feasible (not fashionable) to use
$_REQUEST['vars']
again, which mashes GET and POST params.
If you are employing mod_rewrite, then you should check both the access.log
as well as enable the RewriteLog
to figure out absent parameters.
如果您使用的是mod_rewrite,那么您应该同时检查acces.log和启用ReWriteLog以找出缺少的参数。
$_FILES
- The same sanity checks apply to file uploads and
$_FILES["formname"]
.
- Moreover check for
enctype=multipart/form-data
- As well as
method=POST
in your <form>
declaration.
- See also: PHP Undefined index error $_FILES?
$_COOKIE
- The
$_COOKIE
array is never populated right after setcookie()
, but only on any followup HTTP request.
- Additionally their validity times out, they could be constraint to subdomains or individual paths, and user and browser can just reject or delete them.
Generally because of "bad programming", and a possibility for mistakes now or later.
通常是因为“糟糕的编程”,以及现在或以后出错的可能性。
- If it's a mistake, make a proper assignment to the variable first: $varname=0;
- If it really is only defined sometimes, test for it:
if (isset($varname))
, before using it
- If it's because you spelled it wrong, just correct that
- Maybe even turn of the warnings in you PHP-settings
It means you are testing, evaluating, or printing a variable that you have not yet assigned anything to. It means you either have a typo, or you need to check that the variable was initialized to something first. Check your logic paths, it may be set in one path but not in another.
这意味着您正在测试、评估或打印一个尚未赋值的变量。这意味着要么您有一个拼写错误,要么您需要先检查变量是否被初始化为某个值。检查您的逻辑路径,它可能设置在一条路径中,但不在另一条路径中。
I didn't want to disable notice because it's helpful, but I wanted to avoid too much typing.
我不想禁用通知,因为它很有帮助,但我想避免输入太多内容。
My solution was this function:
我的解决方案是这个函数:
function ifexists($varname)
{
return(isset($$varname) ? $varname : null);
}
So if I want to reference to $name and echo if exists, I simply write:
因此,如果我想引用$name和ECHO(如果存在),我只需写下:
<?= ifexists('name') ?>
For array elements:
对于数组元素:
function ifexistsidx($var,$index)
{
return(isset($var[$index]) ? $var[$index] : null);
}
In a page if I want to refer to $_REQUEST['name']:
在页面中,如果我想引用$_Request[‘name’]:
<?= ifexistsidx($_REQUEST, 'name') ?>
It’s because the variable '$user_location' is not getting defined. If you are using any if loop inside, which you are declaring the '$user_location' variable, then you must also have an else loop and define the same. For example:
这是因为没有定义变量‘$USER_LOCATION’。如果在内部使用任何if循环,并且声明了‘$USER_LOCATION’变量,则还必须有一个Else循环并定义相同的值。例如:
$a = 10;
if($a == 5) {
$user_location = 'Paris';
}
else {
}
echo $user_location;
The above code will create an error as the if loop is not satisfied and in the else loop '$user_location' was not defined. Still PHP was asked to echo out the variable. So to modify the code you must do the following:
上面的代码将创建一个错误,因为IF循环不满足,并且在Else循环中没有定义‘$USER_LOCATION’。尽管如此,仍要求PHP回显该变量。因此,要修改代码,您必须执行以下操作:
$a = 10;
if($a == 5) {
$user_location='Paris';
}
else {
$user_location='SOMETHING OR BLANK';
}
echo $user_location;
The best way for getting the input string is:
获取输入字符串的最佳方法是:
$value = filter_input(INPUT_POST, 'value');
This one-liner is almost equivalent to:
这一句话几乎等同于:
if (!isset($_POST['value'])) {
$value = null;
} elseif (is_array($_POST['value'])) {
$value = false;
} else {
$value = $_POST['value'];
}
If you absolutely want a string value, just like:
如果您绝对想要一个字符串值,就像:
$value = (string)filter_input(INPUT_POST, 'value');
In reply to ""Why do they appear all of a sudden? I used to use this script for years and I've never had any problem."
回答“为什么它们会突然出现?”我多年来一直在用这个剧本,从来没有遇到过任何问题。
It is very common for most sites to operate under the "default" error reporting of "Show all errors, but not 'notices' and 'deprecated'". This will be set in php.ini and apply to all sites on the server. This means that those "notices" used in the examples will be suppressed (hidden) while other errors, considered more critical, will be shown/recorded.
对于大多数网站来说,在“显示所有错误,但不显示'通知'和'已弃用'”的“默认”错误报告下运行是非常常见的。这将在php.ini中设置并应用于服务器上的所有站点。这意味着示例中使用的那些“注意”将被抑制(隐藏),而其他被认为更关键的错误将被显示/记录。
The other critical setting is the errors can be hidden (i.e. display_errors
set to "off" or "syslog").
另一个关键设置是可以隐藏错误(即,DISPLAY_ERROR设置为“OFF”或“SYSLOG”)。
What will have happened in this case is that either the error_reporting
was changed to also show notices (as per examples) and/or that the settings were changed to display_errors
on screen (as opposed to suppressing them/logging them).
在这种情况下会发生的情况是,ERROR_REPORTING被更改为也显示通知(根据示例)和/或设置被更改为DISPLAY_ERROR on Screen(而不是抑制它们/记录它们)。
Why have they changed?
它们为什么会发生变化?
The obvious/simplest answer is that someone adjusted either of these settings in php.ini, or an upgraded version of PHP is now using a different php.ini from before. That's the first place to look.
最明显/最简单的答案是,有人在php.ini中调整了这些设置,或者PHP的升级版本现在使用的是与以前不同的php.ini。这是第一个要找的地方。
However it is also possible to override these settings in
但是,也可以在中覆盖这些设置
- .htconf (webserver configuration, including vhosts and sub-configurations)*
- .htaccess
- in php code itself
and any of these could also have been changed.
而这些也都有可能被改变。
There is also the added complication that the web server configuration can enable/disable .htaccess directives, so if you have directives in .htaccess that suddenly start/stop working then you need to check for that.
此外,Web服务器配置还可能启用/禁用.htaccess指令,因此,如果.htaccess中的指令突然开始/停止工作,则需要检查是否存在这种情况。
(.htconf / .htaccess assume you're running as apache. If running command line this won't apply; if running IIS or other webserver then you'll need to check those configs accordingly)
(.htconf / .htaccess假设你是以apache的身份运行。如果运行命令行,这将不适用;如果运行IIS或其他Web服务器,则需要相应地检查这些参数)
Summary
摘要
- Check
error_reporting
and display_errors
php directives in php.ini has not changed, or that you're not using a different php.ini from before.
- Check
error_reporting
and display_errors
php directives in .htconf (or vhosts etc) have not changed
- Check
error_reporting
and display_errors
php directives in .htaccess have not changed
- If you have directive in .htaccess, check if they are still permitted in the .htconf file
- Finally check your code; possibly an unrelated library; to see if
error_reporting
and display_errors
php directives have been set there.
The quick fix is to assign your variable to null at the top of your code:
快速解决方法是在代码顶部将变量赋值为NULL:
$user_location = null;
Why is this happening?
Over time, PHP has become a more security-focused language. Settings which used to be turned off by default are now turned on by default. A perfect example of this is E_STRICT
, which became turned on by default as of PHP 5.4.0.
随着时间的推移,PHP已经成为一种更加注重安全的语言。过去默认关闭的设置现在默认打开。这方面的一个很好的例子是E_Struction,从PHP5.4.0开始,它被默认打开。
Furthermore, according to PHP documentation, by default, E_NOTICE
is disabled in file php.ini. PHP documentation recommends turning it on for debugging purposes. However, when I download PHP from the Ubuntu repository–and from BitNami's Windows stack–I see something else.
此外,根据PHP文档,默认情况下,在php.ini文件中禁用E_NOTICE。PHP文档建议出于调试目的启用它。然而,当我从Ubuntu库和BitNami的Windows堆栈下载PHP时,我看到了一些不同的东西。
; 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
Notice that error_reporting
is actually set to the production value by default, not to the "default" value by default. This is somewhat confusing and is not documented outside of php.ini, so I have not validated this on other distributions.
请注意,error_reporting实际上默认设置为生产值,而不是默认设置为“default”值。这有点令人困惑,在php.ini之外没有文档记录,所以我没有在其他发行版上验证过。
To answer your question, however, this error pops up now when it did not pop up before because:
然而,为了回答您的问题,此错误现在弹出,而以前没有弹出,原因是:
You installed PHP and the new default settings are somewhat poorly documented but do not exclude E_NOTICE
.
E_NOTICE
warnings like undefined variables and undefined indexes actually help to make your code cleaner and safer. I can tell you that, years ago, keeping E_NOTICE
enabled forced me to declare my variables. It made it a LOT easier to learn C. In C, not declaring variables is much bigger of a nuisance.
What can I do about it?
Turn off E_NOTICE
by copying the "Default value" E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
and replacing it with what is currently uncommented after the equals sign in error_reporting =
. Restart Apache, or PHP if using CGI or FPM. Make sure you are editing the "right" php.ini file. The correct one will be Apache if you are running PHP with Apache, fpm or php-fpm if running PHP-FPM, cgi if running PHP-CGI, etc. This is not the recommended method, but if you have legacy code that's going to be exceedingly difficult to edit, then it might be your best bet.
Turn off E_NOTICE
on the file or folder level. This might be preferable if you have some legacy code but want to do things the "right" way otherwise. To do this, you should consult Apache 2, Nginx, or whatever your server of choice is. In Apache, you would use php_value
inside of <Directory>
.
Rewrite your code to be cleaner. If you need to do this while moving to a production environment or don't want someone to see your errors, make sure you are disabling any display of errors, and only logging your errors (see display_errors
and log_errors
in php.ini and your server settings).
To expand on option 3: This is the ideal. If you can go this route, you should. If you are not going this route initially, consider moving this route eventually by testing your code in a development environment. While you're at it, get rid of ~E_STRICT
and ~E_DEPRECATED
to see what might go wrong in the future. You're going to see a LOT of unfamiliar errors, but it's going to stop you from having any unpleasant problems when you need to upgrade PHP in the future.
对选项3进行扩展:这是理想的选择。如果你能走这条路,你应该走。如果您最初不打算采用此方法,请考虑最终通过在开发环境中测试代码来实现此方法。在此过程中,删除~E_STRIGN和~E_DEVERATED,看看将来会出什么问题。您将看到许多不熟悉的错误,但这将使您在将来需要升级PHP时不会遇到任何令人不快的问题。
What do the errors mean?
Undefined variable: my_variable_name
- This occurs when a variable has not been defined before use. When the PHP script is executed, it internally just assumes a null value. However, in which scenario would you need to check a variable before it was defined? Ultimately, this is an argument for "sloppy code". As a developer, I can tell you that I love it when I see an open source project where variables are defined as high up in their scopes as they can be defined. It makes it easier to tell what variables are going to pop up in the future and makes it easier to read/learn the code.
未定义变量:MY_VARIABLE_NAME-当变量在使用前尚未定义时,会发生这种情况。当执行PHP脚本时,它只在内部假定为空值。但是,在哪种情况下,您需要在定义变量之前对其进行检查?归根结底,这是支持“草率代码”的理由。作为一名开发人员,我可以告诉您,当我看到一个开放源码项目时,我喜欢它,在这个项目中,变量被定义在它们的作用域的最高位置。这样可以更容易地判断将来会弹出哪些变量,并且更容易阅读/学习代码。
function foo()
{
$my_variable_name = '';
//....
if ($my_variable_name) {
// perform some logic
}
}
Undefined index: my_index
- This occurs when you try to access a value in an array and it does not exist. To prevent this error, perform a conditional check.
未定义的索引:my_index -当您尝试访问数组中的值而该值不存在时,会发生这种情况。若要防止此错误,请执行条件检查。
// 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;
Another option is to declare an empty array at the top of your function. This is not always possible.
另一种选择是在函数顶部声明一个空数组。这并不总是可能的。
$my_array = array(
'my_index' => ''
);
//...
$my_array['my_index'] = 'new string';
(Additional tip)
- When I was encountering these and other issues, I used NetBeanss IDE (free) and it gave me a host of warnings and notices. Some of them offer very helpful tips. This is not a requirement, and I don't use IDEs anymore except for large projects. I'm more of a
vim
person these days :).
I used to curse this error, but it can be helpful to remind you to escape user input.
我过去常常咒骂这个错误,但提醒您避开用户输入会很有帮助。
For instance, if you thought this was clever, shorthand code:
例如,如果您认为这是一种巧妙的速记代码:
// Echo whatever the hell this is
<?=$_POST['something']?>
...Think again! A better solution is:
...再想一想!更好的解决方案是:
// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>
(I use a custom html()
function to escape characters, your mileage may vary)
(我使用一个定制的html()函数来转义字符,您的里程数可能会有所不同)
In PHP 7.0 it's now possible to use the null coalescing operator:
在PHP7.0中,现在可以使用空合并运算符:
echo "My index value is: " . ($my_array["my_index"] ?? '');
Is equals to:
等于:
echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');
PHP manual PHP 7.0
PHP手册PHP 7.0
I use my own useful function, exst(), all time which automatically declares variables.
我一直使用自己的有用函数exst(),该函数自动声明变量。
Your code will be -
你的代码将是-
$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;
}
In a very simple language:
用一种非常简单的语言:
The mistake is you are using a variable $user_location
which is not defined by you earlier, and it doesn't have any value. So I recommend you to please declare this variable before using it. For example:
错误在于您使用的变量$USER_LOCATION不是您之前定义的,并且它没有任何值。因此,我建议您在使用此变量之前先声明它。例如:
$user_location = '';
Or
$user_location = 'Los Angles';
This is a very common error you can face. So don't worry; just declare the variable and enjoy coding.
这是您可能会遇到的一个非常常见的错误。所以不用担心,只需声明变量并享受编码。
Keep things simple:
让事情保持简单:
<?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 the array index. Nice
?>
An undefined index means in an array you requested for an unavailable array index. For example,
未定义的索引表示您为不可用的数组索引请求的数组中。例如,
<?php
$newArray[] = {1, 2, 3, 4, 5};
print_r($newArray[5]);
?>
An undefined variable means you have used completely not an existing variable or which is not defined or initialized by that name. For example,
未定义变量意味着您使用的变量完全不是现有变量,或者没有使用该名称定义或初始化的变量。例如,
<?php print_r($myvar); ?>
An undefined offset means in an array you have asked for a nonexisting key. And the solution for this is to check before use:
未定义的偏移量意味着您在数组中请求了一个不存在的键。解决这个问题的办法是在使用前进行检查:
php> echo array_key_exists(1, $myarray);
Regarding this part of the question:
就问题的这一部分:
Why do they appear all of a sudden? I used to use this script for years and I've never had any problem.
No definite answers but here are a some possible explanations of why settings can 'suddenly' change:
没有确切的答案,但这里有一些可能的解释,解释为什么设置可能会突然改变:
You have upgraded PHP to a newer version which can have other defaults for error_reporting, display_errors or other relevant settings.
You have removed or introduced some code (possibly in a dependency) that sets relevant settings at runtime using ini_set()
or error_reporting()
(search for these in the code)
You changed the webserver configuration (assuming apache here): .htaccess
files and vhost configurations can also manipulate php settings.
Usually notices don't get displayed / reported (see PHP manual)
so it is possible that when setting up the server, the php.ini file could not be loaded for some reason (file permissions??) and you were on the default settings. Later on, the 'bug' has been solved (by accident) and now it CAN load the correct php.ini file with the error_reporting set to show notices.
Using a ternary operator is simple, readable, and clean:
使用三元运算符是简单、可读和干净的:
Pre PHP 7
Assign a variable to the value of another variable if it's set, else assign null
(or whatever default value you need):
如果一个变量被设置,则将其赋值给另一个变量的值,否则赋值为null(或任何你需要的默认值):
$newVariable = isset($thePotentialData) ? $thePotentialData : null;
PHP 7+
The same except using the null coalescing operator. There's no longer a need to call isset()
as this is built in, and no need to provide the variable to return as it's assumed to return the value of the variable being checked:
除了使用空合并运算符之外,其他方法都相同。不再需要调用isset(),因为这是内置的,并且不需要提供要返回的变量,因为假设它返回被检查的变量的值:
$newVariable = $thePotentialData ?? null;
Both will stop the Notices from the OP's question, and both are the exact equivalent of:
两者都将阻止操作员的问题通知,并且两者都完全等同于:
if (isset($thePotentialData)) {
$newVariable = $thePotentialData;
} else {
$newVariable = null;
}
If you don't require setting a new variable then you can directly use the ternary operator's returned value, such as with echo
, function arguments, etc.:
如果您不需要设置新的变量,则可以直接使用三元运算符的返回值,例如使用ECHO、函数参数等:
Echo:
echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';
Function:
$foreName = getForeName(isset($userId) ? $userId : null);
function getForeName($userId)
{
if ($userId === null) {
// Etc
}
}
The above will work just the same with arrays, including sessions, etc., replacing the variable being checked with e.g.:
上述方法对数组(包括会话等)的作用相同,将被检查的变量替换为:
$_SESSION['checkMe']
$_SESSION[‘check Me’]
Or however many levels deep you need, e.g.:
或者您需要多少层深,例如:
$clients['personal']['address']['postcode']
$CLIENTS[‘个人’][‘地址’][‘邮政编码’]
Suppression:
It is possible to suppress the PHP Notices with @
or reduce your error reporting level, but it does not fix the problem. It simply stops it being reported in the error log. This means that your code still tried to use a variable that was not set, which may or may not mean something doesn't work as intended - depending on how crucial the missing value is.
可以使用@来隐藏PHP通知,或者降低错误报告级别,但这并不能解决问题。它只是停止在错误日志中报告它。这意味着您的代码仍然试图使用一个未设置的变量,这可能意味着也可能不意味着某些东西不能按预期工作--这取决于缺少的值有多重要。
You should really be checking for this issue and handling it appropriately, either serving a different message, or even just returning a null value for everything else to identify the precise state.
您真的应该检查这个问题并适当地处理它,要么提供不同的消息,要么只是为其他所有内容返回空值以标识准确的状态。
If you just care about the Notice not being in the error log, then as an option you could simply ignore the error log.
如果您只关心错误日志中没有通知,那么作为一种选择,您可以简单地忽略错误日志。
If working with classes you need to make sure you reference member variables using $this
:
如果使用类,则需要确保使用$This引用成员变量:
class Person
{
protected $firstName;
protected $lastName;
public function setFullName($first, $last)
{
// Correct
$this->firstName = $first;
// Incorrect
$lastName = $last;
// Incorrect
$this->$lastName = $last;
}
}
Another reason why an undefined index notice will be thrown, would be that a column was omitted from a database query.
抛出未定义索引通知的另一个原因是数据库查询中省略了一列。
I.e.:
即:
$query = "SELECT col1 FROM table WHERE col_x = ?";
Then trying to access more columns/rows inside a loop.
然后尝试访问循环内的更多列/行。
I.e.:
即:
print_r($row['col1']);
print_r($row['col2']); // undefined index thrown
or in a while
loop:
或者在While循环中:
while( $row = fetching_function($query) ) {
echo $row['col1'];
echo "<br>";
echo $row['col2']; // undefined index thrown
echo "<br>";
echo $row['col3']; // undefined index thrown
}
Something else that needs to be noted is that on a *NIX OS and Mac OS X, things are case-sensitive.
另外需要注意的是,在*Nix OS和Mac OS X上,大小写都是敏感的。
Consult the followning Q&A's on Stack:
请参考以下关于堆栈的问答:
One common cause of a variable not existing after an HTML form has been submitted is the form element is not contained within a <form>
tag:
在提交了一个HTML表单之后,变量不存在的一个常见原因是
Example: Element not contained within the <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>
Example: Element now contained within the <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>
These errors occur whenever we are using a variable that is not set.
每当我们使用未设置的变量时,就会发生这些错误。
The best way to deal with these is set error reporting on while development.
处理这些问题的最好方法是在开发时设置错误报告。
To set error reporting on:
要设置错误报告,请执行以下操作:
ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');
error_reporting(E_ALL);
On production servers, error reporting is off, therefore, we do not get these errors.
在生产服务器上,错误报告处于关闭状态,因此,我们没有收到这些错误。
On the development server, however, we can set error reporting on.
但是,在开发服务器上,我们可以将错误报告设置为。
To get rid of this error, we see the following example:
为了消除此错误,我们查看以下示例:
if ($my == 9) {
$test = 'yes'; // Will produce an error as $my is not 9.
}
echo $test;
We can initialize the variables to NULL
before assigning their values or using them.
在赋值或使用变量之前,我们可以将变量初始化为NULL。
So, we can modify the code as:
因此,我们可以将代码修改为:
$test = NULL;
if ($my == 9) {
$test = 'yes'; // Will produce an error as $my is not 9.
}
echo $test;
This will not disturb any program logic and will not produce a Notice even if $test
does not have a value.
这不会干扰任何程序逻辑,即使$test没有值,也不会产生通知。
So, basically, it’s always better to set error reporting ON for development.
因此,基本上,为开发设置错误报告总是更好的。
And fix all the errors.
并修复所有错误。
And on production, error reporting should be set to off.
在生产环境中,应将错误报告设置为关闭。
I asked a question about this and I was referred to this post with the message:
我问了一个关于这个问题的问题,我被推荐到这个帖子,上面写着这样一条信息:
This question already has an answer here:
“Notice: Undefined variable”, “Notice: Undefined index”, and “Notice:
Undefined offset” using PHP
I am sharing my question and solution here:
我在这里分享我的问题和解决方案:
This is the error:
这是错误:
Line 154 is the problem. This is what I have in line 154:
154线是问题所在。这是我在第154行的内容:
153 foreach($cities as $key => $city){
154 if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){
I think the problem is that I am writing if conditions for the variable $city
, which is not the key but the value in $key => $city
. First, could you confirm if that is the cause of the warning? Second, if that is the problem, why is it that I cannot write a condition based on the value? Does it have to be with the key that I need to write the condition?
我认为问题在于,我正在为变量$City编写if条件,它不是键,而是$key=>$City中的值。首先,你能确认这是否是警告的原因吗?其次,如果这就是问题所在,为什么我不能根据值编写条件呢?我写这个条件一定要用密钥吗?
UPDATE 1: The problem is that when executing $citiesCounterArray[$key]
, sometimes the $key
corresponds to a key that does not exist in the $citiesCounterArray
array, but that is not always the case based on the data of my loop. What I need is to set a condition so that if $key
exists in the array, then run the code, otherwise, skip it.
更新1:问题是,在执行$citiesCounterArray[$key]时,有时$key对应的键在$citiesCounterArray数组中不存在,但根据我的循环的数据,情况并不总是如此。我需要设置一个条件,以便如果数组中存在$key,则运行代码,否则跳过它。
UPDATE 2: This is how I fixed it by using array_key_exists()
:
更新2:这是我使用ARRAY_KEY_EXISTS()修复它的方式:
foreach($cities as $key => $city){
if(array_key_exists($key, $citiesCounterArray)){
if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){
Probably you were using an old PHP version until and now upgraded PHP that’s the reason it was working without any error till now from years.
您可能一直在使用旧的PHP版本,直到现在升级了PHP,这就是它多年来一直工作而没有任何错误的原因。
Until PHP 4 there was no error if you are using variable without defining it but as of PHP 5 onwards it throws errors for codes like mentioned in question.
在PHP4之前,如果您在没有定义变量的情况下使用变量,则不会出现错误,但从PHP5开始,它会为上述代码抛出错误。
If you are sending data to an API, simply use isset():
如果要将数据发送到API,只需使用isset():
if(isset($_POST['param'])){
$param = $_POST['param'];
} else {
# Do something else
}
If it is an error is because of a session, make sure you have started the session properly.
如果是由于会话导致的错误,请确保您已正确启动会话。
Those notices are because you don't have the used variable defined
and my_index
key was not present into $my_array
variable.
这些注意事项是因为您没有定义USED变量,并且$MY_ARRAY变量中没有出现MY_INDEX键。
Those notices were triggered every time, because your code
is not correct, but probably you didn't have the reporting of notices on.
每次都会触发这些通知,因为您的代码不正确,但可能您没有报告通知。
Solve the bugs:
解决错误:
$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
}
Another way to get this out:
另一种解决办法是:
ini_set("error_reporting", false)
When dealing with files, a proper enctype and a POST method are required, which will trigger an undefined index notice if either are not included in the form.
在处理文件时,需要正确的enctype和POST方法,如果表单中没有包含任何一个,这将触发未定义的索引通知。
The manual states the following basic syntax:
该手册说明了以下基本语法:
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>";
?>
Reference:
参考资料:
In PHP you need first to define the variable. After that you can use it.
在PHP中,您需要首先定义变量。在那之后你就可以用了。
We can check if a variable is defined or not in a very efficient way!
我们可以非常有效地检查变量是否已定义!
// 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 if the variable is defined or undefined
// Isset() does not check that variable has a true or false value
// But it checks the null value of a variable
if(isset($my_variable_name)){
}
Simple Explanation
// It will work with: true, false, and NULL
$defineVariable = false;
if($defineVariable){
echo "true";
}else{
echo "false";
}
// It will check if the variable is defined or not and if the variable has a null value.
if(isset($unDefineVariable)){
echo "true";
}else{
echo "false";
}
更多回答
@dieselpower44 A couple of thoughts: The "shut-up operator" (@
) has some performance issues. Also, since it suppresses all errors within a particular scope, using it without care might mask messages you wish you'd seen.
@dieselPower44有几个想法:“闭嘴操作员”(@)有一些性能问题。此外,因为它抑制特定范围内的所有错误,所以不小心使用它可能会掩盖您希望看到的消息。
Hiding the issues is NOT the way to deal with issues. Items #2...#4 can be used only on production servers, not in general.
隐藏问题不是处理问题的方法。项目#2...#4只能在生产服务器上使用,不能在一般情况下使用。
Is it possible to shut-up the message inline (not in handler) when also a custom error handler is used? $var = @$_GET['nonexisting'];
still causes notice..
当还使用自定义错误处理程序时,是否可以关闭内联消息(不在处理程序中)?$var=@$_GET[‘NONEXISTING’];仍然引起注意..
Why is it recommended to use 1. $value = isset($_POST['value']) ? $_POST['value'] : '';
instead of using 4. $value = @$_POST['value'];
?
为什么建议使用1.$VALUE=isset($_POST[‘VALUE’])?$_POST[‘VALUE’]:‘’;而不是使用4.$VALUE=@$_POST[‘VALUE’];?
I don't recommend using isset() for arrays, e.g. $str = '111';
, (I know it should be array) isset($str[0])
will return true. It's better off using array_key_exist() instead of isset()
我不建议对数组使用isset(),例如$str=‘111’;,(我知道它应该是数组)isset($str[0])将返回TRUE。最好使用ARRAY_KEY_EXIST()而不是isset()
If using E_NOTICE
from the php.ini
configuration file, do error_reporting = (E_ALL & ~E_NOTICE)
如果使用php.ini配置文件中的E_NOTICE,则执行ERROR_REPORT=(E_ALL&~E_NOTICE)
From the above answer, I have tried isset, array_key_exists but those didn't work. I tried your answer, .empty(), and it works. Thank you very much!
从上面的答案来看,我已经尝试了isset、arraykey_Existes,但它们都不起作用。我尝试了您的答案.Empty(),它起作用了。非常感谢!
Thank you so much . I have add "error_reporting(E_ALL ^ E_NOTICE); " this is working to me .
太感谢你了。我添加了“ERROR_REPORTING(E_ALL^E_NOTICE);”,这对我很有效。
If you are curious what is the performance impact, this article summarises it well, derickrethans.nl/….
如果你想知道性能影响是什么,这篇文章很好地总结了它,derickrethans.nl/.
@GajusKuizinas There have been quoite a few changes since 2009, in particular php.net/ChangeLog-5.php#5.4.0 changes the outcome drastically (see "Zend Engine, performance" and "(silence) operator").
@GaushKuizinas自2009年以来已经有了一些变化,特别是php.net/changelog-5.php#5.4.0彻底改变了结果(参见“Zend Engine,Performance”和“(Silent)运算符”)。
Thanks @mario, interesting. Now, if someone was good enough to benchmark the two... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs According to this test, seem to be identical (notice that scale changes).
谢谢@Mario,很有趣。现在,如果有人足够好来衡量这两个... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs根据此测试,似乎是相同的(注意比例变化)。
Please don't turn warnings off. In stricter languages, they often mean "there might be a bug, you better check this line twice" - in a language as permissive as PHP, they often means "this code is crap and propably riddled with bugs; I'll try to make some sense of it but you better fix this ASAP".
请不要关闭警告。在更严格的语言中,它们通常意味着“可能有错误,您最好检查这一行两次”--在像PHP这样宽松的语言中,它们通常意味着“这段代码一团糟,可能充满了错误;我会试着理解它,但您最好尽快修复它”。
Although I agree with the first three points, #4 is simply wrong. Hiding a problem won't make it go away, and it might even cause more problems down the road.
虽然我同意前三点,但第四点是完全错误的。隐藏一个问题不会让它消失,它甚至可能在未来引发更多的问题。
@Freek absolutely true, but in some scenarios (Bought script, zero technical knowledge, need it running by tomorrow...) it's the duct-tape solution - really bad, that always needs emphasizing, but an option
@Freek绝对正确,但在某些情况下(购买的脚本,零技术知识,需要在明天之前运行...)这是管道胶带解决方案--非常糟糕,总是需要强调,但也是一个选择
Your ifexists() function doesn't work for me in PHP 5.3. The caller's variables are not available in the function's local scope (see Variable scope), unless they are Superglobals or you fiddle with $GLOBALS, so $foo = "BABAR"; ifexists('foo');
will in general return null. (Italics are php.net chapters.)
你的ifexists()函数在PHP 5.3中不适用。调用者的变量在函数的局部作用域中不可用(参见变量作用域),除非它们是超全局变量或者你摆弄了$GLOBALS,所以$foo =“BABAR”; ifexists('foo');通常会返回null。(斜体是php.net章节。)
now you will get "hello from"... what's the point? just check the value if( !empty($user) and !empty($location) ) echo "hello $user ..."
现在你会得到“Hello from”..。这有什么意义呢?如果(!Empty($User)and!Empty($Location))回显“Hello$USER...”,只需检查该值。
We experienced a change in behavior similar to this that was due to error_reporting
behaving differently than expected because of a custom error_handler
in our code that we were previously unaware of.
我们经历了与此类似的行为更改,这是因为ERROR_REPORT的行为与预期的不同,因为我们的代码中有一个我们以前不知道的自定义ERROR_HANDLER。
This also works fine in if statements. if (is_array($my_array['idontexist'] ?? '')) { dosomething(); }
这在IF语句中也可以很好地工作。If(is_array($my_array[‘idontexist’]??‘’)){dosomething();}
Your code is actually a nice overlooked bug: ?? - only checks for isset()
, if you pass is_array()
- which is a boolean, unexpected behavior will follow.
你的代码实际上是一个很好的被忽视的错误:?-只检查isset(),如果你传递的是一个布尔值,意外的行为将会随之而来。
What does "php>" signal? A REPL of some sort? If yes, which one?
“php>”表示什么?某种类型的REPL?如果是,是哪一家?
What would be an example of an API? What are you referring to? Can you elaborate?
API的一个例子是什么?你指的是什么?你能详细说明一下吗?
我是一名优秀的程序员,十分优秀!