这是什么?

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


当前回答

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

在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脚本,该脚本试图机械地修复此问题。

其他回答

注意:未初始化的字符串偏移量:*

顾名思义,当您很可能试图遍历或从具有不存在键的数组中查找值时,就会发生此类错误。

考虑到您正在尝试显示$string中的每个字母

$string = 'ABCD'; 
for ($i=0, $len = strlen($string); $i <= $len; $i++){
    echo "$string[$i] \n"; 
}

上面的例子将生成(在线演示):

A
B
C
D
Notice: Uninitialized string offset: 4 in XXX on line X

并且,一旦脚本完成回显D,你就会得到错误,因为在for()循环中,你已经告诉PHP显示你从'ABCD'的第一个到第五个字符串字符,存在,但由于循环从0开始计数,并在到达4时回显D,它将抛出偏移错误。

类似的错误:

非法字符串偏移量'选项1'

什么也看不见。页面是空白的,白色的。

也被称为白页死亡或白屏幕死亡。当错误报告被关闭并且发生致命错误(通常是语法错误)时,就会发生这种情况。

如果启用了错误日志记录,您将在错误日志中找到具体的错误消息。这通常在一个名为“php_errors.log”的文件中,要么在一个中心位置(例如在许多Linux环境中是/var/log/apache2),要么在脚本本身的目录中(有时在共享主机环境中使用)。

有时,临时启用错误显示可能更直接。然后,白页将显示错误消息。要小心,因为这些错误对访问网站的每个人都是可见的。

这可以通过在脚本顶部添加以下PHP代码轻松完成:

ini_set('display_errors', 1); error_reporting(~0);

代码将打开错误显示并将报告设置为最高级别。

由于ini_set()是在运行时执行的,它对解析/语法错误没有影响。这些错误将出现在日志中。如果你想在输出中显示它们(例如在浏览器中),你必须将display_startup_errors指令设置为true。在php.ini或.htaccess或任何其他在运行时之前影响配置的方法中执行此操作。

您可以使用相同的方法设置log_errors和error_log指令来选择您自己的日志文件位置。

查看日志或使用显示,您将得到更好的错误消息和脚本停止的代码行。

相关问题:

PHP的白屏死机 白屏死机! PHP不显示错误消息 PHP在错误时释放500 -在哪里有文档? 如何在PHP中获得有用的错误消息? 关于Stackoverflow的所有PHP“死亡白页”问题

相关的错误:

解析错误:语法错误,意外的T_XXX 致命错误:调用成员函数…在一个非物体上 代码不运行/我的PHP代码的某些部分被输出

some_function():参数#1必须是给定的x, y类型

这个错误不言自明。您的代码试图调用some_function(),并将错误类型的数据作为参数之一传递。例如:

<?php declare(strict_types=1);

function multiply(int $x, int $y) { return $x * $y; }

echo multiply("3", 4);

因为被调用的函数的第一个参数是int标量类型,并且调用是在一个启用了严格类型的文件中(stict_types=1),所以当传递字符串给它时,它会出现类型错误:

TypeError: multiply():参数#1 ($x)必须是类型为整型,字符串在…

这个例子来自3v4l.org。

警告:数组到字符串的转换

注意:数组到字符串的转换

(PHP 7.4之前的一个通知,PHP 8.0之后的一个警告)

如果你试图将数组视为字符串,就会发生这种情况:

$arr = array('foo', 'bar');

echo $arr;  // Notice: Array to string conversion
$str = 'Something, ' . $arr;  // Notice: Array to string conversion

数组不能简单地与字符串回显或连接,因为结果没有很好地定义。PHP将使用字符串“Array”来代替数组,并触发通知,指出这可能不是预期的结果,您应该检查这里的代码。你可能想要这样的东西:

echo $arr[0];  // displays foo
$str = 'Something ' . join(', ', $arr); //displays Something, foo, bar

或者循环数组:

foreach($arr as $key => $value) {
    echo "array $key = $value";
    // displays first: array 0 = foo
    // displays next:  array 1 = bar
}

如果这个通知出现在您意想不到的地方,这意味着您认为是字符串的变量实际上是一个数组。这意味着你的代码中有一个错误,使这个变量成为一个数组,而不是你期望的字符串。

mysql_connect(): user 'name'@'host'拒绝访问

当您连接到无效或缺少凭据(用户名/密码)的MySQL/MariaDB服务器时,会出现此警告。所以这通常不是代码问题,而是服务器配置问题。

See the manual page on mysql_connect("localhost", "user", "pw") for examples. Check that you actually used a $username and $password. It's uncommon that you gain access using no password - which is what happened when the Warning: said (using password: NO). Only the local test server usually allows to connect with username root, no password, and the test database name. You can test if they're really correct using the command line client: mysql --user="username" --password="password" testdb Username and password are case-sensitive and whitespace is not ignored. If your password contains meta characters like $, escape them, or put the password in single quotes. Most shared hosting providers predeclare mysql accounts in relation to the unix user account (sometimes just prefixes or extra numeric suffixes). See the docs for a pattern or documentation, and CPanel or whatever interface for setting a password. See the MySQL manual on Adding user accounts using the command line. When connected as admin user you can issue a query like: CREATE USER 'username'@'localhost' IDENTIFIED BY 'newpassword'; Or use Adminer or WorkBench or any other graphical tool to create, check or correct account details. If you can't fix your credentials, then asking the internet to "please help" will have no effect. Only you and your hosting provider have permissions and sufficient access to diagnose and fix things. Verify that you could reach the database server, using the host name given by your provider: ping dbserver.hoster.example.net Check this from a SSH console directly on your webserver. Testing from your local development client to your shared hosting server is rarely meaningful. Often you just want the server name to be "localhost", which normally utilizes a local named socket when available. Othertimes you can try "127.0.0.1" as fallback. Should your MySQL/MariaDB server listen on a different port, then use "servername:3306". If that fails, then there's a perhaps a firewall issue. (Off-topic, not a programming question. No remote guess-helping possible.) When using constants like e.g. DB_USER or DB_PASSWORD, check that they're actually defined. If you get a "Warning: Access defined for 'DB_USER'@'host'" and a "Notice: use of undefined constant 'DB_PASS'", then that's your problem. Verify that your e.g. xy/db-config.php was actually included and whatelse. Check for correctly set GRANT permissions. It's not sufficient to have a username+password pair. Each MySQL/MariaDB account can have an attached set of permissions. Those can restrict which databases you are allowed to connect to, from which client/server the connection may originate from, and which queries are permitted. The "Access denied" warning thus may as well show up for mysql_query calls, if you don't have permissions to SELECT from a specific table, or INSERT/UPDATE, and more commonly DELETE anything. You can adapt account permissions when connected per command line client using the admin account with a query like: GRANT ALL ON yourdb.* TO 'username'@'localhost'; If the warning shows up first with Warning: mysql_query(): Access denied for user ''@'localhost' then you may have a php.ini-preconfigured account/password pair. Check that mysql.default_user= and mysql.default_password= have meaningful values. Oftentimes this is a provider-configuration. So contact their support for mismatches. Find the documentation of your shared hosting provider: e.g. HostGator, GoDaddy, 1and1, DigitalOcean, BlueHost, DreamHost, MediaTemple, ixWebhosting, lunarhosting, or just google yours´. Else consult your webhosting provider through their support channels. Note that you may also have depleted the available connection pool. You'll get access denied warnings for too many concurrent connections. (You have to investigate the setup. That's an off-topic server configuration issue, not a programming question.) Your libmysql client version may not be compatible with the database server. Normally MySQL and MariaDB servers can be reached with PHPs compiled in driver. If you have a custom setup, or an outdated PHP version, and a much newer database server, or significantly outdated one - then the version mismatch may prevent connections. (No, you have to investigate yourself. Nobody can guess your setup).

更多的引用:

mysql服务器错误:mysql用户无法访问root用户 mysql_connect():拒绝访问 mysql_select_db()拒绝访问用户" @'localhost'(使用密码:NO) PHPMyAdmin拒绝用户“root”@“localhost”的访问

顺便说一句,你可能不想再使用mysql_*函数了。新来者经常迁移到mysqli,然而这也一样乏味。相反,阅读PDO和准备好的语句。 $db =新PDO("mysql:主机=localhost;dbname=testdb", "用户名","密码");