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

时间:2013-08-05 03:11:16

标签: php parsing debugging syntax-error

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

  

PHP Parse错误:语法错误,第20行的index.php中的意外“{”

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

  

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

虽然不是每个案例都匹配另一个案例。然而,有一些general steps to solve syntax mistakes。 这篇文章总结了常见的陷阱:

密切相关的参考文献:

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

  • 回答每个人的编码错误和狭隘的拼写错误主要被认为是偏离主题的。
  • 因此,在发布语法修复请求之前,请花点时间关注basic steps
  • 如果您仍然需要,请展示您自己的解决方案,尝试修复以及您的看法或错误的思考过程。

如果您的浏览器显示错误消息,例如“SyntaxError:非法字符”,那么它实际上并非 - 相关,而是 - syntax error


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

20 个答案:

答案 0 :(得分:105)

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

使用语法检查IDE意味着:

您(有效地)永远不会再次遇到语法错误,只是因为您在键入时看到它们正确。严重。

具有语法检查的优秀IDE(所有这些都适用于Linux,Windows和Mac):

  1. NetBeans [免费]
  2. PHPStorm [$ 199 USD]
  3. EclipsePHP Plugin [免费]
  4. Sublime [$ 80 USD](主要是文字编辑器,但可以通过插件扩展,例如PHP Syntax Parser

答案 1 :(得分:53)

意外[

现在,在过时的PHP版本中经常会出现意外的[数组括号。自PHP > = 5.4 以来,short array syntax可用。旧版安装仅支持array()

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

对于较旧的PHP版本,数组函数结果解除引用同样不可用:

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

Reference - What does this error mean in PHP? - "Syntax error, unexpected \["显示了最常见且最实用的解决方法。

尽管如此,您最好还是升级PHP安装。对于共享的虚拟主机计划,首先进行研究,例如, SetHandler php56-fcgi可用于启用较新的运行时。

另见:

顺便说一下,如果你真的和旧的+较慢的PHP版本紧密相关,还有预处理器和PHP 5.4 syntax down-converters

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

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

  • 您不能使用array property declarations/expressions in classes,即使在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进行括号匹配,以查找任何过早的]数组闭包。至少使用更多的间距和换行来缩小范围。

答案 2 :(得分:45)

意外的T_VARIABLE

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

purposefully abstract/inexact operator+$variable diagram

  1. 缺少分号

    最常见的是前一行a missing semicolon。语句后面的变量赋值是一个很好的指标:

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

    频繁发生的事故是string concatenations被遗忘的.运营商:

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

    顺便说一句,只要有助于提高可读性,你应该更喜欢string interpolation(双引号中的基本变量)。这避免了这些语法问题。

      

    字符串插值是一种脚本语言核心功能。利用它并不羞耻。忽略关于变量.连接的任何微优化建议更快不是。

  3. 缺少表达式运算符

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

               ⇓
    print 4 + 7 $var;
    

    如果变量应该被添加,减去或比较等,那么PHP不能猜测

  4. 解释

    语法列表相同,例如在数组中,解析器也指示预期的逗号,,例如:

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

    或函数参数列表:

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

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

  5. 班级声明

    此解析器错误也会发生in class declarations。您只能分配静态常量,而不能分配表达式。因此,解析器将变量作为分配的数据抱怨:

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

    无法匹配的}花括号可以特别引领。如果方法过早终止(使用适当的缩进!),那么杂散变量通常被错放到类声明体中。

  6. 标识符后的变量

    你也永远不能直接拥有a variable follow an identifier

                 ⇓
    $this->myFunc$VAR();
    
    不过,这是一个常见的例子,其意图是使用variable variables。在这种情况下,例如使用$this->{"myFunc$VAR"}();进行变量属性查找。

      

    请记住,使用变量变量应该是例外。即使阵列更简单,更合适,新手也会经常尝试使用它们。

  7. 语言构造后缺少parens

    匆匆打字可能导致忘记开括号 对于iffor以及foreach语句:

           ⇓
    foreach $array as $key) {
    

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

  8. 否则不期望条件

         ⇓
    else ($var >= 0)
    

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

  9. 需要用于关闭的括号

         ⇓
    function() uses $var {}
    

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

  10. 隐形空白

    正如reference answer中提到的那样" Invisible stray Unicode" (例如non-breaking space),你可能也会看到这个错误,因为我不知道如下代码:

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

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

  11. 另见

答案 3 :(得分:31)

意外的T_CONSTANT_ENCAPSED_STRING
意外的T_ENCAPSED_AND_WHITESPACE

笨拙的名称T_CONSTANT_ENCAPSED_STRINGT_ENCAPSED_AND_WHITESPACE引用引用的 "string" 文字

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

  1. 变量插值不正确

    最常出现错误的PHP变量插值:

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

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

    更准确地说,使用PHP2风格的simple syntax within double quotes进行数组引用是有效的:

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

    嵌套数组或更深层次的对象引用需要complex curly string expression语法:

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

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

  2. 缺少连接

    如果一个字符串跟在一个表达式后面,但没有连接或其他操作符,那么你会看到PHP抱怨字符串文字:

                           ⇓
    print "Hello " . WORLD  " !";
    

    虽然对你我来说很明显,但PHP不能猜测该字符串是否附加在那里。

  3. 令人困惑的字符串引用围栏

    confounding string delimiters时出现相同的语法错误。由单个'或双"引号启动的字符串也以相同的结尾。

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

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

      

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

    这是一个很好的例子,你不应该首先打破双引号。相反,只需使用proper \" escapes作为HTML属性的引号:

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

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

  4. 缺少开场白

    等同于forgotten opening "/' quotes解析器错误的配方:

                   ⇓
     make_url(login', 'open');
    

    此处', '将成为裸字后的字符串文字,显然login是字符串参数。

  5. 数组列表

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

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

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

  6. 功能参数列表

    同样的事情for function calls

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

    一个常见的变体是完全被遗忘的字符串终结符:

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

    这里PHP抱怨两个字符串文字直接相互跟随。但真正的原因当然是未公开的前一串。

  8. 另见

答案 4 :(得分:22)

意外的T_STRING

T_STRING有点用词不当。它没有引用引用的"string"。这意味着遇到了原始标识符。这可以是bare个单词到剩余的CONSTANT或函数名称,忘记的未加引号的字符串或任何纯文本。

  1. 错误引用字符串

    但是,对于错误引用的字符串值,此语法错误最常见。任何未转义和流浪的"'引号都会形成无效的表达式:

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

    语法突出显示会使这样的错误超级明显。重要的是要记住使用反斜杠来转义\"双引号或\'单引号 - 取决于用作string enclosure的内容。

    • 为方便起见,在输出带双引号的纯HTML时,您应该更喜欢外部单引号。
    • 如果要插入变量,请使用双引号字符串,但请注意转义文字"双引号。
    • 要获得更长的输出,请选择多个echo / print行,而不是转发和转出。更好的是考虑一个HEREDOC部分。

    另请参阅 What is the difference between single-quoted and double-quoted strings in PHP?

  2. 未关闭的字符串

    如果您miss a closing ",则语法错误通常会在以后生效。未终止的字符串通常会消耗一些代码,直到下一个预期的字符串值为止:

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

    然后解析器可能会抗议文字T_STRING。对于未加引号的文字HTML,另一种常见的变体是Unexpected '>'

  3. 非编程字符串引号

    如果您从博客或网站复制并粘贴代码,有时会导致代码无效。 Typographic quotes aren't PHP期望:

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

    印刷/智能引号是Unicode符号。 PHP将它们视为邻接的字母数字文本的一部分。例如,”these被解释为常量标识符。但是,随后的任何文本文字都被解析器视为一个单词/ T_STRING。

  4. 缺少分号;再次

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

           ⇓
    func1()
    function2();
    

    PHP无法知道您是否打算逐个运行两个函数,或者您是想要将结果相乘,添加它们,比较它们,还是只运行一个||或另一个。

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

    这种情况相当罕见。但是如果启用了short_open_tags,则无法启动PHP脚本with an XML declaration

          ⇓
    <?xml version="1.0"?>
    

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

  6. 不可见的Unicode字符

    语法错误最可怕的原因是Unicode符号,例如non-breaking space。 PHP允许Unicode字符作为标识符名称。如果您收到完全不可靠的代码的T_STRING解析器投诉,例如:

    <?php
        print 123;
    

    你需要打破另一个文本编辑器。或者甚至是hexeditor。这里看起来像普通空格和换行符的内容可能包含不可见的常量。基于Java的IDE有时无视UTF-8 BOM内部,零宽度空间,段落分隔符等。尝试重新编辑所有内容,删除空格并重新添加正常空格。

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

    <?php
        ;print 123;
    

    此处的额外;分号将前面的不可见字符转换为未定义的常量引用(表达式为语句)。作为回报,PHP会产生有用的通知。

  7. 变量名前面缺少`$`符号

    Variables in PHP由美元符号后跟变量名称表示。

    美元符号($)是sigil,它将标识符标记为变量的名称。如果没有此标识,标识符可以是language keywordconstant

    当PHP代码为"translated" from code written in another language(C,Java,JavaScript等)时,这是一个常见错误。在这种情况下,变量类型的声明(当原始代码用使用类型化变量的语言编写时)也可能会偷偷摸摸并产生此错误。

  8. Escaped Quotation marks

    如果在字符串中使用\,则它具有特殊含义。这称为“Escape Character”,通常告诉解析器按字面意思取下一个字符。

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

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

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

答案 5 :(得分:15)

意外(

打开括号通常遵循if / foreach / for / array / list等语言结构,或者启动算术表达式。在"strings",之前的(),单独的$以及某些典型的声明语境中,它们在语法上不正确。

  1. 函数声明参数

    此错误的罕见情况是trying to use expressions as default function parameters。即使在PHP7中也不支持此功能:

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

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

  2. 类属性默认值

    class member declarations也是如此,其中只允许使用文字/常量值,而不是表达式:

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

    将这些东西放在构造函数中。 另请参阅Why don't PHP attributes allow functions?

    再次注意,PHP 7仅允许var $xy = 1 + 2 +3;常量表达式。

  3. PHP中的JavaScript语法

    使用JavaScript或jQuery syntax因为显而易见的原因而无法在PHP中工作:

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

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

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

    isset()empty()都是语言内置函数,而不是函数。他们need to access a variable directly。如果你无意中添加了一对括号,那么你就创建了一个表达式:

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

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

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


  5. 意外)

    1. 缺少功能参数

      你不能有流浪commas last in a function call。 PHP期望有一个值,因此抱怨早期关闭)括号。

                    ⇓
      callfunc(1, 2, );
      

      只有array()list()个结构才允许使用尾随逗号。

    2. 未完成的表达

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

                     ⇓
      $var = 2 * (1 + );
      

      如果你忘了结束),那么你就会得到关于意外分号的投诉。

    3. Foreach为constant

      对于forgotten variable $ prefixes in control statements,您会看到:

                         ↓    ⇓
      foreach ($array as wrong) {
      

      这里的PHP有时会告诉你它需要::。因为class :: $ variable可以满足预期的$ variable表达式..


    4. 意外{

      大括号{}包含代码块。关于它们的语法错误通常表明存在一些错误的嵌套。

      1. if

        中不匹配的子表达式

        如果解析器抱怨开放卷曲{太早出现,则最常见的是unbalanced ( and )misdeclared functions without parameter list。一个简单的例子:

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

        计算您的parens或使用有助于此的IDE。也不要在没有任何空格的情况下编写代码。可读性很重要。

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

        您无法在表达式中使用花括号。如果你混淆括号和卷曲,它就不符合语言语法:

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

        标识符构造有一些例外,例如局部范围变量${references}

      4. 变量变量或卷曲变量表达式

        这非常罕见。但是对于复杂的变量表达式,您可能还会得到{}个解析器投诉:

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

        虽然在这种情况下出现意外}的可能性较高。


      5. 意外}

        获得&#34;意外}&#34;错误,您过早关闭了代码块。

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

          任何未终止的表达都可能发生。

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

          function whatever() {
              doStuff()
          }            ⇧
          

          此处解析器无法判断您是否仍想将+ 25;添加到函数结果或其他内容。

        2. 无效的块嵌套/忘记{

          当代码块}过早关闭,或者您忘记了{开放时,您有时会看到此解析器错误:

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

          在上面的代码段中,if没有开放{大括号。因此,下面的}结束变得多余。因此,用于该函数的下一个结束}无法与原始的开放{大括号相关联。

          如果没有适当的代码缩进,这些错误就更难找到。使用IDE和括号匹配。


        3. 意外{,期待(

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

          1. 参数列表

            例如,不允许if without condition

                             ⇓
            function whatever {
            }
            
          2. 控制声明条件

            你也不能{{3}}。

              ⇓
            if {
            }
            

            显然,这没有任何意义。通常的嫌疑人for / foreachwhile / do等同样的事情。

              

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

答案 6 :(得分:14)

意外的$ end

当PHP谈到“意外的$end”时,这意味着您的代码提前结束。 (从字面上看,这个消息有点误导。它不是一个名为“$ end”的变量,有时候是新人所假设的。它指的是“文件结束”, EOF 。)

  

原因:代码块/函数或类声明的不平衡{}

关于前面的代码块关闭缺少}大括号的几乎总是

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

  • 使用支架匹配的IDE,找出}不对的位置。  大多数IDE和文本编辑器都有键盘快捷键:

    • NetBeans,PhpStorm,Komodo: Ctrl [ Ctrl ]
    • Eclipse,Aptana: Ctrl Shift P
    • Atom,Sublime: Ctrl m - Zend Studio Ctrl M
    • Geany,Notepad ++: Ctrl B - Joe: Ctrl G - Emacs: CMn < / kbd> - Vim:

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

Bracket matching in an IDE

未终止的表达式

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

  • $var = func(1,  ?> EOF

所以,先看一下脚本的结尾。对于任何PHP脚本中的最后一个语句,尾随;通常是多余的。但你应该有一个。正是因为它缩小了这种语法问题。

缩进HEREDOC标记

HEREDOC or NOWDOC字符串会出现另一种常见情况。使用前导空格,制表符等忽略终止标记:

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

因此,解析器假定HEREDOC字符串一直持续到文件结尾(因此“意外的$ end”)。几乎所有的IDE和语法高亮的编辑器都会使这个显而易见或警告它。

Escaped Quotation marks

如果在字符串中使用\,则它具有特殊含义。这称为“Escape Character”,通常告诉解析器按字面意思取下一个字符。

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

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

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

替代语法

在模板中使用语句/代码块的替代语法时,您会看到此语法错误。例如,使用if:else:以及缺少endif;

另见:

答案 7 :(得分:13)

意外的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树中混合搭配。

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

  2. IF不能在表达式

    中使用

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

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

    当然这是无效的。

    您可以使用a ternary conditional,但要注意可读性影响。

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

    否则打破这样的输出构造:使用multiple ifs and echos
    更好的是,使用temporary variables,并将您的条件放在:

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

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

    控制块不会返回&#34;结果&#34;

    现在这种情况不太常见,但有些程序员甚至会尝试将if视为可以返回结果

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

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

    • 但是control structures(if / foreach / while)没有&#34;结果&#34;
    • 文字字符串&#34; true&#34;也只是一个无效的陈述。

    您必须在代码块中使用作业

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

    或者,可以采用?:三元比较。

    如果在

    您在条件中cannot nest an if

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

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

  3. Forgotton ;分号

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

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

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

  4. 分号太早

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

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

    这种情况比你想象的更频繁。

    • 当你terminate the if () expression with ;时,它将执行一个void语句。 ;变成了自己的{}
    • {…}块因此与if分离,并且始终会运行。
    • 因此else不再与开放的if结构有关系, 这就是为什么这会导致意外的T_ELSE语法错误。

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

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

    代码块;之后的{…}终止整个if 构造,在句法上切断else分支。

  5. 不使用代码块

    语法允许在{ / } / if分支中的代码块中省略大括号elseif ... else。遗憾的是,对于非反向编码人员来说,这种语法风格很常见。 (在错误的假设下,输入或读取的速度更快)。

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

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

    但是要实际使用代码块, 确实有 来编写{ ... }这样的代码!

      

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

  6. Else / Elseif订单错误

    提醒自己的一件事当然是conditional order

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

    您可以拥有任意数量的elseif,但else has to go last。这就是它的原因。

  7. 班级声明

    作为mentioned above,您不能在类声明中拥有控制语句:

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

    在这种情况下,您要么forgot a function定义,要么过早关闭}

  8. 意外的T_ELSEIF / T_ELSE

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

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

    正确的表单<?php } elseif

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

    这或多或少是不正确缩进的变体 - 可能通常基于错误的编码意图     您不能mash other statements inbetween ifelseif / else结构代币:

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

    任何一个都只能出现在{…}个代码块中,而不能出现在控制结构标记之间。

    • 无论如何这都没有意义。它并不像有一些&#34; undefined&#34; PHP在ifelse分支之间跳转时的状态。
    • 您必须在打印语句属于/或者是否需要在两个分支中重复时下定决心。

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

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

    ifelse之间没有syntactic relationforeach词汇范围在}结束,因此if结构无法继续。

  9. T_ENDIF

    如果有人抱怨意外的T_ENDIF,您可以使用其他语法风格if:elseif:else:endif;。你应该三思而后行。

    • 一个常见的陷阱令人感到困惑similar : colon for a ; semicolon。 (涵盖在&#34;分号太早&#34;)

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

    • 使用} endif;  是 doubled if - 终止符。  

    虽然&#34;意外的$ end&#34;通常是忘记结束}花括号的价格。

  10. 作业与比较

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

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

    那不是==/=== comparison, but an = assignment。这是相当微妙的,很容易导致一些用户无助地编辑整个条件块。当你遇到逻辑错误/不当行为时,请先注意意外的任务。

答案 8 :(得分:11)

意外的T_IF
意外的T_FOREACH
意外的T_FOR
意外的T_WHILE
意外的T_DO
意想不到的T_ECHO

控制ifforeachforwhilelistglobalreturn等构造,{ {1}},doprint只能用作对帐单。他们通常独自居住。

  1. 分号;你在哪?

    如果解析器抱怨控制语句,那么上一行中普遍有missed a semicolon

    echo

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

  2. 班级声明

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

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

    此类语法错误通常会导致错误嵌套的class xyz { if (true) {} foreach ($var) {} {。特别是当功能代码块过早关闭时。

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

    大多数语言结构都可以only be used as statements。它们并不意味着放在其他表达式中:

    }

    同样不能在字符串,数学表达式或其他地方使用 ⇓ $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. 类条件,您经常要使用?: ternary evaluation

    这同样适用于ifforwhileglobal以及较小的echo

    list

    ⇓ echo 123, echo 567, "huh?"; 是一种可以在表达式上下文中使用的内置语言。 (但很少有道理。)

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

    您也不能将print()do以及其他语言结构用于用户定义的函数或类名。 (也许在PHP7中。但即使这样也不可取。)

答案 9 :(得分: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
意外<
意外>

比较运算符,例如==>====!=<>!==<=或{ {1}}和<主要应仅用于表达式,例如>表达式。如果解析器抱怨它们,那么它通常意味着不正确的配对或不匹配if (围绕它们。

  1. Parens分组

    特别是对于多重比较的)语句,您必须注意正确计算opening and closing parenthesis

    if

    此处此 ⇓ if (($foo < 7) && $bar) > 5 || $baz < 9) { ... } ↑ 条件已由if

    终止

    一旦你的比较变得足够复杂,通常有助于将它分成多个嵌套的)结构。

  2. isset()使用比较

    进行混淆

    一个普通的新人是pitfal试图将isset()empty()与比较结合起来:

    if

    甚至:

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

    这对PHP没有意义,因为 ⇓ if (isset($variable !== "value")) { isset是只接受变量名的语言结构。比较结果也没有意义,因为输出只是/已经是布尔值。

  3. empty数组运算符

    混淆>=大于或等于

    两个运营商看起来有些相似,所以他们有时会混淆:

    =>

    您只需记住此比较运算符被称为“大于相等”以使其正确。

    另请参阅:If statement structure in PHP

  4. 无法与

    进行比较

    如果它们属于相同的变量名,则也无法组合两个比较:

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

    PHP无法推断您是想再次比较初始变量。表达式通常根据operator precedence进行配对,因此在看到 ⇓ if ($xyz > 5 and < 100) 时,原始变量只剩下一个布尔结果。

    另请参阅:unexpected T_IS_SMALLER_OR_EQUAL

  5. 比较链

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

    <

    这必须分为两个比较,每个比较针对 ⇓ $reult = (5 < $x < 10);

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

  6. 意外$x
    意外>

    大于<或小于>的运算符没有自定义<标记符名称。虽然它们可能像其他人一样错位,但您经常会看到解析器因错误引用字符串和混合HTML而抱怨它们:

    T_XXX

    这相当于一个字符串 ⇓ print "<a href='z">Hello</a>"; ↑ 被比较"<a href='z"到文字常量>,然后是另一个Hello比较。或者至少是PHP如何看待它。实际的原因和语法错误是过早的字符串<终止。

    也无法嵌套PHP开始标记:

    "
  7. 另见:

答案 10 :(得分:6)

意外&#39;?&#39;

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

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

意外&#39;?&#39;,期待变量

可以为空的类型发生类似的错误,如:

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

这再次表明正在使用过时的PHP版本(CLI版本php -v或网络服务器绑定了一个phpinfo();)。

答案 11 :(得分:5)

意外的T_LNUMBER

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

  1. 变量名称无效

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

    $1   // Bad
    $_1  // Good
    

    *

    • 经常comes up在PHP上下文中使用preg_replace - 占位符"$1"

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

      应该引用回调的地方。 (现在已弃用/e正则表达式标志。但有时它仍在preg_replace_callback函数中被滥用。)

    • 相同的标识符约束适用于object properties,顺便说一句。

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

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

  2. 杂散阵列条目

    array declarations时也会发生意外的长时间 - 当缺少,逗号时:

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

    或者类似于函数调用和声明,以及其他构造:

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

    因此,通常会因为分隔列表或表达式而遗漏;,

  3. 错误引用HTML

    同样,misquoted strings是流浪数字的常见来源:

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

    此类案件应该或多或少地被视为Unexpected T_STRING错误。

  4. 其他标识符

    函数,类和namespaces都不能以数字开头命名:

             ↓
    function 123shop() {
    

    与变量名称几乎相同。

答案 12 :(得分:2)

意外的'='

这可能是由于变量名中包含无效字符引起的。变量名称​​必须遵循以下规则:

  

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

答案 13 :(得分:1)

意外的“继续”(T_CONTINUE)

continue是一个语句(例如for或if),并且必须独立出现。它不能用作表达式的一部分。部分是因为continue不返回值,但是在表达式中,每个子表达式都必须得到某个值,因此整个表达式都将得到一个值。这就是语句和表达式之间的区别。

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

意外的“中断”(T_BREAK)

当然break;也一样。它在表达式上下文中也不可用,而是严格的语句(与foreachif块处于同一级别)。

意外的“返回”(T_RETURN)

现在,对于return来说,这可能更令人惊讶,但这也只是一个块级的声明。它的确向更高的作用域/函数返回一个值(或NULL),但它不作为表达式本身求值。 →也就是说:做return(return(false);;

是没有意义的

答案 14 :(得分:1)

意外的'。'

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

...首先在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中,您可以将其用于Array expressions

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];

答案 15 :(得分:0)

意外的“ endwhile”(T_ENDWHILE)

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

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

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

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

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

答案 16 :(得分:0)

错误地将类静态引用Parse error: syntax error, unexpected ':'编写为Class::$Variable可能导致以Class:$Variable开头的错误消息。

答案 17 :(得分:0)

意外:

1. PHP 8 命名参数语法

<块引用>

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

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

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

解决方案:

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

2.裁剪类 :: 分隔符

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

答案 18 :(得分:0)

发生这些错误的另一个原因是意外的空格,如代码中的相似字符,代码行似乎很完美,但它们包含一些类似于换行符或空格或制表符的特定字符,但它们没有得到由解析器解析。 当我尝试通过简单的复制粘贴将一些代码从网页放入代码编辑器时,我遇到了这个问题,我在数组定义中看到了这个错误。一切都在数组定义中看起来正确。我无法理清正确的错误,最后我在一行中定义了这个数组,然后错误就消失了。然后我再次尝试将该定义设为多个,但手动为每个数组元素添加 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,
];

答案 19 :(得分:0)

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