这是什么?

这是一些关于在编程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中是什么意思?


当前回答

注意:未定义变量

在尝试使用以前未定义的变量时发生。

一个典型的例子是

foreach ($items as $item) {
    // do something with item
    $counter++;
}

如果您之前没有定义$counter,上面的代码将触发通知。

正确的方法是在使用变量之前设置它

$counter = 0;
foreach ($items as $item) {
    // do something with item
    $counter++;
}

类似地,变量在其作用域之外是不可访问的,例如在使用匿名函数时。

$prefix = "Blueberry";
$food = ["cake", "cheese", "pie"];
$prefixedFood = array_map(function ($food) {
  // Prefix is undefined
  return "${prefix} ${food}";
}, $food);

这应该使用use来传递

$prefix = "Blueberry";
$food = ["cake", "cheese", "pie"];
$prefixedFood = array_map(function ($food) use ($prefix) {
  return "${prefix} ${food}";
}, $food);

注意:未定义的属性

此错误的含义大致相同,但指的是对象的属性。重用上面的示例,这段代码将触发错误,因为没有设置counter属性。

$obj = new stdclass;
$obj->property = 2342;
foreach ($items as $item) {
    // do something with item
    $obj->counter++;
}

相关问题:

所有关于Stackoverflow的PHP“注意:未定义变量”问题 “注意:未定义的变量”,“注意:未定义的索引”,“注意:未定义的偏移量”使用PHP 参考:什么是变量作用域,哪些变量可以从哪里访问,什么是“未定义变量”错误?

其他回答

警告:不能修改报头信息-报头已经发送

当您的脚本试图向客户端发送HTTP报头,但之前已经有输出,导致报头已经发送到客户端时发生。

这是一个E_WARNING,它不会停止脚本。

一个典型的例子是这样的模板文件:

<html>
    <?php session_start(); ?>
    <head><title>My Page</title>
</html>
...

session_start()函数将尝试向客户端发送带有会话cookie的报头。但是PHP在将<html>元素写入输出流时已经发送了头文件。您必须将session_start()移到顶部。

您可以通过遍历代码触发Warning之前的行并检查它输出的位置来解决这个问题。移动任何头发送代码之前的代码。

一个经常被忽略的输出是PHP关闭?>后的新行。当?>是文件中的最后一个内容时,省略它被认为是一种标准实践。同样,出现此警告的另一个常见原因是当开头<?php前面有一个空格,行,或者不可见的字符,导致web服务器发送报头和空格/换行,这样当php开始解析时就不能提交任何报头。

如果您的文件有多个<?php……?>代码块,它们之间不应该有任何空格。(注意:如果你有自动构造的代码,你可能有多个块)

还要确保在代码中没有任何字节顺序标记,例如当脚本的编码是UTF-8和BOM时。

相关问题:

头文件已经被PHP发送 所有PHP“头已经发送”的问题在Stackoverflow 字节顺序标记 什么PHP函数可以创建输出?

致命错误:不能在写上下文中使用函数返回值

这通常发生在直接使用带有empty的函数时。

例子:

if (empty(is_null(null))) {
  echo 'empty';
}

这是因为empty是一个语言结构,而不是一个函数,在5.5之前的PHP版本中,它不能用表达式作为参数调用。在PHP 5.5之前,empty()的参数必须是变量,但在PHP 5.5+中允许任意表达式(例如函数的返回值)。

Empty,尽管它的名字,实际上并不检查一个变量是否为“空”。相反,它检查变量是否存在,或== false。表达式(如示例中的is_null(null))将始终被视为存在,因此这里的empty仅检查它是否等于false。你可以在这里用!替换empty(),例如if (!is_null(null)),或者显式地与false进行比较,例如if (is_null(null) == false)。

相关问题:

致命错误:不能使用函数返回值

致命错误:闭包类的对象不能转换为字符串

这意味着您没有执行匿名函数(或闭包)。

在这个例子中,使用箭头函数会抛出一个错误:

echo $fn = fn($x = 42) => $x;

或者对任何匿名函数

echo function($x = 42) { return $x; };

要解决这个错误,您需要执行闭包。

echo $fn = (fn($x = 42) => $x)(30); // take notice of the 2 sets of brackets

echo (function($x = 42) { return $x; })(30);

这种语法叫做IIFE,是在PHP 7中添加的。

严格标准:非静态方法[<class>::<method>]不应该被静态调用

当您试图在类上调用静态的非静态方法时发生,并且您在error_reporting()设置中也有E_STRICT标志。

例子:

class HTML {
   public function br() {
      echo '<br>';
   }
}

HTML::br()或$ HTML::br()

实际上,您可以通过不向error_reporting()添加E_STRICT来避免此错误,例如

error_reporting(E_ALL & ~E_STRICT);

因为对于PHP 5.4.0及以上版本,E_STRICT包含在E_ALL [ref]中。但这并不可取。解决方案是将你想要的静态函数定义为实际的静态函数:

public static function br() {
  echo '<br>';
}

或者按常规调用函数:

$html = new HTML();
$html->br();

相关问题:

我如何解决“非静态方法xxx:xxx()不应该在PHP 5.4中被静态调用?”

已弃用:不支持使用花括号的数组和字符串偏移访问语法

在PHP 7.4.0之前,字符串偏移量和数组元素可以通过花括号{}访问:

$string = 'abc';
echo $string{0};  // a

$array = [1, 2, 3];
echo $array{0};  // 1

自PHP 7.4.0起已弃用,并生成一个警告:

已弃用:不支持使用花括号的数组和字符串偏移访问语法

你必须使用方括号[]来访问字符串偏移量和数组元素:

$string = 'abc';
echo $string[0];  // a

$array = [1, 2, 3];
echo $array[0];  // 1

此更改的RFC链接到一个PHP脚本,该脚本试图机械地修复此问题。