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


652

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

PHP解析错误:语法错误,第20行的index.php中出现意外的'{'

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

始终查看代码上下文。语法错误往往隐藏在提及前面的代码行。将代码与手册中的语法示例进行比较。

虽然并非每种情况都匹配。但是,有一些常规步骤可以解决语法错误。这些参考文献总结了常见的陷阱:

密切相关的参考文献:

和:

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

  • 回答每个人的编码错误和狭窄的拼写错误通常被认为是题外话。
  • 因此,在发布语法修复请求之前,请花一些时间按照基本步骤进行操作。
  • 如果仍然需要,请显示您自己的解决方案,尝试的解决方案以及您对外观或错误之处的思考过程。

如果您的浏览器显示错误消息,例如“ SyntaxError:非法字符”,则实际上不是相关,但是 - 语法错误


供应商代码上出现的语法错误:最后,请考虑如果语法错误不是由于编辑代码库而引起的,而是在外部供应商软件包安装或升级之后出现的,则可能是由于PHP版本不兼容所致,因此请针对您的平台检查供应商的要求设定。


1
这些数据不足以作为答案,但是可以编写一个带有parsekit_compile_string的分析器,并在上面放置更友好的答案。如果集成到您的IDE中,这可能会提供很多信息。
Owen Beresford

4
您为此付出了可观的工作量。尊重这一点。对于教师来说,学习快速指出错误或者对于创建IDE或实施快速修复的人来说可能非常好。但是,正如@Panique所建议的那样,IDE已经可以为您有效地完成大部分工作。另外,在很多情况下,从头开始重新启动是一个不错的选择。
allprog 2013年

1
@ Fred-ii-我认为大多数原因与T_IF / T_FOREACH / ...阻止类似。尽管我想为IF / ELSE / ELSEIF问题编写一个更自定义的摘要。
马里奥

1
@mario不知道该如何表述,但是应该对本问答进行一些重写和更加结构化吗?(临时评论)
Rizier123,2013年

2
您知道的,我希望多年前学习PHP时能有这份清单,这对初学者很有帮助。
Chipster

Answers:


291

语法错误是什么?

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

函数定义语法摘要

最重要的提示

您可以始终采取一些基本的预防措施:

  • 使用适当的代码缩进,或采用任何高级编码样式。可读性可防止出现不正常情况。

  • IDE或编辑器用于PHP突出显示语法。这也有助于括号/括号平衡。

    预期:分号

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

如何解释解析器错误

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

解析错误:语法错误,意想不到的T_STRING,期待;file.php线 217

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

诸如此类的绰号T_STRING解释了解析器/令牌最终无法处理的符号。但是,这不一定是语法错误的原因。

同样重要的是要研究以前的代码行。通常,语法错误只是更早发生的不幸。错误行号正是解析器最终放弃处理所有错误的地方。

解决语法错误

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

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

    • 对于失控的字符串和放错位置的运算符,通常会在这里找到罪魁祸首。

    • 从左到右阅读该行,并想象每个符号的作用。

  • 更经常地,您还需要查看前几行

    • 特别是,缺少的;分号在前一行的末尾/语句中丢失。(至少从样式角度而言。)

    • 如果错误地关闭或嵌套了{代码块,}则可能需要进一步研究源代码。使用适当的代码缩进可以简化该过程。

  • 看看语法着色

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

    • 运营商也+-*/.应设置不同的颜色。否则,它们可能处于错误的环境中。

    • 如果看到字符串着色延伸得太远或太短,则说明未变色或缺少结束符"'字符串标记。

    • 彼此相邻的两个同色标点字符也可能带来麻烦。通常,如果运算符不是,或运算符后的括号++,那么运算符将是孤独的--。在大多数情况下,紧随其后的两个字符串/标识符是错误的。

  • Whitespace是您的朋友。遵循任何编码风格。

  • 暂时中断长行。

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

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

    • 代替冗长的数学公式或逻辑链,请使用临时变量来简化代码。(更具可读性=更少的错误。)

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

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

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

  • 注释掉违规代码。

    • 如果您无法找出问题根源,请开始注释掉(并因此暂时删除)代码块。

    • 摆脱分析错误后,您便找到了问题根源。仔细看那里。

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

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

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

    • 三元? :条件运算符可以压缩代码并且确实有用。但这并不能在所有情况下都有助于可读性。if尽量不要使用简单的陈述。

    • PHP的替代语法(if:/ elseif:/ endif;)在模板中很常见,但是可以说比普通{代码}块更难遵循。

  • 最普遍的新人错误是:

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

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

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

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

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

    • 如果您解决了一个问题,但在下面的一些代码中发现了其他问题,那么您通常走在正确的道路上。

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

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

    • 采用源代码版本控制系统。您始终可以查看diff损坏的最后工作版本的。关于语法问题,这可能会有所启发。
  • 不可见的杂散Unicode字符:在某些情况下,您需要在源文件上使用十六进制编辑器或其他编辑器/查看器。仅查看代码无法发现某些问题。

  • 请注意将哪种换行符保存在文件中。

    • PHP只接受\n换行符,而不接受\r回车符。

    • 对于MacOS用户,这有时是个问题(即使在OS X上,对于配置错误的编辑器)。

    • 当使用单行//#注释时,通常仅是一个问题。/*...*/当换行符被忽略时,多行注释很少会干扰解析器。

  • 如果您的语法错误未通过网络传输:您的计算机上发生语法错误。但是,将相同的文件在线发布不再显示。这仅意味着两件事之一:

    • 您正在查看错误的文件!

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

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

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

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


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

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

  • 试错是您的最后选择。

如果其他所有方法均失败,则您始终可以搜索错误消息。语法符号不是那么容易搜索(堆栈溢出本身由SymbolHound索引)。因此,在找到相关内容之前,可能需要翻阅几页。

其他指南:

死亡白屏

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

  • error_reporting = E_ALL
  • display_errors = 1

php.ini通常,您可以通过.htaccessmod_php或什至.user.ini使用FastCGI设置。

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

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

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

当脚本因HTTP 500响应而崩溃时,它还有助于启用PHP error_log并调查您的Web服务器error.log


error_reporting(E_ALL | E_STRICT);对于之前版本的PHP
地理

2
一些IDE(如NetBeans)不仅支持语法突出显示,而且还支持代码格式。如果您习惯于正确格式化代码并要求IDE重新格式化以防万一,以防您不时发现大括号等问题。
约瑟夫·瓦尔斯

115

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

使用语法检查IDE意味着:

您(有效)永远不会再遇到语法错误,仅因为您在键入时就可以正确看到它们。说真的

具有语法检查功能的出色IDE(它们均适用于Linux,Windows和Mac):

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

2
很明显。但是,在这里重新列出IDE,您能否详细说明它们在语法帮助方面的不同之处?Sublime主要是编辑器,而不是IDE。但是又漂亮又活泼;主要仅用于语法高亮处理,但在括号匹配中也确实适用。例如,与PHPStorm不同,它可以轻松地立即发现T_CONSTANT_AND_ENCAPSED错误。但是,对于行内错误,行会更加弯曲。NetBeans的语法提示甚至比PHP更神秘((重新列出允许的结构))。您可以分享您的利弊经验吗?是您最喜欢的Eclipse / PDT还是?
mario

@mario我认为您真的很热衷这个话题,所以我真的不想在这里说任何错误,但是我(以及我的队友,编码的朋友,自由职业者的伙伴)曾经编写的所有代码从未执行过语法错误。因此,我认为至少Netbeans / PHPStorm的语法检查功能非常强大。但也许我读错了你的问题。给我几个小时的时间;;)
Sliq 2013年

您的答案已经出现。可以满足我们99%的问题。但是,在此情况下,我需要权衡考虑因素,IDE会此问题上提供更加友好的新手工具提示。对我们来说这可能是次要的,如果您足够精通,那么色彩和波浪线就足够了。但我认为这些差异对初学者可能更为重要。
mario

有时,IDE不可行。例如,对WordPress主题或插件进行快速编辑。是的,我可以将所有代码复制到IDE中,但是当我希望进行快速编辑时,我必须将其打开,将其全部粘贴在其中,设置标头以及所有其他浪费时间的废话。现在,如果您要开发新功能或从头开始,那么可以,请在IDE中进行。您不会后悔在开始时花那么多时间进行设置。
1934286年

我将IDE看作是预告片,而不仅仅是工具箱。它可能不是FIX,但可以帮助您查找和防止语法错误。许多回答似乎都在说,如果保持代码干净,则出错的机会就更少,并且更容易发现。自动缩进,代码提示,变量出现,自动关闭括号和自动格式设置,每天可以为我节省很多错字,这也是我使用一个错字的主要优势。这不算超出此问题范围的所有其他内容(调试器,数据库连接器,uml图等)。IDE可以节省您的时间,并且不仅可以防止语法错误。
Louis Loudog Trottier

58

意外 [

如今,[在过时的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进行括号匹配,以查找任何过早的]数组闭包。至少要使用更大的间距和换行符来缩小范围。


上面的链接“ PHP 5.4语法下变频器” github.com/IonutBajescu/short-arrays-to-long-arrays断开了。
Danimal Reks

46

意外的T_VARIABLE

“意外T_VARIABLE”表示存在一个文字$variable名称,该名称不适合当前的表达式/语句结构。

有目的的抽象/不精确运算符+ $变量图

  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)

    等价地使用listor global语句,或者;for循环中缺少分号时,您会看到此情况。

  5. 类声明

    在类声明中也会发生此解析器错误。您只能分配静态常量,不能分配表达式。因此,解析器抱怨变量是分配的数据:

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

    无与伦比的}合拢大括号在这里尤其有用。如果方法过早终止(使用适当的缩进!),则通常会将杂散变量放到类声明主体中。

  6. 标识符后的变量

    您也永远不能让变量直接跟随标识符

                 
    $this->myFunc$VAR();

    顺便说一句,这是一个常见的示例,其意图是可能使用可变变量。在这种情况下$this->{"myFunc$VAR"}();,例如使用变量属性查找。

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

  7. 语言构造后缺少括号

    匆忙输入可能会导致忘记忘记ifforforeach语句的括号:

           
    foreach $array as $key) {

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

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

    卷曲{支架不打开代码块,而不关闭if与表达)第一右括号。

  8. 否则就没有条件

         
    else ($var >= 0)

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

  9. 需要括号关闭

         
    function() uses $var {}

    解决方案:在中添加括号$var

  10. 不可见的空格

    正如在“不可见的杂散Unicode”(例如,不间断的空格)的参考答案中提到的那样,对于诸如以下这样的无意代码,您可能还会看到此错误:

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

    在文件的开头以及复制粘贴的代码中,它相当普遍。如果您的代码在视觉上似乎没有包含语法问题,请与hexeditor一起检查。

也可以看看


32

意外的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上下文中,必须引用数组键。但是在双引号字符串(或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. 令人困惑的字符串引用附件

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

                    
    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抱怨两个字符串文字彼此紧随其后。但是,真正的原因当然是之前未公开的字符串。

也可以看看


27

意外的T_STRING

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

  1. 字符串引用错误

    但是,对于错误引用的字符串值,此语法错误最常见。任何未转义且有误"'引号的内容都将构成无效的表达式:

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

    语法高亮将使此类错误变得非常明显。重要的是要记住使用反斜杠来转义\"双引号或\'单引号-取决于哪一个被用作字符串外壳

    • 为方便起见,在输出带有双引号的纯HTML时,应首选外部单引号。
    • 如果要插值变量,请使用双引号引起来的字符串,但请注意避免转义文字"双引号。
    • 为了获得更长的输出,请选择多行echo/ print行而不是转入和转出。最好还是考虑HEREDOC部分。

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

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

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

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

  2. 未封闭的字符串

    如果错过结束语,"那么通常会在以后出现语法错误。未终止的字符串通常会占用一些代码,直到下一个预期的字符串值为止:

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

    T_STRING解析器随后可能会抗议的不只是文字。另一种常见的变体是Unexpected '>'用于未引用文字HTML。

  3. 非编程字符串引号

    如果您从博客或网站复制并粘贴代码,则有时会得到无效的代码。印刷引号不是 PHP期望的:

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

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

  4. 缺少分号;再次

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

           
    func1()
    function2();

    PHP只是不知道您是要一个接一个地运行两个函数,还是要乘以它们的结果,将它们相加,比较它们还是仅运行一个||或另一个。

  5. 短开放标签和 <?xmlPHP脚本中的标头

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

          
    <?xml version="1.0"?>

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

  6. 不可见的Unicode字符

    语法错误最可怕的原因是Unicode符号,例如不间断的space。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\\"


18

意外 (

圆括号通常遵循if// foreach/ for/ array/之类的语言结构,list或者以算术表达式开头。在语法"strings"(),after ,previous ,lone $和在某些典型的声明上下文中,它们在语法上是不正确的。

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

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

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

    这两个isset()empty()是语言内置插件,而不是功能。他们需要直接访问变量。如果您无意间添加了过多的一对括号,那么您将创建一个表达式:

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

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

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


意外 )

  1. 功能参数缺失

    您不能在函数调用中最后加上逗号。PHP期望在那里有一个值,因此抱怨)括号过早闭合。

                  
    callfunc(1, 2, );

    仅在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. 可变变量或卷曲var表达式

    这很少见。但您也可能会收到{}解析复杂变量表达式的投诉:

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

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


意外 }

遇到“意外}”错误时,您几乎已经太早关闭了代码块。

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

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

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

    function whatever() {
        doStuff()
    }            

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

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

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

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

    在上面的代码片段中,if没有开放的{花括号。因此,}下面的最后一个变得多余。因此},该功能的下一个关闭与原始的打开{花括号没有关联。

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


意外的{,期待(

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

  1. 参数清单

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

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

    同样,你也不能if没有条件

      
    if {
    }

    显然,这没有意义。对于通常的犯罪嫌疑人for/ foreachwhile/ do等,也是一样。

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


1
在此帖子中寻找我的问题的答案,但发现自己对以下问题的回答-“意外{”,这就是为什么我想与我的答案分享-对我来说,问题是换行编码-不知何故,文件正在使用macintosh换行符,但是当我将其更改为Windows换行符时-我的问题(在localhost(WAMP)上一切正常,但在linux webserver上不解决)。
Edgars Aivars

@EdgarsAivars感谢您的评论!特定于平台的换行符确实是一个罕见且棘手的问题。我可能也会在这里提到它。(在其他参考答案中只是提到了这一点。)
mario

我发现获得意外}是因为我的一段代码使用了php短标签<?而不是<?php-我花了一段时间才找到它,因为它可以在其他服务器上使用。
c7borg

14

意外的$ end

当PHP谈论“意外$end”时,这意味着您的代码过早结束。(从字面上看,该消息有些误导。这与新手有时假定的名为“ $ end”的变量无关。它指的是“文件结尾” EOF。)

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

几乎总是出现缺少}大括号,关闭前面的代码块。

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

  • 使用带有方括号匹配的IDE找出}amiss的位置。大多数IDE和文本编辑器中都有键盘快捷键:

    • NetBeans,PhpStorm,Komodo:Ctrl[Ctrl]
    • Eclipse,Aptana: CtrlShiftP
    • 原子,崇高:Ctrlm-Zend StudioCtrlM
    • Geany,记事本++:CtrlB-乔:CtrlG-Emacs:C-M-n-Vim:%

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

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中指定路径时非常常见的错误:"C:\xampp\htdocs\"错误。你需要"C:\\xampp\\htdocs\\"

替代语法

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

也可以看看:


14

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

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

在此处输入图片说明

  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在表达式中使用语句,例如打印语句:

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

    这当然是无效的。

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

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

    否则打破这种输出结构了:使用多个ifS和echo小号
    更好的是,使用临时变量,并将条件放在以下位置:

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

    为此类情况定义功能或方法通常也很有意义。

    控制块不返回“结果”

    现在这已经不那么普遍了,但是一些编码人员甚至试图将其if视为可能返回结果

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

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

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

    您必须在代码块中使用分配:

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

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

    如果在

    不能if在条件内嵌套

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

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

  3. 被遗忘的;分号

    再说一遍:每个控制块都必须是一个语句。如果先前的代码段不是以分号结尾的,那么这是可以保证的语法错误:

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

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

  4. 分号为时过早

    现在,责怪特定的编码样式可能是错误的,因为这种陷阱很容易忽略:

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

    发生的次数超出您的想象。

    • 当您终止if ()表达式时;,它将执行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顺序错误

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

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

    可以有任意多个elseif,但else必须倒数第一个。就是这样。

  7. 类声明

    正如上面提到的,你不能在一个类中声明的控制语句:

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

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

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

    这或多或少是不正确缩进的变体-大概经常是基于错误的编码意图。
    你不能混搭其他语句其间 ifelseif/ else结构标记:

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

    那不是一个==/ ===比较,而是一个=赋值。这相当微妙,并且很容易导致某些用户无助地编辑整个条件块。首先要小心意外的任务-每当遇到逻辑故障/行为异常时。


11

意外T_IS_EQUAL
意外T_IS_GREATER_OR_EQUAL
意外T_IS_IDENTICAL
意外T_IS_NOT_EQUAL
意外T_IS_NOT_IDENTICAL
意外T_IS_SMALLER_OR_EQUAL
意外的<
意外>

比较运营商,如==>====!=<>!==<=<>大部分应该只是在表达式中使用,如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. >==>数组运算符混淆更大或更等于

    这两个运算符看起来有些相似,因此有时会混淆:

             
    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. 意外的>
    意外<

    大于>或小于<运算符没有自定义T_XXX标记器名称。尽管它们可能像其他所有对象一样放错了位置,但您更经常会看到解析器抱怨它们的引号错误和HTML混搭:

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

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

    也不能嵌套PHP开始标签:

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

也可以看看:


11

意外的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在字符串,数学表达式或其他地方使用in:

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

    为了将if类似条件的条件专门嵌入表达式中,通常需要使用?:三进制求值

    这同样适用于forwhileglobalecho和较少延伸list

              
    echo 123, echo 567, "huh?";

    print()内置的语言可以在表达式上下文中使用。(但很少有道理。)

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

    您也不能将doif和其他语言构造用于用户定义的函数或类名。(也许在PHP 7中。但是即使那样,也不建议这样做。)


7

意外的“?”

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

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

意外的'?',期望变量

可空类型可能发生类似的错误,如下所示:

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

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


5

意外的T_LNUMBER

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

  1. 无效的变量名

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

    $1   // Bad
    $_1  // Good

    *

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

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

      回调应在何处引用。(现在/e不赞成使用regex标志。但是有时它仍在preg_replace_callback函数中被滥用。)

    • 相同的标识符约束适用于对象属性 btw。

             
      $json->0->value
    • 尽管令牌生成器/解析器不允许将文字$1作为变量名,但可以使用${1}${"1"}。这是非标准标识符的语法解决方法。(最好将其视为本地范围查找。但是通常:在这种情况下,首选纯数组!)

    • 可笑但很不推荐,PHP的解析器允许使用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() {

    与变量名几乎相同。


2

意外的'='

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

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


好约翰。
Funk 40 Niner,

1

意外的“继续”(T_CONTINUE)

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

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

意外的“中断”(T_BREAK)

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

意外的“返回”(T_RETURN)

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


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中,您可以将其用于数组表达式

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


0

该开头的错误消息Parse error: syntax error, unexpected ':'可以通过错误地写一个类静态参考引起Class::$VariableClass:$Variable

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.