这是什么?

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


当前回答

致命错误:调用成员函数…在一个非物体上

发生在类似于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的问题

其他回答

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", "用户名","密码");

致命错误:调用未定义的函数XXX

在尝试调用尚未定义的函数时发生。常见的原因包括缺少扩展和包含,有条件的函数声明,函数声明中的函数或简单的拼写错误。

例1 -条件函数声明

$someCondition = false;
if ($someCondition === true) {
    function fn() {
        return 1;
    }
}
echo fn(); // triggers error

在这种情况下,fn()将永远不会被声明,因为$someCondition不为真。

例2 -函数声明中的函数

function createFn() 
{
    function fn() {
        return 1;
    }
}
echo fn(); // triggers error

在这种情况下,只有在调用createFn()时才声明fn。注意,后续调用createFn()将触发一个关于重新声明现有函数的错误。

在PHP内置函数中也可以看到这种情况。尝试在官方手册中搜索该函数,并检查它属于哪个“扩展”(PHP模块),以及哪些版本的PHP支持它。

如果缺少扩展,请安装该扩展并在php.ini中启用它。请参阅PHP手册中的安装说明,以了解函数在扩展中的显示。你也可以使用你的包管理器(例如Debian或Ubuntu中的apt, Red Hat或CentOS中的yum),或共享托管环境中的控制面板来启用或安装扩展。

如果该函数是在您正在使用的PHP的新版本中引入的,那么您可以在手册或评论部分中找到替代实现的链接。如果它已从PHP中删除,请查找有关原因的信息,因为可能不再需要它了。

如果缺少include,请确保在调用函数之前包含声明该函数的文件。

如果出现错别字,请改正错别字。

相关问题:

https://stackoverflow.com/search?q=Fatal+error%3A+Call+to+undefined+function

注意:未定义变量

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

一个典型的例子是

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 参考:什么是变量作用域,哪些变量可以从哪里访问,什么是“未定义变量”错误?

解析错误:语法错误,意外的T_VARIABLE

可能的场景

我似乎找不到我的代码出了什么问题。以下是我的全部错误:

解析错误:语法错误,意外的T_VARIABLE在x行

我正在尝试的

$sql = 'SELECT * FROM dealer WHERE id="'$id.'"';

回答

解析错误:程序的语法问题,例如在语句的末尾遗漏了分号,或者像上面的情况一样,遗漏了。操作符。解释器在遇到解析错误时停止运行程序。

简单地说,这是一个语法错误,这意味着您的代码中有一些东西阻止了它被正确解析,从而无法运行。

您应该做的是仔细检查错误所在的行周围是否有任何简单的错误。

该错误消息意味着,在文件的第x行,PHP解释器期望看到一个开括号,但相反,它遇到了名为T_VARIABLE的东西。T_VARIABLE这个东西叫做令牌。它是PHP解释器表达程序不同基本部分的方式。当解释器读入程序时,它将您所编写的内容转换为令牌列表。无论你在程序中放入一个变量,解释器的列表中都会有一个aT_VARIABLE令牌。

不错的阅读:解析器令牌列表

因此,请确保在php.ini中至少启用了E_PARSE。产品脚本中不应该存在解析错误。

我总是建议在编码时添加以下语句:

error_reporting(E_ALL);

PHP错误报告

另外,使用IDE是个好主意,它可以让你在输入时知道解析错误。你可以使用:

NetBeans(一个漂亮的免费软件)(在我看来是最好的) PhpStorm(戈登叔叔喜欢这个:P,付费计划,包含专有和免费软件) Eclipse(美女与野兽,免费软件)

相关问题:

参考:PHP语法错误;以及如何解决这些问题?

严格标准:非静态方法[<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中被静态调用?”