这是什么?
这是一些关于在编程PHP时可能遇到的警告、错误和注意事项的答案,而不知道如何修复它们。这也是一个社区维基,所以每个人都被邀请加入和维护这个列表。
为什么会这样?
Questions like "Headers already sent" or "Calling a member of a non-object" pop up frequently on Stack Overflow. The root cause of those questions is always the same. So the answers to those questions typically repeat them and then show the OP which line to change in their particular case. These answers do not add any value to the site because they only apply to the OP's particular code. Other users having the same error cannot easily read the solution out of it because they are too localized. That is sad because once you understood the root cause, fixing the error is trivial. Hence, this list tries to explain the solution in a general way to apply.
我该怎么做呢?
如果您的问题被标记为此问题的副本,请在下面找到您的错误消息并将修复应用于您的代码。答案通常包含进一步的调查链接,以防仅从一般答案中不清楚。
如果您想投稿,请添加您“最喜欢的”错误消息、警告或通知,每个答案一条,简短描述它的含义(即使它只是突出显示手册页的术语),可能的解决方案或调试方法,以及现有的有价值的问答列表。此外,请随意改进任何现有的答案。
列表
Nothing is seen. The page is empty and white. (also known as White Page/Screen Of Death)
Code doesn't run/what looks like parts of my PHP code are output
Warning: Cannot modify header information - headers already sent
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given a.k.a.
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource
Warning: [function] expects parameter 1 to be resource, boolean given
Warning: [function]: failed to open stream: [reason]
Warning: open_basedir restriction in effect
Warning: Division by zero
Warning: Illegal string offset 'XXX'
Warning: count(): Parameter must be an array or an object that implements Countable
Parse error: syntax error, unexpected '['
Parse error: syntax error, unexpected T_XXX
Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM
Parse error: syntax error, unexpected 'require_once' (T_REQUIRE_ONCE), expecting function (T_FUNCTION)
Parse error: syntax error, unexpected T_VARIABLE
Fatal error: Allowed memory size of XXX bytes exhausted (tried to allocate XXX bytes)
Fatal error: Maximum execution time of XX seconds exceeded
Fatal error: Call to a member function ... on a non-object or null
Fatal Error: Call to Undefined function XXX
Fatal Error: Cannot redeclare XXX
Fatal error: Can't use function return value in write context
Fatal error: Declaration of AAA::BBB() must be compatible with that of CCC::BBB()'
Return type of AAA::BBB() should either be compatible with CCC::BBB(), or the #[\ReturnTypeWillChange] attribute should be used
Fatal error: Using $this when not in object context
Fatal error: Object of class Closure could not be converted to string
Fatal error: Undefined class constant
Fatal error: Uncaught TypeError: Argument #n must be of type x, y given
Notice: Array to string conversion (< PHP 8.0) or Warning: Array to string conversion (>= PHP 8.0)
Notice: Trying to get property of non-object error
Notice: Undefined variable or property
"Notice: Undefined Index", or "Warning: Undefined array key"
Notice: Undefined offset XXX [Reference]
Notice: Uninitialized string offset: XXX
Notice: Use of undefined constant XXX - assumed 'XXX' / Error: Undefined constant XXX
MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ... at line ...
Strict Standards: Non-static method [<class>::<method>] should not be called statically
Warning: function expects parameter X to be boolean/string/integer
HTTP Error 500 - Internal server error
Deprecated: Arrays and strings offset access syntax with curly braces is deprecated
还看到:
这个符号在PHP中是什么意思?
"注意:未定义索引"或"警告:未定义数组键"
当您试图通过数组中不存在的键访问数组时发生。
一个典型的Undefined Index通知的例子是(demo)
$data = array('foo' => '42', 'bar');
echo $data['spinach'];
echo $data[1];
数组中菠菜和1都不存在,会触发E_NOTICE。在PHP 8.0中,这是一个E_WARNING。
解决方案是确保在访问索引之前存在索引或偏移量。这可能意味着您需要修复程序中的一个错误,以确保这些索引在您期望它们存在时确实存在。或者这可能意味着你需要使用array_key_exists或isset来测试索引是否存在:
$data = array('foo' => '42', 'bar');
if (array_key_exists('spinach', $data)) {
echo $data['spinach'];
}
else {
echo 'No key spinach in the array';
}
如果你有这样的代码:
<?php echo $_POST['message']; ?>
<form method="post" action="">
<input type="text" name="message">
...
那么$_POST['message']将不会在这个页面第一次加载时设置,你将得到上述错误。只有在提交表单并再次运行此代码时,数组索引才会存在。你通常用以下方法检查:
if ($_POST) .. // if the $_POST array is not empty
// or
if ($_SERVER['REQUEST_METHOD'] == 'POST') .. // page was requested with POST
相关问题:
参考文献:“Notice: Undefined variable”和“Notice: Undefined index”
所有关于Stackoverflow的PHP“注意:未定义的索引”问题
http://php.net/arrays
注意:试图获取非对象错误的属性
在没有对象时试图访问对象的属性时发生。
非对象通知的一个典型例子是
$users = json_decode('[{"name": "hakre"}]');
echo $users->name; # Notice: Trying to get property of non-object
在本例中,$users是一个数组(因此不是一个对象),它没有任何属性。
这类似于访问数组中不存在的索引或键(参见注意:未定义索引)。
这个例子简化了很多。大多数情况下,这样的通知表示一个未检查的返回值,例如,如果一个对象不存在,或者只是一个意外的非对象值(例如,在Xpath结果中,具有意外格式的JSON结构,具有意外格式的XML等),库将返回NULL,但代码不会检查这样的条件。
由于这些非对象通常会被进一步处理,因此在对非对象调用对象方法时经常会发生致命错误(参见:致命错误:调用成员函数…在非对象上)停止脚本。
通过检查错误条件和/或变量是否符合期望,可以很容易地防止这种情况。下面是一个带有DOMXPath示例的通知:
$result = $xpath->query("//*[@id='detail-sections']/div[1]");
$divText = $result->item(0)->nodeValue; # Notice: Trying to get property of non-object
问题是访问第一项的nodeValue属性(字段),而没有检查它是否存在于$result集合中。相反,通过将变量分配给代码所操作的对象,可以使代码更加显式:
$result = $xpath->query("//*[@id='detail-sections']/div[1]");
$div = $result->item(0);
$divText = "-/-";
if (is_object($div)) {
$divText = $div->nodeValue;
}
echo $divText;
相关的错误:
注意:未定义索引
致命错误:调用成员函数…在一个非物体上
警告:[function]: failed to open stream: [reason]
当你通过include, require或fopen调用一个文件时,PHP无法找到该文件或没有足够的权限来加载该文件。
这种情况的发生有多种原因:
文件路径错误
文件路径是相对的
包含路径是错误的
权限限制太大
SELinux已生效
还有更多……
一个常见的错误是不使用绝对路径。这可以通过使用完整路径或神奇常数如__DIR__或dirname(__FILE__)轻松解决:
include __DIR__ . '/inc/globals.inc.php';
or:
require dirname(__FILE__) . '/inc/globals.inc.php';
确保使用正确的路径是排除这些问题的一个步骤,这也可能与不存在的文件、文件系统的权限阻止访问或PHP本身的打开basedir限制有关。
快速解决此问题的最佳方法是遵循下面的故障排除清单。
相关问题:
故障排除清单:无法打开流
相关的错误:
警告:open_basedir限制生效
致命错误:调用成员函数…在一个非物体上
发生在类似于xyz->method()的代码中,其中xyz不是对象,因此不能调用该方法。
这是一个致命错误,将停止脚本(向前兼容性注意:它将从PHP 7开始成为一个可捕获的错误)。
大多数情况下,这表明代码缺少对错误条件的检查。在调用一个对象的方法之前,验证它确实是一个对象。
一个典型的例子是
// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);
在上面的例子中,查询不能被准备,并且prepare()会将false赋值给$statement。尝试调用execute()方法将导致致命错误,因为false是一个“非对象”,因为该值是一个布尔值。
弄清楚为什么函数返回一个布尔值而不是一个对象。例如,检查$pdo对象中最近发生的错误。关于如何调试的细节将取决于如何处理特定函数/对象/类的错误。
如果->准备失败,那么你的$pdo数据库句柄对象没有被传递到当前作用域。找到它被定义的地方。然后将其作为参数传递,将其作为属性存储,或通过全局作用域共享。
另一个问题可能是有条件地创建一个对象,然后尝试在该条件块之外调用一个方法。例如
if ($someCondition) {
$myObj = new MyObj();
}
// ...
$myObj->someMethod();
如果试图在条件块之外执行方法,则可能无法定义对象。
相关问题:
调用非对象上的成员函数
列出所有PHP“致命错误:调用成员函数…”关于Stackoverflow的问题
代码不运行/我的PHP代码的某些部分被输出
如果你的PHP代码没有任何结果,或者你在网页中看到你的PHP源代码输出的部分文字,你可以很确定你的PHP实际上没有被执行。如果在浏览器中使用“查看源代码”,则可能会看到完整的PHP源代码文件。因为PHP代码嵌入在<?php ?>标记时,浏览器将尝试将它们解释为HTML标记,结果可能看起来有些混乱。
要真正运行PHP脚本,您需要:
执行脚本的web服务器
将文件扩展名设置为.php,否则web服务器不会将其解释为*
通过web服务器访问你的。php文件
*除非你重新配置,否则一切都可以配置。
最后一点尤其重要。只需双击该文件,就可以在浏览器中使用如下地址打开它:
file://C:/path/to/my/file.php
这完全绕过了您可能正在运行的任何web服务器,并且文件没有得到解释。你需要在你的web服务器上访问文件的URL,可能是这样的:
http://localhost/my/file.php
您可能还想检查是否使用了短的打开标记<?而不是<?php和您的php配置已关闭短打开标记。
还可以看到PHP代码没有被执行,而是代码显示在页面上
解析错误:语法错误,意外的T_ENCAPSED_AND_WHITESPACE
在PHP 8.0及以上版本中,该消息改为:
语法错误,意外的字符串内容“”,期望“-”或标识符或变量或数字
当试图在双引号字符串中引用带有引号键的数组值时,当整个复杂变量结构没有包含在{}中时,最常遇到此错误。
错误情况:
这将导致意外的T_ENCAPSED_AND_WHITESPACE:
echo "This is a double-quoted string with a quoted array key in $array['key']";
//---------------------------------------------------------------------^^^^^
可能的修复:
在双引号字符串中,PHP将允许数组关键字字符串不带引号使用,并且不会发出E_NOTICE。所以上面可以写成:
echo "This is a double-quoted string with an un-quoted array key in $array[key]";
//------------------------------------------------------------------------^^^^^
整个复杂数组变量和键可以被括在{}中,在这种情况下,它们应该被引用以避免E_NOTICE。PHP文档对于复杂变量推荐使用这种语法。
echo "This is a double-quoted string with a quoted array key in {$array['key']}";
//--------------------------------------------------------------^^^^^^^^^^^^^^^
// Or a complex array property of an object:
echo "This is a a double-quoted string with a complex {$object->property->array['key']}";
当然,上述任何一种方法的替代方法都是将数组变量连接到,而不是插值它:
echo "This is a double-quoted string with an array variable". $array['key'] . " concatenated inside.";
//----------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^
如需参考,请参阅PHP字符串手册页中的变量解析部分