PHP 解析/语法错误;以及如何解决它们

PHP parse/syntax errors; and how to solve them

提问人: 提问时间:8/5/2013 最后编辑:37 revs, 13 users 39%mario 更新时间:5/23/2022 访问量:863293

问:

每个人都会遇到语法错误。即使是有经验的程序员也会打错字。对于新人来说,这只是学习过程的一部分。但是,通常很容易解释错误消息,例如:

PHP 解析错误:语法错误,第 20 行索引.php 中出现意外的“{”

意想不到的符号并不总是真正的罪魁祸首。但是行号给出了一个大致的想法,从哪里开始寻找。

始终查看代码上下文。语法错误通常隐藏在上述代码行或前面的代码行中。将您的代码与手册中的语法示例进行比较。

虽然并非每个案例都匹配。然而,有一些一般的步骤可以解决语法错误。 此参考总结了常见的陷阱:

密切相关的参考文献:

和:

虽然 Stack Overflow 也欢迎新手程序员,但它主要针对专业编程问题。

  • 回答每个人的编码错误和狭窄的错别字被认为是题外话。
  • 因此,在发布语法修复请求之前,请花时间遵循基本步骤
  • 如果您仍然需要,请展示您自己的解决主动性、尝试的修复以及您对看起来或可能出错的思考过程。

如果您的浏览器显示错误消息,例如“SyntaxError: illegal character”,那么它实际上与 无关,而是 语法错误


供应商代码引发的语法错误:最后,请考虑如果语法错误不是通过编辑代码库引发的,而是在外部供应商软件包安装或升级后引发的,则可能是由于 PHP 版本不兼容,因此请根据平台设置检查供应商的要求。

PHP javascript 解析 调试 语法错误

评论

2赞 Owen Beresford 8/13/2013
这还不足以作为答案,但人们可以用parsekit_compile_string编写一个分析器,并在上面给出更友好的答案。如果集成到您的 IDE 中,这可能会提供大量信息。
7赞 allprog 8/15/2013
你为此付出了大量的努力。尊重这一点。对于教师来说,学习快速指出错误或创建 IDE 或实现快速修复的人来说可能非常好。但是,正如@Panique所建议的那样,IDE 已经可以有效地为您完成大部分工作。此外,在许多情况下,从头开始是一个不错的选择。
2赞 mario 5/28/2016
@Fred-ii- 我认为大多数原因都与块相似。尽管我想为 IF/ELSE/ELSEIF 问题编制一个更自定义的摘要。T_IF / T_FOREACH / ...
3赞 2/27/2019
你知道,我希望我在几年前学习PHP时有这个列表。非常有帮助,特别是对于初学者。
2赞 mario 8/22/2019
@β.εηοιτ.βε 好主意;最近有不少这样的问题。尽管如果可能的话,它需要涵盖三种常见情况(导入范围、特征、闭包)。

答:

324赞 13 revs, 4 users 86%mario #1

语法错误是什么?

PHP 属于 C 风格命令式编程语言。它有严格的语法规则,当遇到放错位置的符号或标识符时,它无法从中恢复。它无法猜测您的编码意图。

Function definition syntax abstract

最重要的提示

您可以随时采取一些基本的预防措施:

  • 使用适当的代码缩进,或采用任何崇高的编码风格。 可读性可防止不规则性。

  • 使用带有语法高亮显示的 PHP 的 IDE 或编辑器。 这也有助于括号/括号平衡。

    Expected: semicolon

  • 阅读手册中的语言参考和示例。 两次,变得有点熟练。

如何解释分析器错误

典型的语法错误消息如下:

解析错误:语法错误,意外T_STRING,文件中出现;”.php在第 217

其中列出了语法错误的可能位置。请参阅提到的文件名行号

诸如此类的名字对象解释了解析器/分词器最终无法处理的符号。但是,这并不一定是语法错误的原因。T_STRING

查看前面的代码行也很重要。通常,语法错误只是之前发生的事故。错误行号正是解析器最终放弃处理所有错误行的地方。

解决语法错误

有许多方法可以缩小和修复语法问题。

  • 打开提到的源文件。看看上面提到的代码行

    • 对于失控的字符串和放错位置的运算符,这通常是您找到罪魁祸首的地方。

    • 从左到右阅读这一行,想象一下每个符号的作用。

  • 更频繁地,您还需要查看前面的行

    • 特别是,在前一行末尾/语句中缺少缺少的分号。(至少从文体的角度来看。;

    • 如果代码块被错误地关闭或嵌套,则可能需要进一步调查源代码。使用适当的代码缩进来简化它。{}

  • 语法着色

    • 字符串、变量和常量都应具有不同的颜色。

    • 操作员也应采用不同的颜色。否则,他们可能处于错误的上下文中。+-*/.

    • 如果您看到字符串着色延伸得太远或太短,则您发现未转义或缺少结束或字符串标记。"'

    • 将两个相同颜色的标点符号并排在一起也意味着麻烦。通常,如果运算符后面没有 、 或括号,则运算符是孤独的。在大多数情况下,两个字符串/标识符紧跟在一起是不正确的。++--

  • 空白是你的朋友。 遵循任何编码风格。

  • 暂时打破长队。

    • 您可以在运算符或常量和字符串之间自由添加换行符。然后,解析器将具体化解析错误的行号。您可以隔离缺失或放错位置的语法符号,而不是查看非常冗长的代码。

    • 将复杂的语句拆分为不同的或嵌套的条件。ifif

    • 不要使用冗长的数学公式或逻辑链,而是使用临时变量来简化代码。(可读性更高 = 错误更少。

    • 在以下之间添加换行符:

      1. 您可以轻松识别为正确的代码,
      2. 你不确定的部分,
      3. 以及解析器抱怨的行。

      对长代码块进行分区确实有助于找到语法错误的根源。

  • 注释掉有问题的代码。

    • 如果无法隔离问题源,请开始注释掉(从而暂时删除)代码块。

    • 一旦你摆脱了解析错误,你就找到了问题的根源。更仔细地看那里。

    • 有时您想暂时删除完整的函数/方法块。(如果大括号不匹配和代码缩进错误。

    • 如果无法解决语法问题,请尝试从头开始重写注释掉的部分。

  • 作为新手,请避免一些令人困惑的语法结构。

    • 三元条件运算符可以压缩代码,并且确实很有用。但它并不能在所有情况下都有助于可读性。在不精通的情况下更喜欢简单的陈述。? :if

    • PHP 的替代语法 (//) 在模板中很常见,但可以说不如普通代码块那么容易理解。if:elseif:endif;{}

  • 最普遍的新手错误是:

    • 缺少用于终止语句/行的分号。;

    • 或的字符串引号不匹配,其中的未转义引号。"'

    • 被遗忘的运算符,特别是字符串连接。.

    • 不平衡的括号。在报告的行中计算它们。它们的数量相等吗?()

  • 不要忘记,解决一个语法问题可以发现下一个语法问题。

    • 如果你让一个问题消失了,但其他问题在下面的一些代码中出现,那么你基本上走在正确的道路上。

    • 如果编辑后在同一行中出现新的语法错误,则您尝试的更改可能失败。(但并非总是如此。

  • 如果无法修复以前工作代码的备份,请还原它。

    • 采用源代码版本控制系统。您始终可以查看损坏的和上次工作版本。这可能对语法问题是什么有所启发。diff
  • 不可见的杂散 Unicode 字符:在某些情况下,您需要在源上使用十六进制编辑器或其他编辑器/查看器。有些问题不能仅仅通过查看代码来发现。

  • 注意文件中保存的换行符类型

    • PHP 只支持换行符,而不是回车符。\n\r

    • 对于MacOS用户来说,这偶尔会是一个问题(即使在OS X上,对于配置错误的编辑器也是如此)。

    • 它通常仅在使用单行或注释时才作为问题出现。当换行符被忽略时,多行注释很少会干扰解析器。//#/*...*/

  • 如果语法错误未通过 Web 传输: 碰巧您的机器上有语法错误。但是,在网上发布完全相同的文件不会再展示它。这只能意味着以下两件事之一:

    • 您看错了文件!

    • 或者您的代码包含不可见的杂散 Unicode(见上文)。 你可以很容易地找到:只需将代码从Web表单复制回文本编辑器即可。

  • 检查您的 PHP 版本。并非所有语法构造在每台服务器上都可用。

    • php -v对于命令行解释器

    • <?php phpinfo();对于通过 Web 服务器调用的那个。


    这些不一定相同。特别是在使用框架时,您将它们匹配。

  • 不要使用 PHP 的保留关键字作为函数/方法、类或常量的标识符。

  • 试错是你最后的手段。

如果所有其他方法都失败了,您可以随时在谷歌上搜索您的错误消息。语法符号并不那么容易搜索(不过 Stack Overflow 本身由 SymbolHound 索引)。因此,在找到相关内容之前,可能需要再浏览几页。

更多指南:

白屏死机

如果您的网站只是空白,那么通常语法错误是原因。 通过以下方式启用其显示:

  • error_reporting = E_ALL
  • display_errors = 1

你的php中.ini一般,或者通过.htaccess进行mod_php, 甚至是带有 FastCGI 设置的 .user.ini

在损坏的脚本中启用它为时已晚,因为 PHP 甚至无法解释/运行第一行。一个快速的解决方法是制作一个包装脚本,比如:test.php

<?php
   error_reporting(E_ALL);
   ini_set("display_errors", 1);
   include("./broken-script.php");

然后通过访问此包装脚本来调用失败的代码。

它还有助于启用 PHP,并在脚本崩溃并出现 HTTP 500 响应时查看 Web 服务器的错误.logerror_log

评论

0赞 Geo 8/16/2013
error_reporting(E_ALL | E_STRICT);对于早期版本的 PHP
3赞 Josep Valls 5/22/2015
某些 IDE(如 NetBeans)不仅支持语法高亮显示,还支持代码格式设置。如果您养成了正确格式化代码的习惯,并要求 IDE 重新格式化以防万一,您可能会发现难以发现的问题,例如不匹配的大括号。
50赞 9 revs, 6 users 89%mario #2

意外T_VARIABLE

“意外”意味着有一个文字名称,它不适合当前的表达式/语句结构。T_VARIABLE$variable

purposefully abstract/inexact operator+$variable diagram

  1. 缺少分号

    它最常表示上一行中缺少分号。语句后面的变量赋值是一个很好的指示器:

            ⇓
     func1()
     $var = 1 + 2;     # parse error in line +2
    
  2. 字符串连接

    一个常见的事故是字符串连接与被遗忘的运算符:.

                                    ⇓
     print "Here comes the value: "  $value;
    

    顺便说一句,只要有助于可读性,您应该更喜欢字符串插值(双引号中的基本变量)。这避免了这些语法问题。

    字符串插值是脚本语言的核心功能。使用它并不可耻。忽略任何关于变量串联速度更快的微优化建议。事实并非如此。.

  3. 缺少表达式运算符

    当然,在其他表达式中也可能出现同样的问题,例如算术运算:

                ⇓
     print 4 + 7 $var;
    

    PHP 无法猜测变量是否应该被添加、减去或比较等。

  4. 列表

    语法列表也是如此,例如在数组填充中,解析器还指示预期的逗号,例如:,

                                           ⇓
     $var = array("1" => $val, $val2, $val3 $val4);
    

    或函数参数列表:

                                     ⇓
     function myfunc($param1, $param2 $param3, $param4)
    

    同样,您是否在 or 语句中看到这一点,或者在循环中缺少分号时看到这一点。listglobal;for

  5. 类声明

    此解析器错误也发生在类声明中。只能分配静态常量,而不能分配表达式。因此,解析器将变量抱怨为赋值数据:

     class xyz {      ⇓
         var $value = $_GET["input"];
    

    无与伦比的闭合大括号尤其可以在这里领先。如果方法终止得太早(使用适当的缩进!),则杂散变量通常会错误地放入类声明体中。}

  6. 标识符后的变量

    也不能让变量直接跟在标识符后面

                  ⇓
     $this->myFunc$VAR();
    

    顺便说一句,这是一个常见的例子,其目的是使用变量。在本例中,变量属性查找,例如。$this->{"myFunc$VAR"}();

    请记住,使用变量变量应该是例外。新手经常尝试过于随意地使用它们,即使数组会更简单、更合适。

  7. 语言构造后缺少括号

    匆忙键入可能会导致忘记左括号或右括号 for 和 和 语句:ifforforeach

            ⇓
     foreach $array as $key) {
    

    解决方案:在语句和变量之间添加缺少的开口。(

                           ⇓
     if ($var = pdo_query($sql) {
          $result = …
    

    大括号不会打开代码块,而不会先用右括号关闭表达式。{if)

  8. 否则不期望条件

         ⇓
    else ($var >= 0)
    

    解决方案:从 elseif 中删除条件或使用 elseifelse

  9. 需要支架来闭合

         ⇓
    function() use $var {}
    

    解决方案:在 周围添加括号。$var

  10. 看不见的空白

    如“不可见的杂散 Unicode”(例如不间断空格)的参考答案中所述,对于毫无戒心的代码,您可能还会看到此错误,例如:

    <?php
                              ⇐
    $var = new PDO(...);
    

    它在文件开头和复制粘贴代码中相当普遍。如果您的代码在视觉上不包含语法问题,请使用十六进制编辑器进行检查。

另请参阅

30赞 9 revs, 6 users 73%mario #3

意外T_STRING

T_STRING有点用词不当。它不是指引用的 .这意味着遇到了原始标识符。范围可以从单词到剩余或函数名称、被遗忘的未加引号的字符串或任何纯文本。"string"bareCONSTANT

  1. 错误引用的字符串

    但是,对于错误引用的字符串值,此语法错误最为常见。任何未转义的、偏离的或引号都将形成一个无效的表达式:"'

                   ⇓                  ⇓
     echo "<a href="http://example.com">click here</a>";
    

    语法高亮会使这些错误变得非常明显。请务必记住使用反斜杠来转义双引号或单引号 - 具体取决于用作字符串外壳的格式。\"\'

    • 为方便起见,在输出带有双引号的纯 HTML 时,您应该首选外部单引号。
    • 如果要插值变量,请使用双引号字符串,但要注意转义文字双引号。"
    • 对于更长的输出,首选多行 / 行,而不是转义入和出。更好的是考虑 HEREDOC 部分。echoprint


    另一个例子是在用PHP生成的HTML代码中使用PHP条目:

    $text = '<div>some text with <?php echo 'some php entry' ?></div>'
    

    如果有很多行,并且开发人员看不到整个PHP变量值,而是专注于代码段而忘记了其源代码,就会发生这种情况。示例在这里$text

    参见 PHP 中的单引号字符串和双引号字符串有什么区别?

  2. 未闭合的字符串

    如果您错过了“结束语”,则语法错误通常会在以后出现。未终止的字符串通常会消耗一些代码,直到下一个预期的字符串值:

                                                           ⇓
    echo "Some text", $a_variable, "and some runaway string ;
    success("finished");
             ⇯
    

    解析器可能会抗议的不仅仅是字面意思。另一个常见的变化是未加引号的文字 HTML 的意外“>”。T_STRING

  3. 非编程字符串引号

    如果您从博客或网站复制和粘贴代码,有时最终会得到无效的代码。排版引号不是 PHP 所期望的:

    $text = ’Something something..’ + ”these ain't quotes”;
    

    排版/智能引号是 Unicode 符号。PHP 将它们视为相邻字母数字文本的一部分。例如,被解释为常量标识符。但是,任何后续文本文本都会被解析器视为裸词/T_STRING。”these

  4. 缺少的分号;再

    如果前面几行中有未终止的表达式,则以下任何语句或语言构造都将被视为原始标识符:

           ⇓
    func1()
    function2();
    

    PHP只是不知道你是想一个接一个地运行两个函数,还是想把它们的结果相乘,把它们相加,比较它们,或者只运行一个或另一个。||

  5. PHP 脚本中的短打开标记和标头<?xml

    这是相当罕见的。但是,如果启用了short_open_tags,则不能以 XML 声明开始 PHP 脚本:

          ⇓
    <?xml version="1.0"?>
    

    PHP 将看到 并自行回收它。它不会明白流浪者的目的是什么。它将被解释为常量。但 will 被视为另一个字面/常数。而且,由于解析器无法理解两个后续的文字/值,而中间没有表达式运算符,这将是解析器失败。<?xmlversion

  6. 不可见的 Unicode 字符

    语法错误的最可怕的原因是 Unicode 符号,例如不间断空格。PHP 允许使用 Unicode 字符作为标识符名称。如果您收到T_STRING解析器投诉,因为完全不可疑的代码,例如:

    <?php
        print 123;
    

    您需要分解另一个文本编辑器。甚至是十六进制编辑器。这里看起来像普通空格和换行符的东西可能包含不可见的常量。基于 Java 的 IDE 有时会忽略其中的 UTF-8 BOM、零宽度空格、段落分隔符等。尝试重新编辑所有内容,删除空格并重新添加普通空格。

    您可以通过在每行开头添加冗余语句分隔符来缩小范围:;

    <?php
        ;print 123;
    

    此处的额外分号会将前面的不可见字符转换为未定义的常量引用(表达式即语句)。这反过来使PHP产生一个有用的通知。;

  7. 变量名称前面缺少“$”符号

    PHP 中的变量由美元符号表示,后跟变量的名称。

    美元符号 () 是一个印记,用于将标识符标记为变量的名称。如果没有此印记,标识符可以是语言关键字常量$

    当PHP代码是从另一种语言(C,Java,JavaScript等)编写的代码“翻译”时,这是一个常见的错误。在这种情况下,变量类型的声明(当原始代码是使用类型化变量的语言编写时)也可能偷偷溜出并产生此错误。

  8. 转义引号

    如果在字符串中使用,则具有特殊含义。这称为“转义字符”,通常告诉解析器从字面上获取下一个字符。\

    示例:将打印echo 'Jim said \'Hello\'';Jim said 'hello'

    如果您转义字符串的结束引号,则结束引号将按字面意思理解,而不是按预期进行,即作为字符串的一部分作为可打印的引号,而不是关闭字符串。这将显示为分析错误,通常在打开下一个字符串后或脚本末尾显示。

    在 Windows 中指定路径时非常常见的错误:是错误的。你需要。"C:\xampp\htdocs\""C:\\xampp\\htdocs\\"

  9. 类型化属性

    您需要 PHP ≥7.4 才能使用属性类型,例如:

    public stdClass $obj;
    
32赞 7 revs, 3 users 95%mario #4

意外T_CONSTANT_ENCAPSED_STRING
意外T_ENCAPSED_AND_WHITESPACE

笨拙的名称和引用引用的“字符串”文字T_CONSTANT_ENCAPSED_STRINGT_ENCAPSED_AND_WHITESPACE

它们在不同的上下文中使用,但语法问题非常相似。T_ENCAPSED......警告发生在双引号字符串上下文中,而T_CONSTANT...字符串在普通的 PHP 表达式或语句中经常误入歧途。

  1. 变量插值不正确

    它最常出现在不正确的PHP变量插值中:

                              ⇓     ⇓
    echo "Here comes a $wrong['array'] access";
    

    在 PHP 上下文中,引用数组键是必须的。但是在双引号字符串(或 HEREDOC)中,这是一个错误。解析器抱怨包含的单引号,因为它通常期望那里有一个文字标识符/键。'string'

    更准确地说,在数组引用的双引号内使用 PHP2 样式的简单语法是有效的:

    echo "This is only $valid[here] ...";
    

    但是,嵌套数组或更深层次的对象引用需要复杂的卷曲字符串表达式语法:

    echo "Use {$array['as_usual']} with curly syntax.";
    

    如果不确定,使用起来通常更安全。它通常甚至被认为更具可读性。更好的 IDE 实际上为此使用了不同的语法着色。

  2. 缺少串联

    如果字符串跟在表达式后面,但缺少串联或其他运算符,那么你会看到 PHP 抱怨字符串文字:

                           ⇓
    print "Hello " . WORLD  " !";
    

    虽然这对你我来说是显而易见的,但PHP就是无法猜测该字符串是否要附加在那里。

  3. 令人困惑的字符串引号外壳

    混淆字符串分隔符时,也会发生相同的语法错误。以单引号或双引号开头的字符串也以 same 结尾。'"

                    ⇓
    print "<a href="' . $link . '">click here</a>";
          ⌞⎽⎽⎽⎽⎽⎽⎽⎽⌟⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟
    

    该示例以双引号开头。但是双引号也注定要用于 HTML 属性。然而,其中的预期连接运算符被解释为单引号中第二个字符串的一部分。

    提示:将编辑器/IDE 设置为对单引号和双引号字符串使用略微不同的颜色。(它还有助于应用程序逻辑,例如,将双引号字符串用于文本输出,而仅将单引号字符串用于类似常量的值。

    这是一个很好的例子,你首先不应该打破双引号。相反,只需对 HTML 属性的引号使用适当的 \“ 转义符:

    print "<a href=\"{$link}\">click here</a>";
    

    虽然这也可能导致语法混淆,但所有更好的 IDE/编辑器都可以通过以不同的方式为转义引号着色来提供帮助。

  4. 缺少开盘报价

    同样,忘记打开/引用解析器错误的秘诀:

                   ⇓
     make_url(login', 'open');
    

    在这里,当显然是字符串参数时,将在裸词之后成为字符串文字。', 'login

  5. 数组列表

    如果数组创建块中缺少逗号,解析器将看到两个连续的字符串:,

    array(               ⇓
         "key" => "value"
         "next" => "....",
    );
    

    请注意,最后一行可能总是包含一个额外的逗号,但忽略中间的逗号是不可原谅的。如果没有语法突出显示,这是很难发现的。

  6. 函数参数列表

    函数调用也是如此:

                             ⇓
    myfunc(123, "text", "and"  "more")
    
  7. 失控的字符串

    一个常见的变体是很容易被遗忘的字符串终止符:

                                    ⇓
    mysql_evil("SELECT * FROM stuffs);
    print "'ok'";
          ⇑
    

    在这里,PHP 抱怨两个字符串文字直接跟随彼此。但真正的原因当然是前一个未闭合的字符串。

  8. HEREDOC 缩进

    在 PHP 7.3 之前,heredoc 字符串末尾分隔符不能以空格为前缀:

    print <<< HTML
        <link..>
        HTML;
       ⇑
    

    解决方案:升级PHP或寻找更好的托管商。

另请参阅

19赞 7 revs, 3 users 91%mario #5

意外(

左括号通常遵循语言结构(如 //// 或开始算术表达式)。它们在语法上不正确的 , a previous , one 和 some typical 声明上下文中。ifforeachforarraylist"strings"()$

  1. 函数声明参数

    此错误的情况很少发生,即尝试使用表达式作为默认函数参数。即使在 PHP7 中也不支持此功能:

    function header_fallback($value, $expires = time() + 90000) {
    

    函数声明中的参数只能是文本值或常量表达式。与函数调用不同,您可以自由使用 等。whatever(1+something()*2)

  2. 类属性默认值

    类成员声明也是如此,其中只允许使用文字/常量值,而不允许使用表达式:

    class xyz {                   ⇓
        var $default = get_config("xyz_default");
    

    把这些东西放在构造函数中。 参见 为什么 PHP 属性不允许函数?

    再次注意,PHP 7 只允许在那里使用常量表达式。var $xy = 1 + 2 +3;

  3. PHP 中的 JavaScript 语法

    由于显而易见的原因,使用 JavaScript 或 jQuery 语法在 PHP 中不起作用:

    <?php      ⇓
        print $(document).text();
    

    发生这种情况时,它通常表示一个未终止的前面字符串;以及泄漏到 PHP 代码上下文中的文字部分。<script>

  4. isset(()), 空, 键, 下一个, 当前

    两者都是语言内置的,而不是函数。他们需要直接访问变量。如果你无意中添加了一对括号太多,那么你需要创建一个表达式:isset()empty()

              ⇓
    if (isset(($_GET["id"]))) {
    

    这同样适用于任何需要隐式变量名称访问的语言构造。这些内置函数是语言语法的一部分,因此不允许使用多余的括号。

    需要变量引用但传递表达式结果的用户级函数会导致运行时错误。


意外)

  1. 缺少函数参数

    函数调用中不能有杂散的逗号最后。PHP 期望那里有一个值,因此抱怨过早的右括号。)

                  ⇓
    callfunc(1, 2, );
    

    尾随逗号只允许在 or 构造中使用。array()list()

  2. 未完成的表达式

    如果你在算术表达式中忘记了某些内容,那么解析器就会放弃。因为它应该如何解释:

                   ⇓
    $var = 2 * (1 + );
    

    如果你忘记了结束语,那么你就会收到关于意外分号的抱怨。)

  3. Foreach 作为constant

    对于控制语句中被遗忘的变量 $ 前缀,您将看到:

                       ↓    ⇓
    foreach ($array as wrong) {
    

    PHP在这里有时会告诉你它期望一个。因为 class::$variable 可以满足预期的 $variable表达式。::


意外{

大括号和括号代码块。关于它们的语法错误通常表明一些不正确的嵌套。{}

  1. 中不匹配的子表达式if

    最常见的不平衡 是解析器抱怨开口卷曲出现得太早的原因。一个简单的例子:{

                                  ⇓
    if (($x == $y) && (2 == true) {
    

    数一数括号或使用有助于解决此问题的 IDE。也不要编写没有任何空格的代码。可读性很重要。

  2. 表达式上下文中的 { 和 }

    不能在表达式中使用大括号。如果混淆括号和卷曲,则不符合语言语法:

               ⇓
    $var = 5 * {7 + $x};
    

    标识符构造有一些例外,例如 局部作用域变量 。${references}

  3. 变量变量或大写变量表达式

    这是非常罕见的。但是,对于复杂的变量表达式,您也可能会收到解析器的抱怨:{}

                          ⇓
    print "Hello {$world[2{]} !";
    

    尽管在这种情况下发生意外的可能性更高。}


意外}

当出现“意外”错误时,您大多过早关闭了代码块。}

  1. 代码块中的最后一条语句

    对于任何未终止的表达式,都可能发生这种情况。

    如果函数/代码块中的最后一行缺少尾随分号:;

    function whatever() {
        doStuff()
    }            ⇧
    

    在这里,解析器无法判断您是否仍想添加到函数结果或其他内容中。+ 25;

  2. 无效的块嵌套/被遗忘{

    当代码块关闭得太早时,有时你会看到这个解析器错误,或者你甚至忘记了打开:}{

    function doStuff() {
        if (true)    ⇦
            print "yes";
        }
    }   ⇧
    

    在上面的片段中,没有开口大括号。因此,下面的结尾就变得多余了。因此,用于该函数的下一个闭合处与原始开口大括号无关。if{}}{

    如果没有适当的代码缩进,就更难发现此类错误。使用 IDE 和括号匹配。


出乎意料,期待{(

需要条件/声明标头代码块的语言构造将触发此错误。

  1. 参数列表

    例如,不允许错误声明没有参数列表的函数

                     ⇓
    function whatever {
    }
    
  2. 控制语句条件

    而且你同样不能有一个没有条件的 if

      ⇓
    if {
    }
    

    显然,这没有意义。对于通常的嫌疑人,/、/ 等也是如此。forforeachwhiledo

    如果您遇到此特定错误,您绝对应该查找一些手动示例。

评论

1赞 Edgars Aivars 8/22/2017
在这篇文章中寻找我问题的答案,但自己找到了问题的答案 - “意外 {”,这就是为什么我想分享我的答案 - 对我来说,问题是换行编码 - 不知何故,我的一些文件使用 macintosh 换行符,但是当我将它们更改为 Windows 换行符时 - 我的问题(在 localhost(WAMP) 上一切正常, 但是在 Linux Web 服务器上 don't) 已解决。
0赞 mario 8/22/2017
@EdgarsAivars 感谢您的评论!特定于平台的换行符确实是一个不常见且棘手的问题。我可能也会在这里提到它。(它只是在另一个参考答案中被提及。
0赞 c7borg 9/28/2018
我发现获得意外}是因为我的一段代码使用了php短标签<?而不是<?php - 我花了一段时间才找到这个,因为它可以在其他服务器上工作。
11赞 8 revs, 6 users 87%mario #6

意外T_IF
意外T_FOREACH
意外T_FOR
意外 T_WHILE
意外T_DO
意外T_ECHO

控件构造(如 、 、 、 、 、 只能用作语句。他们通常自己驻留在一条线上。ifforeachforwhilelistglobalreturndoprintecho

  1. 分号;你在哪里?

    如果解析器抱怨控制语句,您通常会在上一行中错过一个分号

                 ⇓
    $x = myfunc()
    if (true) {
    

    解决方案:查看上一行;添加分号。

  2. 类声明

    发生这种情况的另一个位置是在类声明中。在类部分中,只能列出属性初始化和方法部分。那里可能没有代码。

    class xyz {
        if (true) {}
        foreach ($var) {}
    

    此类语法错误通常因错误嵌套的 和 而出现。特别是当功能代码块过早关闭时。{}

  3. 表达式上下文中的语句

    大多数语言结构只能用作语句。它们不应该放在其他表达式中:

                       ⇓
    $var = array(1, 2, foreach($else as $_), 5, 6);
    

    同样,您不能在字符串、数学表达式或其他地方使用:if

                   ⇓
    print "Oh, " . if (true) { "you!" } . " won't work";
    // Use a ternary condition here instead, when versed enough.
    

    为了在表达式中专门嵌入类似 if 的条件,您通常需要使用 ?: 三元计算

    这同样适用于 、 、 和较小的扩展。forwhileglobalecholist

              ⇓
    echo 123, echo 567, "huh?";
    

    而是一种内置语言,可以在表达式上下文中使用。(但很少有意义。print()

  4. 保留关键字作为标识符

    也不能对用户定义的函数或类名使用 OR 和其他语言构造。(也许在 PHP 7 中。但即便如此,这也是不可取的。doif

  5. 您的控制块后面有一个分号而不是冒号 (:) 或大括号 ({)

    控件结构通常用大括号括起来(但冒号可以在替代语法中使用)来表示其范围。如果您不小心使用了分号,则过早地关闭了该块,从而导致结束语句引发错误。

    foreach ($errors as $error); <-- should be : or {
119赞 5 revs, 4 users 72%Sliq #7

我认为这个话题完全被过度讨论/过于复杂。使用 IDE 是完全避免任何语法错误的方法。我什至会说,没有IDE的工作是有点不专业的。为什么?因为现代 IDE 会在您键入的每个字符后检查您的语法。当你编码时,你的整行都变成了红色,并且一个大的警告通知向你显示了语法错误的确切类型和确切位置,那么完全没有必要寻找其他解决方案。

使用语法检查 IDE 意味着:

您(实际上)再也不会遇到语法错误,仅仅因为您在键入时正确地看到了它们。认真地。

具有语法检查功能的优秀 IDE(它们都可用于 Linux、Windows 和 Mac):

  1. NetBeans [免费]
  2. PHPStorm [199 美元]
  3. Eclipse with PHP 插件 [免费]
  4. Sublime [$80 USD](主要是一个文本编辑器,但可以通过插件进行扩展,例如 PHP 语法解析器)

评论

3赞 mario 8/13/2013
显然是这样。但是,在这里重新列出 IDE,您能否详细说明它们在语法有用性方面的不同之处?Sublime 主要是一个编辑器,而不是 IDE;但随后更漂亮、更活泼;主要只是语法突出显示,但在括号匹配方面也是名副其实的。例如,它很容易立即发现T_CONSTANT_AND_ENCAPSED错误,这与 PHPStorm 不同;但是,它对内联错误执行了更多的波浪线。NetBeans 的语法提示曾经比 PHP 更隐晦(而是重新列出允许的构造)。您能否分享您的利弊经验;是你最喜欢的 Eclipse/PDT 或者..?
0赞 Sliq 8/13/2013
@mario我认为你对这个话题非常深入,所以我真的不想在这里说任何错误,但是我(以及我的队友、编码的朋友、自由职业者)在 IDE 中编写的所有代码从未在执行时出现过语法错误。所以我认为至少 Netbeans/PHPStorm 的语法检查非常强大。但也许我误读了你的问题。给几个小时...... ;)
0赞 mario 8/13/2013
你的答案已经是正确的了。符合我们 99% 的问题。但是,对于此处的上下文,我想权衡一下哪个 IDE 提供了更适合新手的工具提示。这对我们来说可能是次要的,如果你足够精通,着色和波浪线就足够了。但我认为这些差异对初学者来说可能更重要。
0赞 user1934286 3/7/2017
有时,IDE 不是一个可行的选择。例如,对 WordPress 主题或插件进行快速编辑。是的,我可以将所有代码复制到 IDE 中,但随后我必须打开它,将其全部粘贴到其中,设置标题和所有其他浪费时间的废话,而我只是希望快速编辑。现在,如果您正在开发新功能或从头开始,那么,是的,可以在 IDE 中进行。您不会后悔在开始时花一点额外的时间来设置它。
1赞 user1934286 4/25/2023
@SimaoGomesViana 对于我的网站,我确实有一个本地实例,我在 Sublime 中进行编辑。但是,当朋友打来电话,或者我正在搞砸一个尚未真正上线的新网站时,我会直接在服务器上进行编辑。如果我担心它,我会在本地备份文件,但我也将其备份到服务器上。哈哈。我只是说,有时快速和肮脏并没有错。
15赞 8 revs, 5 users 69%mario #8

意外$end

当PHP谈到“意外”时,这意味着你的代码结束了,而解析器正在期待更多的代码。(从字面上看,这个消息有点误导。这与新手有时假设的名为“$end”的变量无关。它指的是“文件末尾”,.)$endEOF

原因:不平衡,用于代码块 / 和函数或类声明。{}

几乎总是关于缺少大括号来关闭前面的代码块。它说的是,解析器期望找到关闭,但实际上到达了文件的末尾。}}

  • 同样,使用适当的缩进来避免此类问题。

  • 使用带有括号匹配的 IDE 找出问题所在。 大多数 IDE 和文本编辑器中都有键盘快捷键:}

    • NetBeans、PhpStorm、Komodo:和Ctrl[Ctrl]
    • Eclipse,Aptana:CtrlShiftP
    • Atom, Sublime: - Zend StudioCtrlmCtrlM
    • Geany,记事本++: - 乔: - Emacs: - Vim:CtrlBCtrlGC-M-n%

大多数 IDE 还会突出显示匹配的大括号、括号和圆括号。 这使得检查它们的相关性变得非常容易:

Bracket matching in an IDE

未终止的表达式

对于未终止的表达式或语句,也可能发生语法/解析器错误:Unexpected $end

  • $var = func(1, ?>EOF

所以,先看看脚本的结尾。对于任何 PHP 脚本中的最后一条语句来说,尾随通常是多余的。但你应该有一个。正是因为它缩小了此类语法问题的范围。特别是当你发现自己在脚本末尾添加了更多语句之后。;

缩进的 HEREDOC 标记

另一种常见情况出现在 HEREDOC 或 NOWDOC 字符串中。终止标记被忽略,带有前导空格、制表符等:

print <<< END
    Content...
    Content....
  END;
# ↑ terminator isn't exactly at the line start

因此,分析器假定 HEREDOC 字符串一直持续到文件末尾(因此为“意外$end”)。几乎所有的 IDE 和语法高亮编辑器都会对此进行明显处理或发出警告。

转义引号

如果在字符串中使用,则具有特殊含义。这称为“转义字符”,通常告诉解析器从字面上获取下一个字符。\

示例:将打印echo 'Jim said \'Hello\'';Jim said 'hello'

如果您转义字符串的结束引号,则结束引号将按字面意思理解,而不是按预期进行,即作为字符串的一部分作为可打印的引号,而不是关闭字符串。这将显示为分析错误,通常在打开下一个字符串后或脚本末尾显示。

在 Windows 中指定路径时非常常见的错误:是错误的。你需要。或者,PHP 通常会将 Unix 风格的路径(例如 )转换为适用于 Windows 的正确路径。"C:\xampp\htdocs\""C:\\xampp\\htdocs\\""C:/xampp/htdocs/"

替代语法

在模板中对语句/代码块使用替代语法时,您会看到此语法错误的情况很少见。例如,使用 and 和 missing。if:else:endif;

另请参阅:

61赞 4 revs, 4 users 81%mario #9

意外[

如今,意外的数组括号在过时的PHP版本上很常见。短数组语法从 PHP >= 5.4 开始可用。较旧的安装仅支持 .[array()

$php53 = array(1, 2, 3);
$php54 = [1, 2, 3];
         ⇑

数组函数结果取消引用同样不适用于较旧的 PHP 版本:

$result = get_whatever()["key"];
                      ⇑

参考资料 - 这个错误在PHP中是什么意思? - “语法错误,意外的\[显示了最常见和最实用的解决方法。

不过,你最好只是升级你的PHP安装。对于共享的虚拟主机计划,首先研究,例如 可用于启用较新的运行时。SetHandler php56-fcgi

另请参阅:

顺便说一句,如果您真的坚持使用较旧 + 较慢的 PHP 版本,还有预处理器和 PHP 5.4 语法下变频器

意外 [ 语法错误的其他原因

如果不是PHP版本不匹配,那么这通常是一个简单的拼写错误或新手语法错误:

  • 你不能在类中使用数组属性声明/表达式,即使在 PHP 7 中也不行。

    protected $var["x"] = "Nope";
                  ⇑
    
  • 与大括号或括号的左大括号或括号混淆是一个常见的疏忽。[{(

    foreach [$a as $b)
            ⇑
    

    甚至:

    function foobar[$a, $b, $c] {
                   ⇑
    
  • 或者尝试将常量(PHP 5.6 之前)取消引用为数组:

    $var = const[123];
           ⇑
    

    至少 PHP 将其解释为常量名称。const

    如果你打算访问一个数组变量(这是这里的典型原因),那么添加前导符号 - 这样它就变成了一个 .$$varname

  • 您正在尝试在关联数组的成员上使用关键字。这是无效的语法:global

    global $var['key'];
    


意外的右方括号]

这种情况比较罕见,但终止数组括号也存在语法事故。]

  • 同样,与括号或大括号不匹配的情况很常见:)}

    function foobar($a, $b, $c] {
                              ⇑
    
  • 或者尝试结束一个没有数组的数组:

    $var = 2];
    

    这通常发生在多行嵌套数组声明中。

    $array = [1,[2,3],4,[5,6[7,[8],[9,10]],11],12]],15];
                                                 ⇑
    

    如果是这样,请使用 IDE 进行括号匹配,以查找任何过早的数组闭合。至少使用更多的间距和换行符来缩小范围。]

评论

0赞 DanimalReks 6/6/2019
上面的链接“PHP 5.4 语法下变频器”github.com/IonutBajescu/short-arrays-to-long-arrays 已损坏。
0赞 Yunfei Chen 11/29/2020
“function foobar[$a, $b, $c] {” 我以为函数被声明为“function foobar($a, $b, $c){” ????
12赞 4 revsmario #10

出乎意料 T_IS_EQUAL
出乎意料 T_IS_GREATER_OR_EQUAL
出乎意料 T_IS_IDENTICAL
出乎意料 T_IS_NOT_EQUAL
出乎意料 T_IS_NOT_IDENTICAL
出乎意料 T_IS_SMALLER_OR_EQUAL
出乎意
<>

比较运算符(如 、 、 、 和 或 and )应仅在表达式(如表达式)中使用。如果解析器抱怨它们,那么这通常意味着不正确的配对或它们周围的异常。==>====!=<>!==<=<>if()

  1. Parens 分组

    特别是对于具有多个比较的语句,您必须注意正确计算左括号和右括号if

                            ⇓
    if (($foo < 7) && $bar) > 5 || $baz < 9) { ... }
                          ↑
    

    这里的条件已经被if)

    一旦你的比较变得足够复杂,通常有助于将其拆分为多个嵌套结构。if

  2. isset() 与比较捣碎

    一个常见的新手是 pitfal 试图将 isset() 或 empty() 与比较结合起来:

                            ⇓
    if (empty($_POST["var"] == 1)) {
    

    甚至:

                        ⇓
    if (isset($variable !== "value")) {
    

    这对 PHP 来说没有意义,因为 和 是只接受变量名称的语言结构。比较结果也没有意义,因为输出只是/已经是布尔值。issetempty

  3. 将 greater-or equal 与数组运算符混淆>==>

    这两个运算符看起来有些相似,所以它们有时会混淆:

             ⇓
    if ($var => 5) { ... }
    

    您只需要记住,这个比较运算符被称为“大于等于”即可正确。

    参见:PHP 中的 If 语句结构

  4. 没什么可比较的

    如果两个比较属于相同的变量名称,则也不能合并它们:

                     ⇓
    if ($xyz > 5 and < 100)
    

    PHP 无法推断出您打算再次比较初始变量。表达式通常根据运算符优先级进行配对,因此当看到表达式时,原始变量将只剩下布尔值结果。<

    Смотритетакже: 意外T_IS_SMALLER_OR_EQUAL

  5. 比较链

    您不能与具有一行运算符的变量进行比较:

                      ⇓
     $reult = (5 < $x < 10);
    

    这必须分解为两个比较,每个比较都反对 .$x

    这实际上更像是黑名单表达式的情况(由于等效的运算符关联性)。它在语法上在一些 C 风格的语言中是有效的,但 PHP 也不会将其解释为预期的比较链。

  6. 出乎意料 出乎意
    ><

    大于或小于运算符没有自定义分词器名称。虽然它们可能像其他所有它们一样被放错位置,但你更经常看到解析器抱怨它们被错误引用的字符串和捣碎的 HTML:><T_XXX

                            ⇓
    print "<a href='z">Hello</a>";
                     ↑
    

    这相当于将字符串与文本常量进行比较,然后进行另一次比较。或者至少PHP是这样看的。实际原因和语法错误是字符串过早终止。"<a href='z">Hello<"

    也无法嵌套 PHP 开始标记:

    <?php echo <?php my_func(); ?>
               ↑
    

另请参阅:

15赞 7 revs, 4 users 95%mario #11

意外T_IF
意外T_ELSEIF
意外T_ELSE
意外T_ENDIF

条件控制块,并遵循简单的结构。当您遇到语法错误时,很可能只是缺少大括号的无效块嵌套→ - 或者大括号太多。ifelseifelse{}

enter image description here

  1. 缺失或由于缩进不正确{}

    不匹配的代码大括号对于格式不太好的代码很常见,例如:

    if((!($opt["uniQartz5.8"]!=$this->check58)) or (empty($_POST['poree']))) {if
    ($true) {echo"halp";} elseif((!$z)or%b){excSmthng(False,5.8)}elseif (False){
    

    如果你的代码看起来像这样,请重新开始!否则,您或其他任何人都无法修复它。在互联网上展示这一点以寻求帮助是没有意义的。

    只有当您可以直观地遵循 if/else 条件及其代码块的嵌套结构和关系时,您才能修复它。使用 IDE 查看它们是否全部配对。{}

    if (true) {
         if (false) {
                  …
         }
         elseif ($whatever) {
             if ($something2) {
                 …
             } 
             else {
                 …
             }
         }
         else {
             …
         }
         if (false) {    //   a second `if` tree
             …
         }
         else {
             …
         }
    }
    elseif (false) {
        …
    }
    

    任何双精度结构都不会关闭分支,而是关闭先前的条件结构。因此,坚持使用一种编码风格;不要在嵌套的 if/else 树中混合和匹配。}}

    除了这里的一致性之外,避免冗长的条件也很有帮助。使用临时变量或函数来避免不可读的 -expressions。if

  2. IF不能在表达式中使用

    一个令人惊讶的新手错误是尝试在表达式中使用语句,例如 print 语句:if

                       ⇓
    echo "<a href='" . if ($link == "example.org") { echo …
    

    这当然是无效的。

    您可以使用三元条件,但要注意可读性影响。

    echo "<a href='" . ($link ? "http://yes" : "http://no") . "</a>";
    

    否则,将此类输出结构分解:使用多个 ifs 和 echos
    更好的是,使用临时变量,并将条件语句放在:

    if ($link) { $href = "yes"; } else { $href = "no"; }
    echo "<a href='$href'>Link</a>";
    

    为这种情况定义函数或方法通常也很有意义。

    控制块不返回“结果”

    现在这不太常见,但一些编码人员甚至试图将其视为可以返回结果if

    $var = if ($x == $y) { "true" };
    

    这在结构上与在字符串连接/表达式中使用相同。if

    • 但是控制结构(if / foreach / while)没有“结果”。
    • 文字字符串“true”也只是一个 void 语句。

    您必须在代码块中使用赋值:

    if ($x == $y) { $var = "true"; }
    

    或者,求助于三元比较。?:

    如果在 If

    您也不能在条件中嵌套 if

                        ⇓
    if ($x == true and (if $y != false)) { ... }
    

    这显然是多余的,因为 (or ) 已经允许链接比较。andor

  3. 被遗忘的分号;

    再说一遍:每个控制块都需要是一个语句。如果前面的代码段没有以分号结尾,那么这是一个有保证的语法错误:

                    ⇓
    $var = 1 + 2 + 3
    if (true) { … }
    

    顺便说一句,代码块中的最后一行也需要分号。{…}

  4. 分号过早

    现在,责怪特定的编码风格可能是错误的,因为这个陷阱太容易被忽视了:

                ⇓
    if ($x == 5);
    {
        $y = 7;
    }
    else           ←
    {
        $x = -1;    
    }
    

    这种情况发生的频率比您想象的要高。

    • 当您; 终止 if () 表达式时,它将执行一个 void 语句。它变成了一个空虚!;{}
    • 因此,该块与 分离,并且始终运行。{…}if
    • 因此,不再与开放结构有关, 这就是为什么这会导致意外的T_ELSE语法错误。elseif

    这也解释了这个语法错误的同样微妙的变化:

    if ($x) { x_is_true(); }; else { something_else(); };
    

    其中 after 代码块终止整个构造,在语法上切断分支。;{…}ifelse

  5. 不使用代码块

    在语法上允许省略大括号......用于分支中的代码块。可悲的是,这是一种语法风格,对于不熟悉的编码人员来说非常常见。(在错误的假设下,这打字或阅读速度更快)。{}ifelseifelse

    但是,这很可能会使语法绊倒。其他语句迟早会进入 if/else 分支:

    if (true)
        $x = 5;
    elseif (false)
        $x = 6;
        $y = 7;     ←
    else
        $z = 0;
    

    但是要实际使用代码块,您必须编写...他们就是这样!{}

    即使是经验丰富的程序员也会避免使用这种无括号语法,或者至少避免使用这种无括号语法 将其理解为规则的例外情况。

  6. Else / Elseif 顺序错误

    当然,要提醒自己的一件事是有条件的顺序

    if ($a) { … }
    else { … }
    elseif ($b) { … }
    ↑
    

    你可以随心所欲地拥有,但其他必须排在最后。事情就是这样。elseif

  7. 类声明

    如上所述,类声明中不能包含控制语句:

    class xyz {
        if (true) {
            function ($var) {}
        }
    

    在这种情况下,您要么忘记了函数定义,要么过早关闭了函数定义。}

  8. 意外T_ELSEIF/T_ELSE

    当混合PHP和HTML时,一个的结束必须与下一个在同一个PHP块中。这将产生一个错误,因为需要成为 的一部分:}if/elseif<?php ?>elseif/else}ifelseif

    <?php if ($x) { ?>
        html
    <?php } ?>
    <?php elseif ($y) { ?>
        html
    <?php } ?>
    

    正确的形式:<?php } elseif

    <?php if ($x) { ?>
        html
    <?php } elseif ($y) { ?>
        html
    <?php } ?>
    

    这或多或少是错误缩进的变体 - 大概通常基于错误的编码意图。
    您不能在 和 / 结构标记之间捣碎其他语句
    ifelseifelse

    if (true) {
    }
    echo "in between";    ←
    elseif (false) {
    }
    ?> text <?php      ←
    else {
    }
    

    这两种情况都只能出现在代码块中,而不能出现在控制结构标记之间。{…}

    • 无论如何,这都没有意义。当 PHP 在 和 分支之间跳转时,并不是说存在一些“未定义”的状态。ifelse
    • 您必须确定打印语句属于/或者是否需要在两个分支中重复。

    您也不能在不同的控制结构之间划分 if/else

    foreach ($array as $i) {
        if ($i) { … }
    }
    else { … }
    

    和 之间没有句法关系。词法范围以 结束,因此结构没有必要继续。ifelseforeach}if

  9. T_ENDIF

    如果抱怨意外T_ENDIF,则您使用的是替代语法样式 ⋯ ⋯ ⋯ 。你真的应该三思而后行。if:elseif:else:endif;

    • 一个常见的陷阱是混淆了诡异的相似:冒号为分号;分号。(在“分号太早”中涵盖)

    • 由于缩进在模板文件中更难跟踪,因此在使用替代语法时越多 - 您的不匹配是合理的。endif;if:

    • 使用 } endif;双终止符。if

    而“意外$end”通常是被遗忘的闭合卷曲大括号的代价。}

  10. 分配与比较

    因此,这不是语法错误,但在此上下文中值得一提:

           ⇓
    if ($x = true) { }
    else { do_false(); }
    

    这不是 ==/=== 比较,而是 = 赋值。这是相当微妙的,很容易导致一些用户无助地编辑整个条件块。首先要注意意外的分配 - 当您遇到逻辑错误/不当行为时。

6赞 3 revs, 3 users 82%mario #12

意外T_LNUMBER

令牌是指“长”/数字。T_LNUMBER

  1. 无效的变量名称

    在 PHP 和大多数其他编程语言中,变量不能以数字开头。第一个字符必须是字母或下划线。

    $1   // Bad
    $_1  // Good
    

    *

    • 在PHP上下文中使用-placeholders经常出现preg_replace"$1"

      #                         ↓            ⇓  ↓
      preg_replace("/#(\w+)/e",  strtopupper($1) )
      

      回调应该被引用的位置。(现在正则表达式标志已被弃用。但它有时仍然在函数中被误用。/epreg_replace_callback

    • 顺便说一句,相同的标识符约束适用于对象属性

             ↓
      $json->0->value
      
    • 虽然分词器/解析器不允许将文字作为变量名,但可以使用 或 .这是非标准标识符的语法解决方法。(最好将其视为本地范围查找。但一般来说:在这种情况下更喜欢普通数组!$1${1}${"1"}

    • 有趣的是,但非常不推荐,PHPs解析器允许Unicode标识符;这样才是有效的。(与字面意思不同)。$➊1

  2. 杂散数组条目

    数组声明也可能出现意外的长整型 - 缺少逗号时:,

    #            ↓ ↓
    $xy = array(1 2 3);
    

    或者同样地,函数调用和声明,以及其他构造:

    • func(1, 2 3);
    • function xy($z 2);
    • for ($i=2 3<$z)

    因此,通常有一个或缺少一个用于分隔列表或表达式。;,

  3. 错误引用的 HTML

    同样,错误引用的字符串是杂散数字的常见来源:

    #                 ↓ ↓          
    echo "<td colspan="3">something bad</td>";
    

    此类情况应或多或少地被视为意外T_STRING错误。

  4. 其他标识符

    函数、类和命名空间都不能以数字开头命名:

             ↓
    function 123shop() {
    

    与变量名称几乎相同。

10赞 4 revs, 3 users 36%hakre #13

出乎意料的'?

如果您尝试在此范围内使用,则会给出此错误*。<?php<?php

$var = 'hello '<?php echo 'world'; ?>;

* 适用于 PHP 版本 4.3.1、4.3.5 - 4.3.11、4.4.0 - 4.4.1、5.0.0 - 5.0.5、4.4.2 - 4.4.9、5.1.0 - 5.1.6、5.2.0 - 5.2.17、5.3.0 - 5.3.29、5.4.0 - 5.4.45、5.5.0 - 5.5.38、5.6.0 - 5.6.40、7.0.0 - 7.0.33、7.1.0 - 7.1.33、7.2.0 - 7.2.34、7.3.0 - 7.3.31、7.4.0 - 7.4.24


如果您尝试在 PHP 7 之前的 PHP 版本中使用 null 合并运算符,则会出现此错误。??

<?= $a ?? 2; // works in PHP 7+
<?= (!empty($a)) ? $a : 2; // All versions of PHP

意外的“?”,预期变量

对于可为 null 的类型,可能会发生类似的错误,如下所示:

function add(?int $sum): ?int {

这再次表示正在使用过时的PHP版本(CLI版本或Web服务器绑定的版本)。php -vphpinfo();

1赞 2 revs, 2 users 53%mario #14

意外的“继续”(T_CONTINUE)

continue是一个语句(如 for、或 if),并且必须独立显示。它不能用作表达式的一部分。部分原因是 continue 不返回值,但在表达式中,每个子表达式都必须生成某个值,因此整个表达式生成一个值。这就是语句和表达式之间的区别。

这意味着不能在三元语句或任何需要返回值的语句中使用。continue

意外的“中断”(T_BREAK)

当然也是如此。它也不能在表达式上下文中使用,而是一个严格的语句(与块在同一级别上)。break;foreachif

意外的“退货”(T_RETURN)

现在,这可能更令人惊讶,但这也只是一个块级语句。它确实向更高的范围/函数返回一个值(或 NULL),但它不会作为表达式本身进行计算。→ 也就是说:做没有意义returnreturn(return(false);;

3赞 John Conde #15

意外的“=”

这可能是由于变量名称中的字符无效所致。变量名称必须遵循以下规则:

变量名称遵循与 PHP 中其他标签相同的规则。有效的变量名称以字母或下划线开头,后跟任意数量的字母、数字或下划线。作为正则表达式,它将表示为:“[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

评论

0赞 Funk Forty Niner 12/19/2018
很好的补充约翰。
2赞 2 revs, 2 users 85%mplungjan #16

意外的“endwhile”(T_ENDWHILE)

语法使用冒号 - 如果没有冒号,则会发生上述错误。

<?php while($query->fetch()): ?>
 ....
<?php endwhile; ?>

此语法的替代方法是使用大括号:

<?php while($query->fetch()) { ?>
  ....
<?php } ?>

http://php.net/manual/en/control-structures.while.php

2赞 John Conde #17

出乎意料的'.'

如果您尝试在不受支持的 PHP 版本中使用 splat 运算符 (...),则可能会发生这种情况。

...在 PHP 5.6 中首次出现,用于捕获函数的可变数量的参数:

function concatenate($transform, ...$strings) {
    $string = '';
    foreach($strings as $piece) {
        $string .= $piece;
    }
    return($transform($string));
}

echo concatenate("strtoupper", "I'd ", "like ", 4 + 2, " apples");
// This would print:
// I'D LIKE 6 APPLES

在 PHP 7.4 中,您可以将其用于数组表达式

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
2赞 4 revs, 3 users 61%John Conde #18

意外:

1.PHP 8命名参数语法

意外的 ':',期待 ',' 或 ')'

如果尝试在 PHP < 8 版本中使用 PHP 8 的新命名参数功能,将发生以下错误:

$table->string(column:'Name');

解决 方案:

  1. 将您的 PHP 版本升级到 PHP 8.0.0 或更高版本
  2. 不要使用命名参数(按预期顺序传递参数)

2. 裁剪的类分隔符::

以解析错误开头的错误消息:语法错误,意外的“:”可能是由于错误地将类静态引用编写为 .Class::$VariableClass:$Variable

1赞 swapnil akolkar #19

发生这些错误的另一个原因是意外的空格,例如代码中的类似字符,代码行似乎是完美的,但它们包含一些类似于换行符或空格或制表符的特定字符,但它们不会被解析器解析。 当我尝试通过简单地复制粘贴将一些代码从网页放入代码编辑器时,我遇到了这个问题,我在数组定义中看到了这个错误。在数组定义中,一切看起来都是正确的。我无法整理出正确的错误,最后我在单行中定义了这个数组,然后错误就消失了。然后,我再次尝试使该定义成为多个,但手动为每个数组元素添加break(Enter)并保存了文件,这次编辑器没有解析错误,运行它时也没有错误。 例如,我在一个博客上遇到了这个片段的问题,实际上无法发布这些片段,因为堆栈溢出已经知道代码的问题。

然后在解决它之后,我的工作片段是,它看起来与显示解析错误的片段相似

语法错误,意外的“auth”(T_CONSTANT_ENCAPSED_STRING),预期为“]”

    public $aliases = [
        'csrf'=> \CodeIgniter\Filters\CSRF::class,
        'toolbar'=> \CodeIgniter\Filters\DebugToolbar::class,
        'honeypot'=> \CodeIgniter\Filters\Honeypot::class,
        'auth' => \App\Filters\Auth::class,
];

评论

1赞 mario 2/8/2021
我觉得这已经被不可见的杂散Unicode字符覆盖了。它也不是那么普遍,除了复制和粘贴的编码器。如果,更有可能与意外的T_STRING病例配对。
1赞 ofri cofri #20

对于 VS Code 的新手,如果看到语法错误,请检查是否已保存文件。如果语法错误,请保存文件,然后再次修复语法,VS Code 将继续显示错误。只有在保存文件后,错误消息才会消失。