参考-这个错误在PHP中意味着什么?

这是什么?

这是一些关于您在编程PHP时可能遇到的警告、错误和通知的答案,但不知道如何修复它们。这也是一个社区Wiki,因此邀请每个人参与添加和维护此列表。

这是为什么?

"标题已发送""调用非对象的成员"这样的问题经常在Stack Overflow上弹出。这些问题的根本原因总是相同的。因此,这些问题的答案通常会重复这些问题,然后显示OP在特定情况下要更改的行。这些答案不会为网站增加任何价值,因为它们仅适用于OP的特定代码。有相同错误的其他用户无法轻松从中读出解决方案,因为他们过于本地化。这很可悲,因为一旦你理解了根本原因,修复错误是微不足道的。因此,本列表试图以通用的方式解释解决方案。

我该在这里做什么?

如果您的问题已被标记为此问题的重复,请在下面找到您的错误消息并将修复应用于您的代码。答案通常包含进一步的链接以进行调查,以防仅从一般答案中无法清楚。

如果您想贡献,请添加您“最喜欢的”错误消息、警告或通知,每个答案一个,简短描述它的含义(即使它只是在其手册页上突出显示术语),可能的解决方案或调试方法以及现有有价值的问答列表。此外,请随时改进任何现有的答案。

该名单

另外,请参阅:

264215 次浏览

致命错误:在非对象上调用成员函数…

类似于xyz->method()的代码,其中xyz不是对象,因此不能调用method

这是一个致命错误,它将停止脚本(前向兼容性通知:从PHP 7开始,它将成为一个可捕获的错误)。

大多数情况下,这是代码缺少错误条件检查的迹象。在调用其方法之前,请验证对象实际上是一个对象。

典型的例子是

// ... some code using PDO$statement = $pdo->prepare('invalid query', ...);$statement->execute(...);

在上面的示例中,无法准备查询,prepare()false分配给$statement。尝试调用execute()方法将导致致命错误,因为false是“非对象”,因为值是布尔值。

找出为什么您的函数返回的是布尔值而不是对象。例如,检查$pdo对象中发生的最后一个错误。有关如何调试的详细信息将取决于如何处理有关特定函数/对象/类的错误。

如果连->prepare都失败了,那么您的$pdo数据库处理对象没有传递到当前作用域。找到它的定义位置。然后将其作为参数传递、存储为属性或通过全局作用域共享它。

另一个问题可能是有条件地创建一个对象,然后尝试调用该条件块之外的方法。例如

if ($someCondition) {$myObj = new MyObj();}// ...$myObj->someMethod();

通过尝试在条件块之外执行方法,可能无法定义您的对象。

相关问题:

警告:mysql_fetch_array()期望参数1是资源,给定布尔值

首先是:

请不要在新代码中使用#0函数。它们不再维护并被正式弃用。看到红盒子了吗?改为了解准备好的声明,并使用PDOMySQLi-这篇文章将帮助您决定哪个。如果您选择PDO,这里有一个很好的教程


当您尝试从mysql_query的结果中获取数据但查询失败时,就会发生这种情况。

这是一个警告,不会停止脚本,但会使您的程序出错。

您需要检查mysql_query返回的结果

$res = mysql_query($sql);if (!$res) {die(mysql_error());}// after checking, do the fetch

相关问题:

相关错误:

其他mysql*函数也需要一个MySQL结果资源作为参数,出于同样的原因会产生同样的错误。

警告:无法修改标头信息-标头已发送

当您的脚本尝试向客户端发送HTTP标头但之前已经有输出时,会发生这种情况,这导致标头已经发送到客户端。

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

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

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

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

您可以通过遍历触发警告的代码之前行并检查它的输出位置来解决此问题。将任何标头发送代码移动到该代码之前。

一个经常被忽视的输出是PHP结束?>之后的新行。当?>是文件中的最后一件事时省略?>被认为是一种标准做法。同样,此警告的另一个常见原因是打开<?php之前有一个空格、行或不可见字符,导致Web服务器发送标头和空格/换行符,因此当PHP开始解析时将无法提交任何标头。

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

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

相关问题:

解析错误:语法错误,意外T_XXX

当你有#0代币在意想不到的地方,不平衡(多余的)括号,使用短标签没有激活它在php.ini,等等。

相关问题:

更多帮助见:

解析错误:语法错误,意外T_PAAMAYIM_NEKUDOTAYIM

范围解析运算符也被称为“Paamayim Nekudotayim”,来自希伯来语 פעמיים נקודתיים . 意思是“双冒号”。

如果您无意中将::放入代码中,通常会发生此错误。

相关问题:

文档:

致命错误:XXX字节的允许内存大小耗尽(尝试分配XXX字节)

没有足够的内存来运行您的脚本。PHP已达到内存限制并停止执行它。此错误是致命的,脚本停止。内存限制的值可以在php.ini文件中配置,也可以在脚本中使用ini_set('memory_limit', '128 M');(这将覆盖php.ini中定义的值)。内存限制的目的是防止单个PHP脚本吞噬所有可用内存并导致整个Web服务器停机。

首先要做的是尽量减少脚本所需的内存量。例如,如果您要将大文件读取到变量中,或者从数据库中获取许多记录并将它们全部存储在数组中,那可能会使用大量内存。将代码更改为逐行读取文件或一次获取一个数据库记录,而无需将它们全部存储在内存中。这确实需要对幕后发生的事情以及数据何时存储在内存和其他地方有一点概念上的认识。

如果此错误发生在您的脚本没有进行内存密集型工作时,您需要检查您的代码以查看是否存在内存泄漏。#0函数是您的朋友。

相关问题:

致命错误:不在对象上下文中使用$this

#0是PHP中的一个特殊变量无法分配。如果在不存在的上下文中访问它,则会给出此致命错误。

可能会出现此错误:

  1. 如果静态调用非静态方法。例子:

    class Foo {protected $var;public function __construct($var) {$this->var = $var;}
    public static function bar () {// ^^^^^^echo $this->var;//   ^^^^^}}
    Foo::bar();

    如何修复:再次检查你的代码,$this只能在对象上下文中使用,永远不应该在静态方法中使用。此外,静态方法不应该访问非静态属性。使用self::$static_property访问静态属性。

  2. 如果类方法的代码已复制到普通函数中,或者只是全局范围保留$this特殊变量。
    如何修复:查看代码并将$this替换为不同的替换变量。

相关问题:

  1. 将非静态方法调用为静态:PHP致命错误:不在对象上下文中使用$this
  2. 复制代码:致命错误:不在对象上下文中使用$this
  3. 全部"不在对象上下文中使用$this"Stackoverflow上的问题

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

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

示例:

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

这是因为#0是一个语言构造而不是一个函数,它不能在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)

相关问题:

“注意:未定义索引”或“警告:未定义数组键”

当您尝试通过数组中不存在的键访问数组时发生。

Undefined Index通知的典型示例是(demo

$data = array('foo' => '42', 'bar');echo $data['spinach'];echo $data[1];

spinach1都不存在于数组中,导致触发#2。在PHP 8.0中,这是一个E_WARNING。

解决方案是在访问索引之前确保索引或偏移量存在。这可能意味着您需要在程序中修复bug以确保这些索引在您期望它们时确实存在。或者这可能意味着您需要使用#0#1测试索引是否存在:

$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// orif ($_SERVER['REQUEST_METHOD'] == 'POST') ..  // page was requested with POST

相关问题:

MySQL:您的SQL语法有错误;请检查与您的MySQL服务器版本相对应的手册,以获取在… at line…附近使用的正确语法。

此错误通常是因为您忘记正确转义传递给MySQL查询的数据。

没有要做的事情(“坏主意”)的一个例子:

$query = "UPDATE `posts` SET my_text='{$_POST['text']}' WHERE id={$_GET['id']}";mysqli_query($db, $query);

此代码可以包含在带有要提交的表单的页面中,其URL例如http://example.com/edit.php?id=10(用于编辑帖子n°10)

如果提交的文本包含单引号会发生什么?$query将以:

$query = "UPDATE `posts` SET my_text='I'm a PHP newbie' WHERE id=10';

当这个查询被发送到MySQL时,它会抱怨语法错误,因为中间有一个额外的单引号。

为了避免此类错误,您必须总是在查询中使用之前对数据进行转义。

在SQL查询中使用之前转义数据也非常重要,因为如果不这样做,您的脚本将打开SQL注入。SQL注入可能会导致记录、表或整个数据库的更改、丢失或修改。这是一个非常严重的安全问题!

文档:

警告:open_basedir限制生效

此警告可以与与文件和目录访问相关的各种函数一起出现。它警告有关配置问题。

当它出现时,这意味着已禁止访问某些文件。

警告本身不会破坏任何内容,但大多数情况下,如果阻止文件访问,脚本将无法正常工作。

修复通常是改变php配置,相关设置称为#0

有时会使用错误的文件或目录名称,然后修复使用正确的名称。

相关问题:

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

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

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

有时,暂时启用错误显示可能更直接。然后白页将显示错误消息。请注意,访问网站的每个人都可以看到这些错误。

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

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

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

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

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

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

相关问题:

相关错误:

注意:使用未定义的常量XXX-假设'XXX'

或者,在PHP 7.2或更高版本中:

警告:使用未定义的常量XXX-假设为'XXX'(这将在PHP的未来版本中引发错误)

或者,在PHP 8.0或更高版本中:

错误:未定义的常量XXX

当代码中使用令牌并且看起来是常量,但未定义该名称的常量时,就会发生这种情况。

此通知最常见的原因之一是未能引用用作关联数组键的字符串。

例如:

// Wrongecho $array[key];
// Rightecho $array['key'];

另一个常见原因是变量名前面缺少$(美元)符号:

// Wrongecho varName;
// Rightecho $varName;

或者你可能拼错了其他常量或关键字:

// Wrong$foo = fasle;
// Right$foo = false;

当您尝试访问由该库定义的常量时,它也可能是缺少所需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 undefinedreturn "${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++;}

相关问题:

致命错误:调用未定义的函数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中删除,请查找有关原因的信息,因为它可能不再需要。

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

如果出现错别字,请修复错别字。

相关问题:

警告:[函数]:打开流失败:[理由]

当您通常通过includerequirefopen调用文件并且PHP找不到该文件或没有足够的权限加载该文件时,就会发生这种情况。

这可能由于各种原因而发生:

  • 文件路径错误
  • 文件路径是相对的
  • 包含路径错误
  • 权限限制太严
  • SELinux正在生效
  • 还有更多…

一个常见的错误是不使用绝对路径。这可以通过使用完整路径或魔术常数(如__DIR__dirname(__FILE__))轻松解决:

include __DIR__ . '/inc/globals.inc.php';

或:

require dirname(__FILE__) . '/inc/globals.inc.php';

确保使用正确的路径是解决这些问题的一个步骤,这也可能与不存在的文件、文件系统的权限阻止访问或PHP本身打开base dir限制有关。

快速解决此问题的最佳方法是按照以下故障排除清单进行操作。

相关问题:

相关错误:

致命错误:无法重新声明类[类名]

致命错误:无法重新声明【功能名称】

这意味着您要么使用了两次相同的函数/类名,需要重命名其中一个,要么是因为您使用了requireinclude,而您应该使用require_onceinclude_once

当一个类或函数在PHP中声明时,它是不可变的,以后不能用新值声明。

考虑以下代码:

class.php

<?php
class MyClass{public function doSomething(){// do stuff here}}

index.php

<?php
function do_stuff(){require 'class.php';$obj = new MyClass;$obj->doSomething();}
do_stuff();do_stuff();

第二次调用do_stuff()会产生上面的错误。通过将require更改为require_once,我们可以确定包含MyClass定义的文件只会加载一次,并且可以避免错误。

解析错误:语法错误,意外T_ENCAPSED_AND_WHITESPACE

在PHP 8.0及更高版本中,消息改为:

语法错误,意外的字符串内容“”,期待“-”或标识符或变量或数字

当整个复杂变量构造未包含在{}中时,尝试在双引号字符串内引用带有引用的关键的数组值进行插值时,最常遇到此错误。

错误情况:

这将导致Unexpected 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_NOTICEPHP留档建议复杂变量使用此语法。

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字符串手册页中关于变量解析的部分

警告:[函数]期望参数1是资源,给定布尔值

警告:mysql_fetch_array()期望参数1是资源,给定布尔值的更一般的变体)

资源是PHP中的类型(如字符串、整数或对象)。资源是一个不透明的blob,它本身没有固有的有意义的值。资源特定于一组特定的PHP函数或扩展并由其定义。例如,MySQL扩展定义了两种资源类型

MySQL模块中使用了两种资源类型。第一种是数据库连接的链接标识符,第二种是保存查询结果的资源。

cURL扩展定义了另一个两种资源类型

…一个cURL句柄和一个cURL多句柄。

var_dumped时,值如下所示:

$resource = curl_init();var_dump($resource);
resource(1) of type (curl)

这就是大多数资源,某种类型((curl))的数字标识符((1))。

你随身携带这些资源并将它们传递给不同的函数,这些资源对这些函数有意义。通常,这些函数在后台分配某些数据,资源只是他们用来在内部跟踪这些数据的引用。


…期望参数1是资源,给定布尔值”错误通常是未经检查的操作的结果,该操作应该创建资源,但返回了false。例如,#1函数有这样的描述:

返回值

成功时返回文件指针资源,错误时返回FALSE

所以在这段代码中,$fp将是resource(x) of type (stream)false

$fp = fopen(...);

如果您不检查fopen操作是成功还是失败,因此$fp是有效资源还是false并将$fp传递给另一个需要资源的函数,您可能会得到上述错误:

$fp   = fopen(...);$data = fread($fp, 1024);
Warning: fread() expects parameter 1 to be resource, boolean given

您总是需要错误检查尝试分配资源<强烈>可能会失败的函数的返回值:

$fp = fopen(...);
if (!$fp) {trigger_error('Failed to allocate resource');exit;}
$data = fread($fp, 1024);

相关错误:

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

可能的情况

我似乎找不到我的代码哪里出错了。这是我的完整错误:

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

我在尝试什么

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

答案

解析错误:程序语法的问题,例如在语句末尾留下分号,或者像上面的情况一样,缺少.运算符。解释器在遇到解析错误时停止运行您的程序。

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

你该怎么做是仔细检查错误所在的行是否有任何简单的错误。

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

好读:解析器令牌列表

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

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

error_reporting(E_ALL);

php错误报告

此外,使用IDE是一个好主意,它会让您在键入时知道解析错误。您可以使用:

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

相关问题:

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

如名称所示,当您最有可能尝试迭代或从具有不存在键的数组中查找值时,就会发生此类错误。

想想你,正试图显示$string的每一个字母

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

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

ABCDNotice: Uninitialized string offset: 4 in XXX on line X

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

类似错误:

警告:除以零

警告消息“除以零”是新PHP开发人员最常问的问题之一。此错误不会导致异常,因此,一些开发人员偶尔会通过在表达式前添加错误抑制运算符@来抑制警告。例如:

$value = @(2 / 0);

但是,就像任何警告一样,最好的方法是追踪警告的原因并解决它。警告的原因将来自您尝试除以0、等于0的变量或未分配的变量(因为NULL==0)的任何实例,因为结果将是“未定义”。

要纠正此警告,您应该重写表达式以检查值是否不是0,如果是,请执行其他操作。如果值为零,您要么不应该除法,要么应该将值更改为1,然后除法,因此除法的结果相当于仅除以附加变量。

if ( $var1 == 0 ) { // check if var1 equals zero$var1 = 1; // var1 equaled zero so change var1 to equal one instead$var3 = ($var2 / $var1); // divide var1/var2 ie. 1/1} else {$var3 = ($var2 / $var1); // if var1 does not equal zero, divide}

相关问题:

严格标准:非静态方法<类>::<方法>不应静态调用

当您尝试调用类的非静态方法时发生,因为它是静态的,并且您的error_reporting()设置中也有E_STRICT标志。

示例:

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

HTML::br()$html::br()

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

error_reporting(E_ALL & ~E_STRICT);

因为对于PHP 5.4.0及更高版本,E_STRICT包含在E_ALL[参考]中。但这并不可取。解决方案是将您预期的静态函数定义为实际的static

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

或者按照惯例调用函数:

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

相关问题:

解析错误:语法错误,意外的'['

这个错误有两个变量:

变式1

$arr = [1, 2, 3];

这种数组初始化器语法仅在PHP 5.4中引入;它会在之前的版本上引发解析器错误。如果可能,升级您的安装或使用旧语法:

$arr = array(1, 2, 3);

参见手册中的这个例子

变式2

$suffix = explode(',', 'foo,bar')[1];

PHP 5.4中还引入了数组取消引用函数结果。如果无法升级,您需要使用(临时)变量:

$parts = explode(',', 'foo,bar');$suffix = $parts[1];

参见手册中的这个例子

代码不运行/看起来我的PHP代码的一部分被输出

如果你没有看到PHP代码的任何结果,并且/或者你在网页中看到了PHP源代码的部分文字输出,那么你可以非常确定你的PHP实际上没有被执行。如果你在浏览器中使用View Source,你可能会看到整个PHP源代码文件的原样。由于PHP代码嵌入在<?php ?>标记中,浏览器会尝试将这些解释为超文本标记语言标记,结果可能看起来有点混乱。

要实际运行PHP脚本,您需要:

  • 执行您的脚本的Web服务器
  • 将文件扩展名设置为. php,否则Web服务器不会将其解释为. php*
  • 通过Web服务器访问您的. php文件

*除非您重新配置它,否则一切都可以配置。

最后一个特别重要。只需双击该文件就可能会在您的浏览器中使用以下地址打开它:

file://C:/path/to/my/file.php

这完全绕过了您可能运行的任何Web服务器,并且文件没有得到解释。您需要访问Web服务器上文件的URL,可能类似于:

http://localhost/my/file.php

您可能还想检查您是否使用短开放标记<?而不是<?php,并且您的PHP配置已关闭短开放标记。

另见PHP代码没有被执行,而是代码显示在页面上

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

如果您尝试将数组视为字符串,则会发生这种情况:

$arr = array('foo', 'bar');
echo $arr;  // Notice: Array to string conversion$str = 'Something, ' . $arr;  // Notice: Array to string conversion

数组不能简单地echo'或与字符串连接,因为结果没有很好地定义。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}

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

注意:尝试获取非对象错误的属性

当您在没有对象的情况下尝试访问对象的属性时发生。

非标的通知的一个典型例子是

$users = json_decode('[{"name": "hakre"}]');echo $users->name; # Notice: Trying to get property of non-object

在这种情况下,$users是一个数组(所以不是对象),它没有任何属性。

这类似于访问数组的不存在索引或键(参见注意:未定义索引)。

这个例子很简单。大多数情况下,这样的通知会发出未经检查的返回值的信号,例如,当库返回NULL时,如果对象不存在,或者只是一个意外的非对象值(例如,在Xpath结果中,具有意外格式的JSON结构,具有意外格式的XML等),但代码不会检查这样的条件。

由于这些非对象通常会进一步处理,因此在调用非对象上的对象方法时通常会发生致命错误(请参阅:致命错误:在非对象上调用成员函数…),从而停止脚本。

它可以通过检查错误条件和/或变量是否符合期望来轻松预防。这里有一个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;

相关错误:

警告:非法字符串偏移量'XXX'

当您尝试使用方括号语法访问数组元素时会发生这种情况,但您是在字符串上而不是在数组上执行此操作,因此操作显然是都说不通

示例:

$var = "test";echo $var["a_key"];

如果您认为变量应该是一个数组,请查看它来自哪里并在那里解决问题。

警告:mysql_connect():用户名@主机访问被拒绝

当您连接到具有无效或丢失凭据(用户名/密码)的MySQL/MariaDB服务器时,会显示此警告。所以这通常是没有代码问题,而是服务器配置问题。

更多参考:

顺便说一句,你可能不想使用#0功能不再。新人经常迁移到mysqli,然而这同样乏味。相反,请阅读PDO和准备好的声明
$db = new PDO("mysql:host=localhost;dbname=testdb", "username", "password");

致命错误:[TraitA]和[TraitB]在[ClassC]的组合中定义了相同的属性([$x])

当类尝试#0多重特征时发生,其中两个或多个Trait具有相同名称的定义了一个属性,并且属性具有不同的初始值。

示例:

<?phptrait TraitA{public $x = 'a';}trait TraitB{public $x = 'b';}class ClassC{use TraitA, TraitB;}

问题:虽然可以解决竞争方法之间的冲突,但目前还没有语法可以解决两个竞争属性之间的冲突。目前唯一的解决方案是重构;即避免产生致命错误的属性名称之间的冲突。


相关问题:

警告:函数()期望参数X是布尔值(或整数、字符串等)

如果将错误类型的参数传递给函数——并且PHP无法自动转换它——则会抛出警告。此警告会识别出问题的参数以及预期的数据类型。解决方案:将指示的参数更改为正确的数据类型。


例如这段代码:

echo substr(["foo"], 23);

此输出中的结果:

PHP警告:substr()期望参数1是字符串,给定数组

HTTP错误500-内部服务器错误

HTTP状态代码500和典型的Apache或浏览器警告是一个非常广泛的信息。这不是实际的错误。要弄清楚它是Web服务器错误配置(.htaccess)还是PHP致命错误,您必须查看#1

Apache错误页面:

您通常可以在以下位置找到Web服务器日志:

  • /var/log/apache2在Linux服务器上,通常用于本地和虚拟主机。
  • /var/www/_user12345_/logs或类似的共享主机计划。
    通常每个htdocs/文件夹旁边都有一个logs/目录。
  • C:\xampp\apache\logs\error.log表示Apache+PHP的WAMP/XAMPP发行版。
  • 或者,只需使用文件搜索功能来定位任何称为“error.log”的东西。
    或者查看您的Apachehttpd.conf及其ErrorLog指令。
  • /var/log/nginx/nginx_error.logNginx
  • C:\inetpub\logs\LogFilesIIS
  • 幸运的是,这仍然不常见,但journalctl -r -u apache2.service也可以保存Linux设置的部分日志。

这是一个文本文件。搜索与错误时间最匹配的条目,并使用错误消息的重要部分(从“PHP错误:…”到“in line…”)进行进一步的谷歌搜索。

[Mon 22:10] [:error] [pid 12345] [client 127.0.0.1] FastCGI: server "/fcgi/p73" stderr: PHP message:#1variable $_JSON['pokestop_lng'] in filyfile.php on line 845

对于FPM设置,您通常会在此处看到致命的PHP错误。而旧的mod_php(共享主机)配置通常混合在警告和通知中(通常也值得检查)。

如果没有配置为使用系统或Apache日志记录机制,您可能还想看看PHP的error.log。通常,保留默认值并启用error_display+error_reporting来显示具体错误会更简单。HTTP 500的全能页面毕竟只是PHP的死亡白屏的变体。

另见:

警告:coun():参数必须是数组或实现Countable的对象

不言自明;传递给count()函数的参数必须是可数的,通常是数组。

可能的问题是传递了一个标量值,例如字符串或整数,或者一个没有实现Countable接口的对象。在有问题的变量上使用var_dump()可以显示是否是这种情况。

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

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

使用箭头函数将为此示例抛出错误:

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中添加

不建议使用:不建议使用带花括号的数组和字符串偏移访问语法

字符串偏移量和数组元素可以通过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脚本,它试图机械地修复这个问题。

致命错误:未定义的类常量

此错误表示您尝试使用不存在的类常数。与其他“未定义”通知和警告不同,这是一个致命错误,将立即停止脚本。

首先要检查的应该是排版错误。确认常量是在类中定义的,并且是使用适当的命名空间调用它的。还确认已包含所有适当的文件来解析常量。

致命错误:未捕获的类型错误: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)的文件中,所以在向其传递string时会出现类型错误:

致命错误:未捕获的类型错误:乘法():参数#1($x)必须是整数类型,字符串在…

这个关于3v4l.org的例子

致命错误:超过XX秒的最大执行时间

每个PHP页面请求或脚本调用都会测量php代码的执行时间。如果达到配置的限制,脚本将通过此消息中止。

请注意,时间不要通常包括在PHP“外部”发生的事情,例如等待数据库结果的时间,或使用shell_exec执行的外部程序等,但当PHP在Windows上运行时例外,其中测量的时间是“时钟时间”,确实包括这些外部等待时间。

常见原因

  • 无限循环。编写错误的whiledo...whilefor循环可能永远不会完成,这意味着PHP永远在持续运行。即使是foreach循环也可以是无限的,例如,如果循环到迭代器对象发生器函数上。
  • 大型数据集。即使你的循环不是无限的,如果它正在做大量的工作,如果它正在处理大量的结果,它可能需要太长的时间才能完成。

更改限制

如果你知道你有一个缓慢的过程,你可以配置时间限制:

  • 在php.ini,使用max_execution_time设置
  • 当脚本运行时,使用set_time_limit功能。请注意,调用this会将测量时间重置为零,因此set_time_limit(10);表示“允许10更多秒,无论脚本已经花费了多长时间”。

这两种机制都应该有秒数,或者特殊值0,意思是“无限制”。设置“无限制”对于真正打算在后台永远运行的命令行脚本最有用;对于网页,最好设置一些有限值,即使它非常大,以防止代码中的错误导致整个系统无响应。