1229

这是什么?

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

为什么是这样?

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

我应该在这里做什么?

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

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

名单

另见:

4

37 回答 37

295

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

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

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

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

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

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

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

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

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

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

相关问题:

于 2012-10-07T15:21:03.630 回答
199

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

发生类似于xyz->method()where xyzis not an object 的代码,因此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();

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

相关问题:

于 2012-10-07T15:11:00.930 回答
124

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

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

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

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

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

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

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

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

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

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

相关问题:

相关错误:

于 2012-10-07T21:06:14.763 回答
108

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

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

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

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

两者spinach1都不存在于数组中,导致一个E_NOTICE被触发。在 PHP 8.0 中,这是一个 E_WARNING。

解决方案是在访问该索引之前确保索引或偏移量存在。这可能意味着您需要修复程序中的错误,以确保这些索引在您期望的时候确实存在。或者这可能意味着您需要使用array_key_existsor测试索引是否存在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">
    ...

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

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

相关问题:

于 2012-10-07T16:53:29.207 回答
89

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

首先也是最重要的:

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


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

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

您需要检查mysql_queryby返回的结果

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

相关问题:

相关错误:

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

于 2012-10-07T15:20:41.277 回答
82

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

$this是 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. Stackoverflow 上的所有“不在对象上下文中使用 $this”的问题
于 2012-10-07T15:52:06.820 回答
77

致命错误:调用未定义的函数 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 内置函数中看到这一点。尝试在官方手册中搜索该函数,并查看它属于哪个“扩展”(PHP模块),以及PHP的哪些版本支持它。

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

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

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

如果有错别字,请更正错别字。

相关问题:

于 2012-10-08T14:43:16.253 回答
73

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

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

相关问题:

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

于 2012-10-07T15:22:38.873 回答
71

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

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

例子:

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

这是因为empty它是一种语言结构而不是函数,在 5.5 之前的 PHP 版本中不能使用表达式作为其参数来调用它。在 PHP 5.5 之前,参数 toempty()必须是variable,但 PHP 5.5+ 允许任意表达式(例如函数的返回值)。

empty,尽管它的名字,实际上并不检查变量是否为“空”。相反,它会检查变量是否不存在,或者== false. 表达式(如is_null(null)示例中的)将始终被视为存在,因此这里empty仅检查它是否等于 false。您可以将empty()此处替换为!,例如if (!is_null(null)),或明确比较为 false ,例如if (is_null(null) == false)

相关问题:

于 2012-10-07T16:16:35.923 回答
64

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 注入可能导致记录、表或整个数据库的更改、丢失或修改。这是一个非常严重的安全问题!

文档:

于 2012-10-07T17:45:04.700 回答
55

解析错误:语法错误,意外的 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 将允许使用数组键字符串unquoted,并且不会发出E_NOTICE. 所以上面可以写成:

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

整个复杂数组变量和键可以包含在 中{},在这种情况下,它们应该被引用以避免E_NOTICE. PHP 文档建议对复杂变量使用这种语法。

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

于 2012-12-18T14:52:32.023 回答
53

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

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

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

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

相关问题:

于 2012-10-07T15:36:31.607 回答
46

警告:[功能]:无法打开流:[原因]

当您通常通过 调用文件时会发生这种情况includerequire或者fopenPHP 找不到该文件或没有足够的权限来加载该文件。

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

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

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

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

或者:

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

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

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

相关问题:

相关错误:

于 2012-10-10T13:14:49.320 回答
45

注意:未定义的变量

当您尝试使用以前未定义的变量时会发生这种情况。

一个典型的例子是

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

相关问题:

于 2012-10-08T09:14:58.090 回答
45

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

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

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

相关问题:

文档:

于 2012-10-07T15:29:54.690 回答
44

注意:使用未定义的常量 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 扩展或库。

相关问题:

于 2012-10-07T22:06:37.380 回答
43

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

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

这意味着您要么两次使用相同的函数/类名并需要重命名其中一个,要么是因为您已经使用过requireinclude应该在哪里使用require_onceor include_once

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

考虑以下代码:

类.php

<?php

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

索引.php

<?php

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

do_stuff();
do_stuff();

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

于 2012-12-14T13:18:39.567 回答
36

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

可能的情况

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

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

我正在尝试什么

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

回答

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

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

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

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

好读:解析器令牌列表

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

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

error_reporting(E_ALL);

PHP错误报告

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

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

相关问题:

于 2013-03-21T04:31:16.187 回答
35

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

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

考虑一下你,正试图展示来自$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并回显D当它到达 时4,它会抛出一个偏移错误。

类似错误:

于 2013-07-13T14:00:02.723 回答
34

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

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

非对象通知的典型示例是

$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;

相关错误:

于 2014-10-26T11:20:33.417 回答
29

警告:open_basedir 限制生效

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

当它出现时,表示某些文件已被禁止访问。

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

修复通常是更改PHP 配置,调用相关设置open_basedir

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

相关问题:

于 2012-10-07T19:44:32.163 回答
29

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

此错误有两个变体:

变体 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];

另请参阅手册中的此示例

于 2014-03-11T04:55:52.383 回答
23

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

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

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

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

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

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

编辑时var_dump,值如下所示:

$resource = curl_init();
var_dump($resource);

resource(1) of type (curl)

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

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


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

返回值

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

所以在这段代码中,$fp要么是 aresource(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);

相关错误:

于 2012-12-28T09:51:52.383 回答
22

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

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

例子:

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

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

于 2014-12-28T16:40:40.100 回答
20

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

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

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

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

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

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

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

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

http://localhost/my/file.php

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

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

于 2014-06-26T05:51:40.513 回答
19

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

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

$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
}

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

于 2014-07-01T09:42:50.003 回答
18

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

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

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

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

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

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

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

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

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

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

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

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

    • 直接在您的网络服务器上通过 SSH 控制台进行检查。从本地开发客户端到共享托管服务器的测试很少有意义。

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

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

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

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

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

    • 验证您的 egxy/db-config.php是否实际包含在内,等等。

  • 检查正确设置的GRANT权限

    • username有一个+对是不够的password

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

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

    • mysql_query因此,如果您无权访问SELECT特定表或INSERT/UPDATE以及更常见的DELETE任何内容,则“访问被拒绝”警告也可能会出现在调用中。

    • 您可以在每个命令行客户端使用管理员帐户连接时调整帐户权限,查询如下:
      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_*函数了。新人经常迁移到mysqli,但这同样乏味。而是阅读PDO 和准备好的语句
$db = new PDO("mysql:host=localhost;dbname=testdb", "username", "password");

于 2015-09-20T16:40:26.730 回答
14

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

{}在 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脚本。

于 2019-12-03T14:02:44.483 回答
13

警告:除以零

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

相关问题:

于 2014-02-02T05:12:07.517 回答
8

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

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

例子 :

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();

相关问题:

于 2014-02-21T18:52:49.970 回答
8

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

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

此示例使用箭头函数将引发错误:

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

于 2019-06-18T23:03:53.150 回答
7

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

HTTP 状态代码 500 和典型的 Apache 或浏览器警告是一个非常广泛的消息。这不是真正的错误。要确定它是网络服务器配置错误 ( .htaccess) 还是 PHP 致命错误,您必须查看error.log.

阿帕奇错误页面:

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

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

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

[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_display+error_reporting以显示具体错误更简单。毕竟 HTTP 500 包罗万象的页面只是PHP 的白屏死机的一种变体。

也可以看看:

于 2018-12-19T01:23:40.927 回答
6

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

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

例子:

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

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


相关问题:

于 2017-11-07T14:27:54.193 回答
5

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

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


例如这段代码:

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

输出结果:

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

于 2018-10-12T02:09:58.443 回答
4

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

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

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

于 2019-05-06T19:56:46.937 回答
1

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

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

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

于 2020-01-06T21:45:30.997 回答
1

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

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

这个例子在 3v4l.org 上

于 2021-06-01T00:06:00.803 回答