关于mysql:reference-这个错误在php中意味着什么?

Reference - What does this error mean in PHP?

这是什么?

这是一些关于在编写PHP时可能遇到的警告、错误和注意事项的答案,并且不知道如何修复。这也是一个社区wiki,因此邀请每个人参与添加和维护此列表。

为什么会这样?

堆栈溢出时,像"headers already sent"或"calling a member of a non-object"这样的问题经常出现。这些问题的根本原因总是相同的。因此,这些问题的答案通常会重复这些问题,然后向操作员展示他/她的特定案例中要更改的行。这些答案不会给站点增加任何价值,因为它们只适用于OP的特定代码。其他具有相同错误的用户无法轻松地从中读取解决方案,因为它们太本地化了。这很可悲,因为一旦您了解了根本原因,修复错误就变得微不足道了。因此,这个列表试图用一种通用的方法来解释这个解决方案。

我该怎么办?

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

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

名单

  • 什么也看不见。页面是空的和白色的。(也称为死亡白页/屏幕)
  • 代码不运行/我的PHP代码的某些部分似乎是输出的
  • 警告:无法修改标题信息-标题已发送
  • 警告:mysql_fetch_array()要求参数1为resource,布尔值为a.k.a。警告:mysql_fetch_array():提供的参数不是有效的mysql结果资源a.k.a。警告:mysqli_num_rows()要求参数1为mysqli_结果,给定布尔值(或类似的变化)
  • 警告:【函数】要求参数1为资源,给定布尔值
  • 警告:【函数】:无法打开流:【原因】
  • 警告:打开basedir限制生效
  • 警告:被零除
  • 警告:非法字符串偏移量"xxx"
  • 分析错误:语法错误,意外的"["
  • 分析错误:语法错误,意外的t_xxx
  • 分析错误:语法错误,意外的t_和u空白
  • 分析错误:语法错误,意外的t paamayim u nekudotayim
  • 分析错误:语法错误,意外的'require_once'(t_require_once),需要函数(t_函数)
  • 分析错误:语法错误,意外的t_变量
  • 致命错误:允许的内存大小为xxx字节已用完(尝试分配xxx字节)
  • 致命错误:调用成员函数…关于非对象
  • 致命错误:调用未定义的函数xxx
  • 致命错误:无法重新声明xxx
  • 致命错误:无法在写入上下文中使用函数返回值
  • 致命错误:aaa::bbb()的声明必须与ccc::bbb()的声明兼容
  • 致命错误:不在对象上下文中时使用$this
  • 注意:数组到字符串的转换
  • 注意:试图获取非对象错误的属性
  • 注意:未定义的变量
  • 注意:未定义的索引
  • 注意:未定义的偏移量xxx[参考]
  • 注意:未初始化的字符串偏移量:xxx
  • 注意:使用未定义的常量xxx-假定为'xxx'
  • MySQL:您的SQL语法有错误;请查看与您的MySQL服务器版本相对应的手册,以获得在附近使用的正确语法…在线…
  • 严格标准:不应静态调用非静态方法[]
  • 警告:函数要求参数x为布尔值/string/integer
  • HTTP错误500-内部服务器错误

此外,参见

  • 引用-这个符号在PHP中是什么意思?


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

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

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

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

1
2
3
4
5
<html>
    <?php session_start(); ?>
    <head>My Page
</html>
...

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

您可以通过在触发警告的代码之前浏览这些行来解决这个问题,并检查它的输出位置。将任何发送代码的头段移动到该代码之前。

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

如果您的文件中有多个代码块,那么它们之间不应该有任何空格。(注意:如果有自动构造的代码,则可能有多个块)

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

相关问题:

  • 已由PHP发送的邮件头
  • 所有关于stackoverflow的php"headers already sent"问题
  • 字节顺序标记
  • 什么PHP函数创建输出?


致命错误:调用成员函数…关于非对象

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

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

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

一个典型的例子是

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

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

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

如果即使是->prepare失败,那么您的$pdo数据库句柄对象也没有被传递到当前的作用域中。找到它的定义。然后将其作为参数传递、存储为属性或通过全局范围共享。

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

1
2
3
4
5
if ($someCondition) {
    $myObj = new MyObj();
}
// ...
$myObj->someMethod();

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

相关问题:

  • 对非对象调用成员函数
  • 列出所有php"致命错误:调用成员函数…关于stackoverflow的"非对象"问题

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

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

如果启用了错误日志记录,您将在错误日志中找到具体的错误消息。这通常会出现在一个名为"php_errors.log"的文件中,或者出现在一个中心位置(如许多Linux环境中的/var/log/apache2),或者出现在脚本本身的目录中(有时在共享托管环境中使用)。

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

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

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

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

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

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

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

相关问题:

  • PHP的死亡白屏
  • 死亡的白屏!
  • PHP不显示错误消息
  • PHP发出500个错误-这是在哪里记录的?
  • 如何在PHP中获取有用的错误消息?
  • 所有关于stackoverflow的php"死亡白页"问题

相关错误:

  • 分析错误:语法错误,意外的t_xxx
  • 致命错误:调用成员函数…关于非对象
  • 代码不运行/我的PHP代码的某些部分似乎是输出的


注意:未定义的索引

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

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

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

阵列中不存在spinach1,导致触发E_NOTICE

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

1
2
3
4
5
6
7
$data = array('foo' => '42', 'bar');
if (array_key_exists('spinach', $data)) {
    echo $data['spinach'];
}
else {
    echo 'No key spinach in the array';
}

如果您有类似的代码:

1
2
3
4
<?php echo $_POST['message']; ?>
<form method="post" action="">
    <input type="text" name="message">
    ...

那么,当第一次加载此页面时,不会设置$_POST['message'],您将得到上述错误。只有提交表单并再次运行此代码时,数组索引才会存在。您通常通过以下方式检查:

1
2
3
if ($_POST)  ..  // if the $_POST array is not empty
// or
if ($_SERVER['REQUEST_METHOD'] == 'POST') ..  // page was requested with POST

相关问题:

  • 参考:"注意:未定义变量"和"注意:未定义索引"
  • 所有关于stackoverflow的php"notice:undefined index"问题
  • http://php.net/数组


警告:mysql_fetch_array()要求参数1为资源,给定布尔值

首先:

Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.

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

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

您需要检查mysql_query返回的结果

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

相关问题:

  • mysql_fetch_array()要求参数1为资源,select中给定布尔值
  • 所有"mysql_fetch_array()都要求参数1为资源,布尔值给定"stackoverflow问题

相关错误:

  • 警告:【函数】要求参数1为资源,给定布尔值

其他的mysql*函数也希望将mysql结果资源作为参数,因此会产生相同的错误。


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

$this是php中的一个特殊变量,不能赋值。如果在不存在的上下文中访问它,则会出现此致命错误。

此错误可能发生:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Foo {
       protected $var;
       public function __construct($var) {
           $this->var = $var;
       }

       public static function bar () {
           // ^^^^^^
           echo $this->var;
           //   ^^^^^
       }
    }

    Foo::bar();

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

  • 如果类方法中的代码被复制到一个正常函数或只是全局范围中,并保留$this特殊变量。如何修复:检查代码并用不同的替换变量替换$this

  • 相关问题:

  • 将非静态方法调用为static:php致命错误:不在对象上下文中时使用$this
  • 复制代码:致命错误:不在对象上下文中使用$this
  • StackOverflow上的所有"不在对象上下文中使用$this"问题

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

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

    示例1-条件函数声明

    1
    2
    3
    4
    5
    6
    7
    $someCondition = false;
    if ($someCondition === true) {
        function fn() {
            return 1;
        }
    }
    echo fn(); // triggers error

    在这种情况下,不会声明fn(),因为$someCondition不是真的。

    示例2-函数声明中的函数

    1
    2
    3
    4
    5
    6
    7
    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=致命+错误%3a+调用+到+未定义+函数

    分析错误:语法错误,意外的t_xxx

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

    相关问题:

    • 参考:php解析/语法错误;如何解决它们?
    • 分析错误:语法错误:意外的""
    • 分析错误:语法错误,我的PHP代码中出现意外的文件结尾
    • 分析错误:语法错误,在-fix中出现意外的"<"?
    • 分析错误:语法错误,意外的'?'

    有关更多帮助,请参阅:

    • http://phpcodechecker.com/—它确实为您的语法问题提供了一些更有用的解释。

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

    这通常在直接与empty一起使用函数时发生。

    例子:

    1
    2
    3
    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)

    相关问题:

    • 致命错误:无法使用函数返回值


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

    这个错误经常是因为您忘记正确地转义传递给MySQL查询的数据。

    不做什么的例子("坏主意"):

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

    此代码可以包含在一个带有要提交的表单的页面中,并带有一个URL,如http://example.com/edit.php?ID=10(编辑10号杆)

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

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

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

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

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

    文档:

    • 如何在PHP中防止SQL注入?
    • mysql_real_escape_string()
    • mysqli_real_escape_string()
    • "bobby tables"xkcd漫画中的SQL注入是如何工作的?
    • 围绕mysql_real_escape_string()的SQL注入


    致命错误:允许的内存大小为xxx字节已用完(尝试分配xxx字节)

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

    首先要做的是最小化脚本所需的内存量。例如,如果您正在将一个大文件读取到一个变量中,或者正在从数据库中提取许多记录,并将它们全部存储在一个数组中,那么可能会占用大量内存。将代码改为逐行读取文件或一次提取一个数据库记录,而不将它们全部存储在内存中。这确实需要有一点概念上的意识,知道在幕后发生了什么,以及何时数据存储在内存中,而不是其他地方。

    如果在脚本不进行内存密集型工作时发生此错误,则需要检查代码以查看是否存在内存泄漏。memory_get_usage功能是你的朋友。

    相关问题:

    • StackOverflow上的所有"致命错误:允许内存大小为XXX字节已用完"问题

    分析错误:语法错误,意外的t_和u空白

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

    错误案例:

    这将导致Unexpected T_ENCAPSED_AND_WHITESPACE

    1
    2
    echo"This is a double-quoted string with a quoted array key in $array['key']";
    //---------------------------------------------------------------------^^^^^

    可能的修复:

    在双引号字符串中,php将允许不加引号地使用数组键字符串,并且不会发出E_NOTICE。因此,上述内容可以写成:

    1
    2
    echo"This is a double-quoted string with an un-quoted array key in $array[key]";
    //------------------------------------------------------------------------^^^^^

    整个复杂数组变量和键可以括在{}中,在这种情况下,它们应该被引用以避免E_NOTICE。PHP文档为复杂变量推荐了这种语法。

    1
    2
    3
    4
    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']}";

    当然,上述任何一种方法的替代方法都是将数组变量连接在一起,而不是对其进行插值:

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

    有关参考信息,请参见php字符串手册页中的变量解析部分。


    分析错误:语法错误,意外的t paamayim u nekudotayim

    范围解析操作符也被希伯来语称为"paamayim nekudotayim"??????????????????????。表示"双冒号"或"双点两次"。

    如果不小心在代码中放入了::,则通常会发生此错误。

    相关问题:

    • 参考:php解析/语法错误;如何解决它们?
    • 两个冒号在PHP中是什么意思?
    • PHP中的::(双冒号)和->(箭头)有什么区别?
    • 意外的t paamayim nekudotayim,需要t s分隔符

    文档:

    • 作用域解析运算符(::)


    警告:【函数】:无法打开流:【原因】

    当您调用一个文件时,通常是由includerequirefopen调用,而php找不到该文件或没有足够的权限加载该文件。

    这种情况可能有多种原因:

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

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

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

    或:

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

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

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

    相关问题:

    • 故障排除清单:无法打开流

    相关错误:

    • 警告:打开basedir限制生效


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

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

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

    请考虑以下代码:

    PHP类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php

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

    索引文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php

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

    do_stuff();
    do_stuff();

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


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

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

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

    当代码中使用了一个标记,并且该标记似乎是一个常量,但未定义该名称的常量时,就会出现此通知。

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

    例如:

    1
    2
    3
    4
    5
    // Wrong
    echo $array[key];

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

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

    1
    2
    3
    4
    5
    // Wrong
    echo varName;

    // Right
    echo $varName;

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

    1
    2
    3
    4
    5
    // Wrong
    $foo = fasle;

    // Right
    $foo = false;

    当您试图访问由该库定义的常量时,它也可能是所需的PHP扩展名或库丢失的迹象。

    相关问题:

    • PHP错误消息"notice:use of undefined constant"是什么意思?


    注意:未定义的变量

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

    一个典型的例子是

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

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

    正确的方法是在使用变量之前设置它,即使它只是一个空字符串

    1
    2
    3
    4
    5
    $counter = 0;
    foreach ($items as $item) {
        // do something with item
        $counter++;
    }

    相关问题:

    • stackoverflow上的所有php"notice:undefined variable"问题
    • php:"notice:未定义变量"、"notice:未定义索引"和"notice:未定义偏移量"
    • 参考:什么是变量范围,从哪里可以访问哪些变量,什么是"未定义变量"错误?

    分析错误:语法错误,意外的t_变量

    可能的情况

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

    Parse error: syntax error, unexpected T_VARIABLE on line x

    我在尝试什么

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

    回答

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

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

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

    这个错误消息意味着在文件的第x行中,PHP解释器希望看到一个左括号,但是它遇到了一个名为T_VARIABLE的东西。这个东西叫做token。这是PHP解释器表达程序不同基本部分的方式。当解释器读取一个程序时,它会将您所写的内容转换成一个令牌列表。在程序中放置变量的任何地方,解释器列表中都有AT_VARIABLE标记。

    可读性好:解析器令牌列表

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

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

    PHP错误报告

    另外,最好使用一个IDE,它可以让您在键入时知道解析错误。你可以使用:

  • Netbeans(一款漂亮的免费软件)(我认为最好)
  • phpstorm(Gordon叔叔喜欢这个:p,付费计划,包含专有和免费软件)
  • Eclipse(Beauty and the Beast,免费软件)
  • 相关问题:

    • 参考:php解析/语法错误;如何解决它们?

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

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

    以你为例,是想展示每封来自$string的信。

    1
    2
    3
    4
    5
    $string = 'ABCD';
    for ($i=0, $len = strlen($string); $i <= $len; $i++){
        echo"$string[$i]
    "
    ;
    }

    以上示例将生成(在线演示):

    1
    2
    3
    4
    5
    A
    B
    C
    D
    Notice: Uninitialized string offset: 4 in XXX on line X

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

    类似的错误:

    • 非法字符串偏移量"选项1"


    警告:打开basedir限制生效

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

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

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

    修复方法通常是更改php配置,相关设置称为open_basedir

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

    相关问题:

    • 打开"basedir限制"生效。文件(/)不在允许的路径内:
    • 所有php"warning:open-basedir restriction in effect"在stackoverflow上查询


    分析错误:语法错误,意外的"["

    这个错误有两个变量:

    变异1

    1
    $arr = [1, 2, 3];

    这个数组初始值设定项语法只在php 5.4中引入;它将在之前的版本上引发语法分析器错误。如果可能,请升级安装或使用旧语法:

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

    另请参见手册中的此示例。

    变异2

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

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

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

    另请参见手册中的此示例。


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

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

    非对象通知的一个典型示例是

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

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

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

    这个例子简化了很多。通常,这样的通知会发出未经检查的返回值信号,例如当库返回NULL时,如果对象不存在,或者只是一个意外的非对象值(例如,在xpath结果中,具有意外格式的json结构、具有意外格式的xml等),但代码不会检查这种情况。

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

    通过检查错误条件和/或变量与期望匹配,可以很容易地防止这种情况。这里有一个带有domxpath示例的通知:

    1
    2
    $result  = $xpath->query("//*[@id='detail-sections']/div[1]");
    $divText = $result->item(0)->nodeValue; # Notice: Trying to get property of non-object

    问题是访问第一个项目的nodeValue属性(字段),而没有检查它是否存在于$result集合中。相反,通过为代码操作的对象分配变量,使代码更显式是值得的:

    1
    2
    3
    4
    5
    6
    7
    $result  = $xpath->query("//*[@id='detail-sections']/div[1]");
    $div     = $result->item(0);
    $divText ="-/-";
    if (is_object($div)) {
        $divText = $div->nodeValue;
    }
    echo $divText;

    相关错误:

    • 注意:未定义的索引
    • 致命错误:调用成员函数…关于非对象


    警告:【函数】要求参数1为资源,给定布尔值

    (更一般的警告变体:mysql_fetch_array()要求参数1为资源,布尔值给定)

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

    There are two resource types used in the MySQL module. The first one is the link identifier for a database connection, the second a resource which holds the result of a query.

    curl扩展定义了另外两种资源类型:

    ... a cURL handle and a cURL multi handle.

    var_dumped时,值如下:

    1
    2
    3
    4
    $resource = curl_init();
    var_dump($resource);

    resource(1) of type (curl)

    这就是所有的资源,一个特定类型的数字标识符((1)((curl))。

    您携带这些资源,并将它们传递给不同的函数,对于这些函数,这样的资源意味着某种东西。通常,这些函数在后台分配特定的数据,而资源只是一个引用,用于在内部跟踪这些数据。

    "……"期望参数1为资源,布尔给定的"错误通常是未经检查的操作的结果,该操作本应创建资源,但返回false"。例如,fopen函数具有以下描述:

    Return Values

    Returns a file pointer resource on success, or FALSE on error.

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

    1
    $fp = fopen(...);

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

    1
    2
    3
    4
    $fp   = fopen(...);
    $data = fread($fp, 1024);

    Warning: fread() expects parameter 1 to be resource, boolean given

    您总是需要错误地检查试图分配资源并可能失败的函数的返回值:

    1
    2
    3
    4
    5
    6
    7
    8
    $fp = fopen(...);

    if (!$fp) {
        trigger_error('Failed to allocate resource');
        exit;
    }

    $data = fread($fp, 1024);

    相关错误:

    • 警告:mysql_fetch_array()要求参数1为资源,给定布尔值

    警告:非法字符串偏移量"xxx"

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

    例子:

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

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


    代码不运行/我的PHP代码的某些部分似乎是输出的

    如果您没有看到任何来自PHP代码的结果和/或您在网页中看到了文本PHP源代码输出的一部分,那么您可以非常确定您的PHP实际上没有得到执行。如果在浏览器中使用VIEWSOURCE,则可能会看到整个PHP源代码文件。由于PHP代码嵌入到标记中,浏览器将尝试将这些标记解释为HTML标记,结果可能看起来有点混乱。

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

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

    >除非重新配置,否则可以配置所有内容。

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

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

    这将完全绕过您可能正在运行的任何Web服务器,并且不会解释该文件。您需要访问Web服务器上文件的URL,可能如下所示:

    1
    http://localhost/my/file.php

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

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


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

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

    • 示例见mysql_connect("localhost","user","pw")上的手册页。好的。

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

      • 你不使用密码获得访问权限是很少见的——这是警告时发生的事情:(using password: NO)说。
      • 只有本地测试服务器通常允许使用用户名root,没有密码和test数据库名称进行连接。好的。

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

      • 用户名和密码区分大小写,不忽略空白。如果您的密码包含元字符,如$,请将其转义,或将密码放在单引号中。好的。

      • 大多数共享宿主提供程序都预先声明了与Unix用户帐户相关的MySQL帐户(有时只是前缀或额外的数字后缀)。有关模式或文档,请参阅文档,以及设置密码的CPanel或任何接口。好的。

      • 请参阅mysql手册中关于使用命令行添加用户帐户的内容。当作为管理员用户连接时,您可以发出如下查询:CREATE USER 'username'@'localhost' IDENTIFIED BY 'newpassword';好的。

      • 或者使用管理员、工作台或任何其他图形工具来创建、检查或更正帐户详细信息。好的。

      • 如果你不能修改你的证书,那么要求互联网"请帮助"将没有效果。只有您和您的宿主提供商具有诊断和修复问题的权限和足够的访问权限。好的。

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

      • 直接从您的Web服务器上的ssh控制台检查这个。从本地开发客户机到共享托管服务器的测试很少有意义。好的。

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

      • 如果您的mysql/mariadb服务器监听不同的端口,则使用"servername:3306"。好的。

      • 如果失败了,那么可能存在防火墙问题。(主题外,不是编程问题。无法进行远程猜测。)好的。

    • 当使用诸如DB_USERDB_PASSWORD之类的常量时,请检查它们是否被实际定义。好的。

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

      • 确认您的E.G.xy/db-config.php实际上包括在其中,以及什么。好的。

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

      • 一对usernamepassword+好的。

      • 每个mysql/mariadb帐户都可以有一组附加的权限。好的。

      • 它们可以限制允许您连接的数据库、连接可能来自哪个客户机/服务器以及允许哪些查询。好的。

      • 因此,如果您没有从特定表或EDOCX1(23/EDOCX1)(24)或更常见的DELETE的权限,那么"拒绝访问"警告也可能出现在mysql_query呼叫中。好的。

      • 当使用管理帐户通过如下查询连接每个命令行客户端时,可以调整帐户权限:GRANT ALL ON yourdb.* TO 'username'@'localhost';好的。

    • 如果警告首先出现在Warning: mysql_query(): Access denied for user ''@'localhost'中,那么您可能有一个php.ini预配置的帐户/密码对。好的。

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

      • 通常这是一个提供者配置。因此,请联系他们的支持人员了解不匹配之处。好的。

    • 查找共享宿主提供程序的文档:好的。

      • 例如hostgator、godaddy、1和1、digitalOcean、bluehost、dreamhost、mediatemple、ixwebhosting、lunarhosting,或者只搜索你的'。好的。

      • 否则,请通过他们的支持渠道咨询您的网站托管提供商。好的。

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

    • 你的libmysql客户端版本可能不会是兼容的与数据库服务器。normally MySQL服务器和mariadb可以reached与PHP编译中的司机。如果你有一个自定义的设置,或是outdated PHP版本,和一个更newer数据库服务器,或明显outdated一前的版本mismatch可以防止连接。(好的,你要investigate你自己。没有人能想你的设置)。

      /好的。

    [参考文献:

    /好的。

    • serverfault:拒绝访问MySQL数据库的"根"的"名牌"的计算机
    • 警告:_ mysql connect():拒绝访问
    • 警告:_ mysql select db()_拒绝访问用户""""localhost"(用password:嗯)
    • 拒绝访问用户的"根"@"localhost"以phpMyAdmin

    Btw, you probably don't want to use mysql_* functions anymore. Newcomers often migrate to mysqli, which however is just as tedious. Instead read up on PDO and prepared statements.
    $db = new PDO("mysql:host=localhost;dbname=testdb","username","password");

    Ok.

    好的。


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

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

    1
    2
    3
    4
    $arr = array('foo', 'bar');

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

    数组不能简单地由echo或字符串连接,因为结果定义不好。PHP将使用字符串"array"代替数组,并触发通知,指出这可能不是预期的,您应该在这里检查代码。你可能想要这样的东西:

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

    或者循环数组:

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

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


    警告:被零除

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

    1
    $value = @(2 / 0);

    但是,与任何警告一样,最好的方法是跟踪警告的原因并解决它。警告的原因将来自尝试除以0的任何实例、等于0的变量或由于结果将为"未定义"而未赋值的变量(因为null==0)。

    若要更正此警告,应重写表达式以检查该值是否为0,如果为0,请执行其他操作。如果该值为零,则不应将该值除,或将该值更改为1,然后再除,这样除的结果等于只除以附加变量。

    1
    2
    3
    4
    5
    6
    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
    }

    相关问题:

    • 警告:被零除
    • 警告:在php和mysql上按零除
    • WordPress主题中的零错误除法
    • 如何抑制"零除"错误
    • 如何捕捉被零除?


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

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

    例子:

    1
    2
    3
    4
    5
    class HTML {
       public function br() {
          echo '';
       }
    }

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

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

    1
    error_reporting(E_ALL & ~E_STRICT);

    由于对于php 5.4.0及以上版本,E_STRICT包含在E_ALL中。但这是不明智的。解决方案是将您的预期静态功能定义为实际的static

    1
    2
    3
    public static function br() {
      echo '';
    }

    或者常规调用函数:

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

    相关问题:

    • 如何解决"在php 5.4中不应该静态调用非静态方法xxx:xxx()?

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

    HTTP状态代码500和典型的Apache或浏览器警告是一个非常广泛的消息。这不是实际的错误。要找出这是Web服务器配置错误(.htaccess还是PHP致命错误,您必须查看error.log

    您通常可以在下面找到WebServers error.log

    • Linux服务器上的/var/log/apache2,通常用于本地和虚拟主机。
    • /var/www/_user12345_/logs或类似的共享托管计划。通常每个htdocs/文件夹旁边都有一个logs/目录。
    • 用于apache+php的wamp/xampp发行版的C:\xampp\apache\logs\error.log
    • 或者,只需使用文件搜索功能来定位任何称为"error.log"的内容。或者查看您的apache httpd.conf及其ErrorLog指令。
    • 用于nginx的/var/log/nginx/nginx_error.log
    • 用于IIS的C:\inetpub\logs\LogFiles

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

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

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

    如果没有配置为使用系统或Apache日志记录机制,您可能还需要查看php的error.log。一般来说,只需让error_displayerror_reporting显示具体的错误就可以简单地保留默认值。毕竟,HTP500的catch all页面只是PHP死亡白屏的一个变体。

    参见:

    • 500 PHP文件内部服务器错误,而不是HTML
    • 如何让PHP显示错误而不是给我500个内部服务器错误
    • 如何在iis7上显示和记录PHP错误?
    • 如何修复WordPress中的500内部服务器错误

    致命错误:[traita]和[traitb]在[classc]的组合中定义相同的属性([$x])。

    当一个类尝试use多个特性时发生,其中两个或多个特性用相同的名称定义了一个特性,并且该特性具有不同的初始值。

    例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    trait TraitA
    {
        public $x = 'a';
    }
    trait TraitB
    {
        public $x = 'b';
    }
    class ClassC
    {
        use TraitA, TraitB;
    }

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

    相关问题:

    • PHP特性:如何解决属性名冲突?
    • 特征-与父类的属性冲突


    警告:函数()要求参数x为布尔值(或整数、字符串等)

    如果将错误类型的参数传递给函数(而PHP无法自动转换),则会引发警告。此警告标识问题是哪个参数,以及预期的数据类型。解决方案:将指示的参数更改为正确的数据类型。

    例如,此代码:

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

    结果如下:

    PHP Warning: substr() expects parameter 1 to be string, array given