【问题标题】:Reference - What does this error mean in PHP?参考 - 这个错误在 PHP 中是什么意思?
【发布时间】:2018-03-30 15:08:04
【问题描述】:

这是什么?

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

这是为什么?

像"Headers already sent" 或"Calling a member of a non-object" 这样的问题经常在 Stack Overflow 上弹出。这些问题的根本原因总是相同的。因此,这些问题的答案通常会重复它们,然后向 OP 显示在其特定情况下要更改哪一行。这些答案不会为站点增加任何价值,因为它们仅适用于 OP 的特定代码。其他具有相同错误的用户无法轻松地从中读取解决方案,因为他们过于本地化。这很可悲,因为一旦您了解了根本原因,修复错误就变得微不足道了。因此,此列表试图以通用的方式解释解决方案。

我应该在这里做什么?

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

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

名单

另见:

【问题讨论】:

标签: php debugging error-handling warnings custom-error-handling


【解决方案1】:

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

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

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

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

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

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

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

一个经常被忽视的输出是 PHP 关闭 ?&gt; 之后的新行。当 ?&gt; 是文件中的最后一件事时,忽略它被认为是一种标准做法。同样,此警告的另一个常见原因是开头 &lt;?php 前面有一个空格、行或不可见字符,导致 Web 服务器发送标头和空格/换行符,因此当 PHP 开始解析时不会可以提交任何标题。

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

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

相关问题:

【讨论】:

  • 如果您使用的是 WordPress,请检查主题文件。当我将网站升级到新版本的 WordPress 时,我无法更新主题,因为它已经好几年没有更新了。这个问题就出现了。原来functions.php文件有不止一个 ?> 块之间有空格。
  • @RoyLeban “如果您的文件中包含多个块......”我不确定这意味着什么。什么是“块”?一个块是否由&lt;?php ?&gt; 组成,因此“多个块”将是&lt;?php ?&gt; &lt;?php ?&gt;?
  • 如果可能,请在 PHP.ini 配置文件中打开“输出缓冲”功能。它是用来解决这个问题的。它发送的 html 文件保存在输出缓冲区中,只发送给客户端脚本停止后,因此如果在不同位置发出两个标头,则旧标头将被新标头替换。
【解决方案2】:

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

发生在类似于xyz-&gt;method() 的代码中,其中xyz 不是对象,因此无法调用method。

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

这通常表明代码缺少对错误条件的检查。在调用它的方法之前验证一个对象实际上是一个对象。

typical 示例是

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

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

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

如果即使-&gt;prepare 失败,那么您的$pdo 数据库句柄对象didn't get passed into the current scope。找到它被定义的地方。然后将其作为参数传递,将其存储为属性,或通过全局范围共享。

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

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

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

相关问题:

【讨论】:

    【解决方案3】:

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

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

    如果您启用了错误日志记录,您将在错误日志中找到具体的错误消息。这通常位于名为“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 或any other method that affects the configuration before runtime 中执行此操作。

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

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

    相关问题:

    相关错误:

    【讨论】:

    • error_reporting(~0); 为什么不-1?这就是 ~0 的计算结果,并且不那么神秘。
    • 我认为两者都同样神秘。 ~0 是更明确的 IMO:否定空位集,即。 e.启用 所有 标志。 -1 并不像 C 中的 strpos() 那样代表“未找到”,而是作为一个设置了所有标志的位集,因为 -1 是二进制 1111'1111'1111'1111(32 位)。
    • 糟糕,1111'1111'1111'1111 确实是 16 位,但我希望你明白我的意思。
    • 你可能得到这个的另一个原因是因为你在你的 PHP 代码中输入了return false;
    【解决方案4】:

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

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

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

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

    spinach 和 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
    

    相关问题:

    【讨论】:

    • 我倾向于使用if(!empty($_POST['message'])){ //do stuff }
    【解决方案5】:

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

    首先:

    Please, don't use mysql_* functions in new code。它们不再维护and are officially deprecated。看到red box?改为了解prepared statements,并使用PDO 或MySQLi - this article 将帮助您决定哪个。如果你选择 PDO,here is a good tutorial。


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

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

    您需要检查mysql_query返回的结果

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

    相关问题:

    相关错误:

    同样期望 MySQL 结果资源作为参数的其他 mysql* 函数将出于同样的原因产生同样的错误。

    【讨论】:

    • 只是一个注释。如果mysql_query 还不够糟糕,那么在上面加上or die 就是雪上加霜。
    • 我遇到的问题是$res = mysql_query($query)如果查询成功则返回1,所以它被认为是真的。因此,当将mysql_query 的结果传递给mysql_fetch_array() 时,通知会显示。
    • @mboy 对于 SELECT、SHOW、DESCRIBE、EXPLAIN 和其他返回结果集的语句,mysql_query() 成功时返回资源,错误时返回 FALSE。对于其他类型的 SQL 语句,INSERT、UPDATE、DELETE、DROP 等,mysql_query() 在成功时返回 TRUE,在错误时返回 FALSE。
    • @xdazz 这就是我面临的问题,插入更新返回 TRUE,所以我无法摆脱这个错误mysql_fetch_array() expects parameter 1 to be resource, boolean given in select 请参阅 - gist.github.com/romelemperado/93af4cdbd44ebf3a07cbfa0e3fc539d7 有什么建议可以摆脱这个错误吗?跨度>
    • @mboy mysql_fetch_array() 用于选择查询,用于插入和更新,您不需要获取结果集(并且没有结果集让您获取)。
    【解决方案6】:

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

    $this is a special variable in 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 Fatal error: Using $this when not in object context
    2. 复制代码:Fatal error: Using $this when not in object context
    3. All "Using $this when not in object context" Questions on Stackoverflow

    【讨论】:

    • 您可能还想提及它是如何使用闭包工作的(即使在非静态方法中)以及它在 5.4 中是如何“修复”的。
    • @hakre 我说的是闭包内的静态调用。喜欢$closure = function() { self::method(); }。
    • @KendallHopkins:这是一个不同的错误:“致命错误:无法访问 self:: 当没有活动的类范围时” 但是使用$this,您可以触发定制“致命错误:不在对象上下文中使用 $this”:$closure = function() { $this-&gt;method(); };
    【解决方案7】:

    致命错误:调用未定义函数 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
    

    在这种情况下,fn 只会在 createFn() 被调用时被声明。请注意,随后对createFn() 的调用将触发有关重新声明现有函数的错误。

    您也可能会在 PHP 内置函数中看到这一点。尝试在the official manual中搜索该函数,并检查它属于哪个“扩展”(PHP模块),以及哪些版本的PHP支持它。

    如果缺少扩展,请安装该扩展并在 php.ini 中启用它。有关您的函数出现的扩展,请参阅 PHP 手册中的安装说明。您还可以使用包管理器启用或安装扩展(例如,Debian 或 Ubuntu 中的 apt,Red Hat 或 CentOS 中的 yum ) 或共享主机环境中的控制面板。

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

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

    如有错别字,请改正错字。

    相关问题:

    【讨论】:

      【解决方案8】:

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

      当T_XXX token 出现在意想不到的地方、括号不平衡(多余的)、使用短标签而不在 php.ini 中激活它等等时,就会发生这种情况。

      相关问题:

      如需进一步帮助,请参阅:

      【讨论】:

        【解决方案9】:

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

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

        例子:

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

        这是因为empty 是一种语言结构而不是一个函数,因此在 PHP 5.5 之前的版本中不能使用表达式作为其参数来调用它。在 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).

        相关问题:

        【讨论】:

          【解决方案10】:

          MySQL:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取正确的语法,以便在 ... 行 ...

          此错误通常是因为您忘记正确转义传递给 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 注入可能导致记录、表或整个数据库的更改、丢失或修改。这是一个非常严重的安全问题!

          文档:

          【讨论】:

          • 此外,如果您不这样做,您的网站将被机器人自动入侵
          • @gladoscc 点击“编辑”并修改答案。我知道它可以改进。
          • 或者使用准备好的sql查询。
          【解决方案11】:

          解析错误:语法错误,意外的 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_NOTICE。 The PHP documentation 建议对复杂变量使用此语法。

          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']}";
          

          当然,上述 any 的替代方法是连接数组变量而不是插值:

          echo "This is a double-quoted string with an array variable". $array['key'] . " concatenated inside.";
          //----------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^
          

          有关参考,请参阅the PHP Strings manual page中的变量解析部分

          【讨论】:

            【解决方案12】:

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

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

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

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

            相关问题:

            【讨论】:

              【解决方案13】:

              警告:[功能]:打开流失败:[原因]

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

              发生这种情况的原因有很多:

              • 文件路径错误
              • 文件路径是相对的
              • 包含路径错误
              • 权限过于严格
              • SELinux 生效
              • 还有更多...

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

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

              或:

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

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

              快速解决此问题的最佳方法是遵循下面的故障排除清单。

              相关问题:

              相关错误:

              【讨论】:

                【解决方案14】:

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

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

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

                相关问题:

                文档:

                【讨论】:

                • 触发此错误的最简单方法是运行a()::b; 或$a=::;。
                【解决方案15】:

                注意:未定义的变量

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

                一个典型的例子是

                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++;
                }
                

                相关问题:

                【讨论】:

                  【解决方案16】:

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

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

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

                  当在代码中使用了一个标记并且看起来是一个常量,但没有定义该名称的常量时,就会出现此通知。

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

                  例如:

                  // Wrong
                  echo $array[key];
                  
                  // Right
                  echo $array['key'];
                  

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

                  // Wrong
                  echo varName;
                  
                  // Right
                  echo $varName;
                  

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

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

                  当您尝试访问由该库定义的常量时,这也可能表明缺少所需的 PHP 扩展或库。

                  相关问题:

                  【讨论】:

                  • 我想说最常见的原因是在变量而不是数组前面忘记了 $。
                  【解决方案17】:

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

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

                  这意味着您要么使用了相同的函数/类名两次并且需要重命名其中一个,要么是因为您使用了 require 或 include,而您应该使用 require_once 或 @987654326 @。

                  当一个类或函数在 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定义的文件只会被加载一次,从而避免了错误。

                  【讨论】:

                  • 使用自动加载是否值得一提,PSR-4 甚至现在已弃用的PSR-0 等标准通过让您无需使用 require/include 来摆脱这一点(bar a一些奇怪的边缘情况)。
                  【解决方案18】:

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

                  可能的情况

                  我似乎找不到我的代码出错的地方。这是我的完整错误:

                  解析错误:语法错误,第 x 行出现意外的 T_VARIABLE

                  我正在尝试什么

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

                  回答

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

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

                  你应该做的是仔细检查错误所在的线条是否有任何简单的错误。

                  该错误消息意味着在文件的第 x 行中,PHP 解释器期望看到一个左括号,但它却遇到了名为 T_VARIABLE 的内容。那个T_VARIABLE 被称为token。它是 PHP 解释器表达程序不同基本部分的方式。当解释器读入一个程序时,它会将你写的内容翻译成一个标记列表。无论您在程序中的何处放置变量,解释器列表中都会有一个T_VARIABLE 标记。

                  Good read: List of Parser Tokens

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

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

                  error_reporting(E_ALL);
                  

                  PHP error reporting

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

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

                  相关问题:

                  【讨论】:

                    【解决方案19】:

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

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

                    考虑一下你,正在尝试显示来自$string 的每封信

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

                    上面的例子会生成(online demo):

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

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

                    类似的错误:

                    【讨论】:

                      【解决方案20】:

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

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

                      非对象通知的典型示例是

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

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

                      这类似于访问数组中不存在的索引或键(请参阅Notice: Undefined Index)。

                      这个例子被大大简化了。大多数情况下,这样的通知表示未检查的返回值,例如当一个库返回NULL,如果一个对象不存在或只是一个意外的非对象值(例如,在 Xpath 结果中,具有意外格式的 JSON 结构,具有意外格式的 XML 等)但代码不检查这样的条件。

                      由于通常会进一步处理这些非对象,因此在停止脚本时调用非对象上的对象方法(请参阅:Fatal error: Call to a member function ... on a non-object)通常会发生致命错误。

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

                      相关错误:

                      【讨论】:

                      • json_decode 现在默认返回stdclass 的实例,因此示例代码将实际工作。
                      • @HugoZink:它确实(并且总是)返回了一个数组用于该示例:3v4l.org/SUDe0 - 您还可以为您的写作提供参考,即 "json_decode 现在返回一个默认情况下stdclass 的实例" ?我在更新日志中找不到。
                      • 根据json_decode上的PHP手册页,assoc参数默认设置为false。此参数决定函数是否返回 stdclass 而不是关联数组。
                      • json_decode('[{"name": "hakre"}]', true) 将返回一个数组,否则返回一个 stdclass 对象
                      【解决方案21】:

                      警告:open_basedir 限制生效

                      与文件和目录访问相关的各种功能可能会出现此警告。它会警告配置问题。

                      出现时,表示部分文件已被禁止访问。

                      警告本身不会破坏任何东西,但如果阻止文件访问,脚本通常无法正常工作。

                      修复方法一般是更改PHP configuration,相关设置称为open_basedir。

                      有时使用了错误的文件或目录名,解决方法是使用正确的。

                      相关问题:

                      【讨论】:

                      • 这种情况最常发生在共享主机上,人们通常不会将自己锁定在目录之外:-)
                      【解决方案22】:

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

                      这个错误有两个变体:

                      变体 1

                      $arr = [1, 2, 3];
                      

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

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

                      另请参阅手册中的this example。

                      变体 2

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

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

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

                      另请参阅手册中的this example。

                      【讨论】:

                        【解决方案23】:

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

                        (Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given 的更一般的变体)

                        资源是 PHP 中的 type(如字符串、整数或对象)。资源是一个不透明的 blob,它本身没有固有的有意义的价值。资源是特定于一组 PHP 函数或扩展并由其定义的。比如Mysql扩展defines two resource types:

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

                        cURL 扩展定义了另一个two resource types:

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

                        var_dumped 时,值如下所示:

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

                        大多数资源都是特定类型 ((curl)) 的数字标识符 ((1))。

                        您携带这些资源并将它们传递给不同的功能,这些资源对这些功能意味着什么。通常,这些函数会在后台分配某些数据,而资源只是它们用来在内部跟踪这些数据的引用。


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

                        返回值

                        成功时返回文件指针资源,错误时返回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);
                        

                        相关错误:

                        【讨论】:

                          【解决方案24】:

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

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

                          例子:

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

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

                          【讨论】:

                            【解决方案25】:

                            代码不运行/输出了我的 PHP 代码的部分内容

                            如果您没有从您的 PHP 代码中看到任何结果和/或您在网页中看到部分文字 PHP 源代码输出,那么您可以确定您的 PHP 并未真正执行。如果您在浏览器中使用查看源代码,您可能会看到整个 PHP 源代码文件。由于 PHP 代码嵌入在 &lt;?php ?&gt; 标签中,浏览器会尝试将其解释为 HTML 标签,结果可能看起来有些混乱。

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

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

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

                            最后一个特别重要。只需双击该文件,即可在浏览器中使用如下地址打开它:

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

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

                            http://localhost/my/file.php
                            

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

                            另见PHP code is not being executed, instead code shows on the page

                            【讨论】:

                              【解决方案26】:

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

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

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

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

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

                              【讨论】:

                                【解决方案27】:

                                警告:mysql_connect(): 用户 'name'@'host' 的访问被拒绝

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

                                • 有关示例,请参见 mysql_connect("localhost", "user", "pw") 上的手册页。

                                • 检查您是否实际使用了$username 和$password。

                                  • 不使用密码即可获得访问权限的情况并不常见 - 警告时会发生这种情况:(using password: NO)。
                                  • 通常只有本地测试服务器允许使用用户名root、无密码和test 数据库名称进行连接。

                                  • 您可以使用命令行客户端测试它们是否真的正确:
                                    mysql --user="username" --password="password" testdb

                                  • 用户名和密码区分大小写,空格不被忽略。如果您的密码包含像$ 这样的元字符,请将它们转义,或将密码放入single quotes。

                                  • 大多数共享主机提供商预先声明与 unix 用户帐户相关的 mysql 帐户(有时只是前缀或额外的数字后缀)。请参阅文档以获取模式或文档,以及用于设置密码的 CPanel 或任何界面。

                                  • 使用命令行查看Adding user accounts 上的 MySQL 手册。当以管理员用户身份连接时,您可以发出如下查询:
                                    CREATE USER 'username'@'localhost' IDENTIFIED BY 'newpassword';

                                  • 或使用Adminer 或WorkBench 或任何其他图形工具来创建、检查或更正帐户详细信息。

                                  • 如果您无法修复您的凭据,那么请求互联网“请帮助”将无效。只有您和您的托管服务提供商拥有诊断和修复问题的权限和足够的访问权限。

                                • 使用您的提供商提供的主机名验证您是否可以访问数据库服务器:
                                  ping dbserver.hoster.example.net

                                  • 直接从您的网络服务器上的 SSH 控制台检查此项。从本地开发客户端到共享托管服务器的测试几乎没有意义。

                                  • 通常您只希望服务器名称为"localhost",它通常在可用时使用本地命名套接字。其他时候你可以尝试"127.0.0.1" 作为后备。

                                  • 如果您的 MySQL/MariaDB 服务器侦听不同的端口,然后使用 "servername:3306"。

                                  • 如果失败,则可能是防火墙问题。 (题外话,不是编程问题。不可能进行远程猜测。)

                                • 当使用 constants 时,例如DB_USER 或 DB_PASSWORD,检查它们是否真的是 defined。

                                  • 如果你得到一个"Warning: Access defined for 'DB_USER'@'host'" 和一个"Notice: use of undefined constant 'DB_PASS'",那就是你的问题。

                                  • 验证您的例如xy/db-config.php 实际上也包括在内。

                                • 检查是否正确设置了GRANT权限。

                                  • username+password 对是不够的。

                                  • 每个 MySQL/MariaDB 帐户都可以附加一组权限。

                                  • 这些可以限制您可以连接到哪些数据库,连接可能来自哪个客户端/服务器,以及允许哪些查询。

                                  • 因此,如果您没有来自特定表的SELECT 或INSERT/UPDATE 的权限,那么“访问被拒绝”警告也可能会出现在mysql_query 调用中,并且更常见的是DELETE任何东西。

                                  • 当每个命令行客户端使用 admin 帐户 连接时,您可以adapt account permissions 使用如下查询:
                                    GRANT ALL ON yourdb.* TO 'username'@'localhost';

                                • 如果警告首先显示为Warning: mysql_query(): Access denied for user ''@'localhost',那么您可能有一个php.ini-preconfigured account/password pair。

                                  • 检查mysql.default_user= 和mysql.default_password= 是否具有有意义的值。

                                  • 通常这是提供程序配置。因此,如果不匹配,请联系他们的支持人员。

                                • 查找您的共享主机提供商的文档:

                                • 请注意,您可能还耗尽了可用的连接池。对于太多并发连接,您将收到拒绝访问警告。 (您必须调查设置。这是一个跑题的服务器配置问题,而不是编程问题。)

                                • 您的 libmysql 客户端版本可能与数据库服务器不兼容。通常,可以使用在驱动程序中编译的 PHP 访问 MySQL 和 MariaDB 服务器。如果您有自定义设置、过时的 PHP 版本、更新的数据库服务器或明显过时的数据库服务器 - 那么版本不匹配可能会阻止连接。 (不,你必须自己调查。没人能猜到你的设置)。

                                更多参考资料:

                                顺便说一句,您可能不想使用mysql_* functions anymore。新人经常迁移到mysqli,但这同样乏味。而是阅读PDO and prepared statements。
                                $db = new PDO("mysql:host=localhost;dbname=testdb", "username", "password");

                                【讨论】:

                                • mysql 允许通过 php-ini 设置自动连接,然后给出相同的错误消息,并带有不同的命令前缀,例如“警告:mysql_query(): Access denied for user ''@'localhost' (using password: NO) in ...” - 请注意。
                                • 哈,完全忘记了! (可能最后一次使用 PHP3 左右..)
                                【解决方案28】:

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

                                在 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 for this change 链接到 PHP script,它试图以机械方式修复此问题。

                                【讨论】:

                                  【解决方案29】:

                                  警告:除以零

                                  警告消息“除以零”是 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
                                  }
                                  

                                  相关问题:

                                  【讨论】:

                                  • 如果它是 0 则设置为 1 将停止错误,但这真的比你说不应该使用的抑制更好吗(我同意)?我建议大多数时候可能会返回一些其他消息或值。
                                  • 在本例中,如果$var1 == 0,那么您只需将$var3 设置为$var2。即使不这样做,也根本不需要 else,因为在两种情况下分配是相同的,所以没有 else 并在 if 之外分配
                                  【解决方案30】:

                                  严格标准:非静态方法[::]不应被静态调用

                                  当您尝试在类上调用非静态方法时发生,因为它是静态的,并且您的 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 [ref] 中。但这不是可取的。解决方案是将您想要的静态函数定义为实际的 static :

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

                                  或按惯例调用函数:

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

                                  相关问题:

                                  【讨论】:

                                    猜你喜欢
                                    相关资源
                                    最近更新 更多