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

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

PHPparsing错误:语法错误,在第20行的index.php中出现意外的“{”

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

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

虽然不是每一个案件匹配其他。 然而,有一些通用的步骤来解决语法错误 。 这些参考文献总结了常见的陷阱:

  • 意外的T_STRING

  • 意外的T_VARIABLE
    意外的'$ varname'(T_VARIABLE)

  • 意外的T_CONSTANT_ENCAPSED_STRING
    意外的T_ENCAPSED_AND_WHITESPACE

  • 意外的$结束

  • 意外的T_FUNCTION …

  • 意外的{

  • 意外的}

  • 意外的

  • 意外)

  • 意想不到的[

  • 意外]

  • 意外的T_IF
    意外的T_FOREACH
    意外的T_FOR
    意外的T_WHILE
    意外的T_DO
    意外的T_PRINT
    意外的T_ECHO

  • 意外的T_LNUMBER

  • 意外的T_INLINE_HTML …

  • 意外的T_PAAMAYIM_NEKUDOTAYIM …

  • 意外的T_OBJECT_OPERATOR …

  • 意外的T_DOUBLE_ARROW …

  • 意外的T_SL …

  • 意外的T_BOOLEAN_OR …
    意外的T_BOOLEAN_AND …

  • 意外的T_IS_EQUAL
    意外的T_IS_GREATER_OR_EQUAL
    意外的T_IS_IDENTICAL
    意外的T_IS_NOT_EQUAL
    意外的T_IS_NOT_IDENTICAL
    意外的T_IS_SMALLER_OR_EQUAL
    意想不到的<
    意外>

  • 意外的T_NS_SEPARATOR …

  • input中意外的字符:' \ '(ASCII = 92)状态= 1

  • 意外的“公共”(T_PUBLIC)
    意外的“私人”(T_PRIVATE)
    意外的“保护”(T_PROTECTED)
    意外的“最后”(T_FINAL) …

  • 意外的T_STATIC …

  • 意外的T_CLASS …

  • 意外的T_DNUMBER

  • 意外, (逗号)

  • 不受限制 (期)

  • 意想不到的; (分号)

  • 意外* (星号)

  • 意外: 冒号)

密切相关的参考文献:

  • 这个错误在PHP中意味着什么? (运行时错误)
    • parsing错误:语法错误,意外的T_XXX
    • parsing错误:语法错误,意外的T_ENCAPSED_AND_WHITESPACE
    • parsing错误:语法错误,意外的T_VARIABLE
  • 这个符号在PHP中意味着什么? (语言令牌)
  • 那些“”聪明''引号对PHP没有任何意义

和:

  • php.net上的PHP手册及其各种语言标记
  • 或者PHP上的 Wikipedias 语法介绍 。
  • 最后,我们的PHP标签维基当然。

虽然Stackoverflow也是欢迎新秀编码器,它主要针对专业编程问题。

  • 回答每个人编码错误和狭窄的错别字大多被认为是无关紧要的。
  • 因此,请在发布语法修复请求之前花时间按照基本步骤进行操作。
  • 如果你仍然需要,请展示你自己的解决scheme,尝试修复和思考过程。

如果您的浏览器显示“SyntaxError:非法字符”等错误消息,那么它实际上并不是php相关的,而是一个JavaScript 语法错误 。

什么是语法错误?

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

函数定义语法摘要

最重要的提示

有几个基本的预防措施,你总是可以采取:

  • 使用正确的代码缩进 ,或采用任何崇高的编码风格。
    可读性防止违规行为。

  • 使用语法突出显示的 PHP的IDE或编辑器 。
    这也有助于parens /支架平衡。

    预计:分号

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

如何解释分析器错误?

一个典型的语法错误信息如下:

parsing错误:语法错误,意外的T_STRING ,期待' ; '217 行的 file.php中

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

T_STRINGT_STRING解释了parsing器/标记器最终无法处理的符号。 但是,这不一定是语法错误的原因。

查看以前的代码行也很重要。 语法错误常常是早期发生的事故。 错误行号就是parsing器决定放弃处理这一切的地方。

解决语法错误

有很多方法来缩小和修复语法打嗝。

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

    • 对于失控的string和错位的操作员,这通常是你find罪魁祸首的地方。

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

  • 更经常地你也需要看前面的几行

    • 特别是失踪; 分号在前一行结束/语句处丢失。 (至less从文体的angular度来看)

    • 如果{代码块}错误地closures或嵌套,则可能需要进一步调查源代码。 使用正确的代码indendation来简化。

  • 看看语法着色

    • string和variables和常量应该都有不同的颜色。

    • 运营商+-*/. 应该是有区别的。 否则他们可能会在错误的情况下。

    • 如果看到string着色太长或太短,那么你已经发现了一个非转义的或缺lessclosures的"'string标记。

    • 有两个相同颜色的标点字符相邻也可能意味着麻烦。 通常,操作符是单独的,如果不是++--或操作符后面是括号。 在大多数情况下,两个string/标识符直接跟在对方之后是不正确的

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

  • 暂时分手。

    • 您可以在运算符或常量和string之间自由添加换行符 。 parsing器然后将parsing错误的行号。 而不是看很长的代码,你可以隔离丢失或错位的语法符号。

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

    • 而不是冗长的math公式或逻辑链,使用临时variables来简化代码。 (更可读=更less的错误。)

    • 添加换行符:

      1. 代码你可以很容易地识别为正确的,
      2. 你不确定的部分,
      3. parsing器抱怨的路线

      分割长代码块确实有助于查找语法错误的起源。

  • 评论违规的代码。

    • 如果你不能隔离问题的来源,开始注释掉(因此暂时删除)代码块。

    • 一旦你摆脱了parsing错误,你已经find了问题的来源。 在那里仔细观察。

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

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

  • 作为新手避免了一些混淆的语法结构。

    • 三元? : ? :条件运算符可以压缩代码,确实是有用的。 但是在任何情况下都不能提高可读性。 优先使用普通的if语句。

    • PHP的替代语法( if: / elseif: / endif; )对于模板来说是很常见的,但是可以说比普通的{ code }块更容易遵循。

  • 最stream行的新人错误是:

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

    • 不匹配的string引号中的"'和未转义的引号。

    • 被遗忘的操作员,特别是string. 级联。

    • 不平衡(括号) 。 在报告的行中进行计数。 他们有相同数量吗?

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

    • 如果你让一个问题消失了,但另外一个代码在下面出现,你大部分都是在正确的道路上。

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

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

    • 采用源代码版本pipe理系统。 你总是可以查看破碎和最后工作版本的diff 。 对于语法问题,这可能是有启发性的。
  • 不可见的stream浪unicode字符 :在某些情况下,您需要在源代码中使用hexeditor或不同的编辑器/查看器。 有些问题不能从查看你的代码中find。

    • 尝试使用grep --color -P -n "[\x80-\xFF]" file.php作为查找非ASCII符号的第一步。

    • 特别是物料清单,零宽度空间或不间断空格,以及经常使用的智能报价可以find源代码。

  • 注意哪种types的换行符保存在文件中。

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

    • MacOS用户偶尔会遇到这个问题(即使是在OS X上configuration错误的编辑器)。

    • 当使用单行//#注释时,它往往只performance为问题。 当换行符被忽略时,多行/*...*/注释几乎不会干扰parsing器。

  • 如果您的语法错误不通过networking传输
    碰巧你的机器上有语法错误。 但在网上发布相同的文件不再显示它。 这只能意味着两件事之一:

    • 你正在看错文件!

    • 或者你的代码包含不可见的stream浪Unicode。 (往上看)
      您可以轻松find:只需将您的代码从Web表单复制到文本编辑器即可。

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

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

  • 反复试验是你最后的select。

如果一切都失败了,你可以随时谷歌你的错误信息。 语法符号不容易search(虽然Stack Overflow本身是由SymbolHound索引的)。 因此,在您find相关内容之前,可能需要查看更多页面。

其他指南:

  • PHPdebugging基础由David Sklar
  • 修复 Jason McCreary的PHP错误
  • PHP错误 – 10个常见错误马里奥Lurig
  • 常见的PHP错误和解决scheme
  • 如何解决和修复你的WordPress网站
  • PHPdevise师错误信息指南 – Smashing杂志

死亡的白色屏幕

如果您的网站只是空白,那么通常语法错误是原因。
启用它们的显示:

  • error_reporting = E_ALL
  • display_errors = 1

在你的php.ini ,或者通过mod_php的.htaccess ,或者甚至用FastCGI设置的.user.ini

在破坏的脚本中启用它太迟了,因为PHP甚至不能解释/运行第一行。 一个快速的解决方法是制作一个包装脚本,说test.php

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

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

这也有助于启用PHP的error_log并查看您的Web服务器error.log当脚本崩溃HTTP 500响应。

我认为这个主题是完全过度讨论/过度复杂,使用IDE是完全避免任何语法错误的方法。 我甚至会说在没有IDE的情况下工作是不专业的。 为什么? 因为现代IDE在你input的每个字符之后都检查你的语法。 当你编写代码时,你的整条线变成红色,并且一个大的警告通知会显示语法错误的确切types和确切位置,那么绝对不需要search另一个解决scheme。

使用语法检查IDE意味着:

您将(有效地)再也不会遇到语法错误,只是因为您在input时看到它们是正确的。 认真。

具有语法检查的优秀IDE(全部可用于Linux,Win和Mac):

  1. NetBeans [免费]
  2. PHPStorm [199美元]
  3. Eclipse与PHP插件 [免费]
  4. 崇高 [80美元](主要是文本编辑器,但可以使用插件进行扩展,如PHP语法分析器 )

意想不到的[

这些日子,意想不到的[数组括号通常在过时的PHP版本上出现。 从PHP > = 5.4开始,可以使用短arrays语法 。 旧的安装只支持array()

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

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

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

参考 – 这个错误在PHP中意味着什么? – “语法错误,意外的[ ”显示最常见和实用的解决方法。

尽pipe如此,只要升级你的PHP安装,总是更好。 对于共享的网站主办计划,首先研究如果SetHandler php56-fcgi可以用来启用更新的运行时。

也可以看看:

  • 取消引用函数结果的PHP语法→自PHP 5.4起可能
  • PHP:语法错误,意外的'['
  • 数组的缩写:是否有像{}或[]这样的字面语法?
  • PHP 5.3.10 vs PHP 5.5.3语法错误意外'['
  • 数组之间的区别()和[]
  • PHP数组语法parsing错误左方括号“[”

顺便说一句,也有预处理器和PHP 5.4语法下转换器,如果你真的很抱歉旧的+较慢的PHP版本。

其他原因意外[语法错误

如果不是PHP版本不匹配,那么通常是一个普通的错字或新手语法错误:

  • 你不能在类中使用数组属性声明/expression式 ,即使在PHP7中也是如此。

     protected $var["x"] = "Nope"; ⇑ 
  • 混乱[与开放大括号{或parens (是一个共同的监督。

     foreach [$a as $b) ⇑ 

    甚至:

     function foobar[$a, $b, $c] { ⇑ 
  • 或者尝试parsing常量(在PHP 5.6之前)作为数组:

     $var = const[123]; ⇑ 

    至lessPHP将该const解释为常量名称。

    如果你想访问一个数组variables(这是这里的典型原因),那么添加前导$ sigil – 所以它变成一个$varname

意外] closures方括号

这是比较罕见的,但也有终止数组括号的语法意外。

  • 再次与括号或花括号不匹配)是常见的:

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

     $var = 2]; 

    多行嵌套数组声明中经常发生这种情况。

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

    如果是这样,使用你的IDE进行括号匹配,find任何过早的数组closures。 至less使用更多的间距和换行符来缩小它的范围。

意外的T_VARIABLE

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

有目的地抽象/不精确的操作符+ $变量图

  1. 缺less分号

    最常见的是在前一行中缺less分号 。 声明之后的variables赋值是一个很好的指示器,可以看到:

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

    频繁的事故是被遗忘的string连接 . 运营商:

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

    顺便说一句,你应该喜欢string插值 (基本variables在双引号),只要这有助于可读性。 这避免了这些语法问题。

    string插值是一种脚本语言的核心function。 没有羞耻的利用它。 忽略任何关于variables的微观优化build议. 连接速度更快不是。

  3. 缺lessexpression式运算符

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

      ⇓ print 4 + 7 $var; 

    PHP不能猜测这个variables是否应该被添加,减去或比较等。

  4. 清单

    语法列表也是一样的,比如在数组中,parsing器也指出一个预期的逗号,例如:

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

    或function参数列表:

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

    相当于你用listglobal陈述来看这个,或者当你缺less一个; 在循环中的分号。

  5. 类声明

    这个parsing器错误也发生在类声明中 。 您只能分配静态常量,而不是expression式。 因此,parsing器会将variables作为分配的数据进行投诉:

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

    无与伦比的}closures大括号可以在这里特别引导。 如果一个方法过早终止(使用正确的缩进!),那么一个strayvariables通常放错了类声明体。

  6. 标识符后面的variables

    你也可以永远不会有一个variables直接跟随一个标识符 :

      ⇓ $this->myFunc$VAR(); 

    顺便说一下,这是一个常见的例子,其目的是使用variablesvariables 。 在这种情况下,使用$this->{"myFunc$VAR"}();进行variables属性查找$this->{"myFunc$VAR"}(); 例如。

    请记住,使用variablesvariables应该是例外。 即使arrays更简单也更合适,新手经常尝试使用它们。

  7. 在语言构造之后缺less的parens

    匆忙的打字可能会导致忘记左括号, ifforforeach语句:

      ⇓ foreach $array as $key) { 

    解决scheme:添加缺less的开放(在语句和variables之间)。

  8. 否则不期望的条件

      ⇓ else ($var >= 0) 

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

  9. 需要括号closures

      ⇓ function() uses $var {} 

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

  10. 不可见的空白

    正如在关于“不可见的stream浪Unicode”的参考答案中所提到的那样(例如不间断的空格 ),您可能也会看到这样的错误:

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

    这在文件和复制粘贴代码的开始是相当普遍的。 如果您的代码在外观上不包含语法问题,请使用hexeditor进行检查。

也可以看看

  • search:意外的T_VARIABLE

意外的T_CONSTANT_ENCAPSED_STRING
意外的T_ENCAPSED_AND_WHITESPACE

笨重的名字T_CONSTANT_ENCAPSED_STRINGT_ENCAPSED_AND_WHITESPACE指的是引用的"string"文字。

它们在不同的环境中使用,但是语法问题非常相似。 T_ENCAPSED …警告发生在双引号的string上下文中,而T_CONSTANT …string通常在简单的PHPexpression式或语句中产生歧义

  1. 错误的插值

    它出现了最不经常的PHPvariables插值:

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

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

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

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

    嵌套数组或深层对象引用不过需要复杂的stringexpression式语法:

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

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

  2. 缺less连接

    如果一个string遵循一个expression式,但没有连接或其他操作符,那么你会看到PHP抱怨string文字:

      ⇓ print "Hello " . WORLD " !"; 

    虽然这对我们来说很明显,但是PHP无法猜测string是否应该附加在那里。

  3. 混淆string报价附件

    混淆string分隔符时会出现相同的语法错误。 由单个'或双"引号开始的string也以相同的结尾。

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

    这个例子从双引号开始。 但是双引号也是针对HTML属性的。 然而,意图的连接运算符被解释为单引号中第二个string的一部分。

    提示 :将编辑器/ IDE设置为对单引号和双引号string使用稍微不同的着色。 (这也有助于应用程序逻辑,例如双引号string用于文本输出,而单引号string仅用于常量值。

    这是一个很好的例子,你不应该摆脱双引号。 相反,只要使用正确的\"转义 HTML属性”的引号:

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

    虽然这也会导致语法混淆,但所有更好的IDE /编辑器都会通过不同的方式对转义的引号进行着色。

  4. 缺less开盘报价

    等同于忘记打开" / '引用parsing器错误的配方:

      ⇓ make_url(login', 'open'); 

    这里', '会成为一个空string之后的string,显然login是一个string参数。

  5. 数组列表

    如果在数组创build块中遗漏逗号,parsing器将会看到两个连续的string:

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

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

  6. 函数参数列表

    函数调用同样的东西:

      ⇓ myfunc(123, "text", "and" "more") 
  7. 失控的string

    一个常见的变化是相当简单的被遗忘的string终止符:

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

    这里PHP抱怨两个string文字,直接跟在对方之后。 但真正的原因是以前没有closures过的string。

也可以看看

  • PHP – 语法错误,意外的T_CONSTANT_ENCAPSED_STRING
  • 语法错误,PHP中意外的T_CONSTANT_ENCAPSED_STRING
  • SQL查询中意外的T_CONSTANT_ENCAPSED_STRING错误

意外的$结束

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

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

几乎总是关于一个缺less的大括号来closures前面的代码块。

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

  • 使用括号匹配的IDE来找出哪里是错误的。
    大多数IDE和文本编辑器都有键盘快捷键:

    • Netbeans,PhpStorm,Komodo: Ctrl [Ctrl ]
    • Eclipse,Aptana: Ctrl Shift P
    • Atom,Sublime: Ctrl m – Zend Studio Ctrl M
    • Geany,记事本++: Ctrl B – Joe: Ctrl G – Emacs: CMn – Vim:

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

括号在IDEA中匹配

未终止的expression

Unexpected $end语法/分析器错误也可能发生未Unexpected $endexpression式或语句:

  • $var = func(1,
    ?> EOF

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

缩进的HEREDOC标记

HEREDOC或NOWDOCstring会出现另一个常见的情况。 终止标记被前导空格/制表符等忽略。

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

因此,parsing器假定HEREDOCstring继续直到文件的末尾(因此“意外$结束”)。 几乎所有的IDE和语法高亮的编辑都会对此做出明显的警告或警告。

替代语法

在模板中使用语句/代码块的替代语法时,可以看到这种语法错误。 使用if:else:和一个丢失的endif; 例如。

也可以看看:

  • PHP语法错误“意外$结束”
  • parsing错误:语法错误,我的PHP代码中的文件意外结束
  • parsing错误语法错误意外的结束文件的PHP
  • PHPparsing错误:语法错误,Codeigniter视图中的文件意外结束
  • parsing错误:语法错误,文件意外结束(注册脚本)
  • “parsing错误:语法错误,意外的$结束”为我的单一注册分配
  • 修复PHP错误:PHP错误#3:意外的文件结束

意外的T_STRING

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

  1. 错误的string

    但是,这个语法错误对错误引用的string值是最常见的。 任何非转义和stream浪的"'引用将形成一个无效的expression:

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

    语法高亮会使这样的错误变得非常明显。 记住使用反斜杠来转义\"双引号或\'单引号 – 这取决于哪个被用作string包围是很重要的 。

    • 为了方便起见,在输出纯双引号的HTML时,应该使用外部单引号。
    • 如果要插入variables,请使用双引号string,但请注意转义文字"双引号”。
    • 对于更长的输出,更喜欢多个echo / print行,而不是逃避和退出。 更好的是考虑HEREDOC部分。

    另请参见PHP中的单引号和双引号string有什么区别?

  2. 未封闭的string

    如果你错过了一个closures"那么一个语法错误通常会在稍后实现。一个未终结的string通常会消耗一些代码,直到下一个预期的string值:

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

    这不仅仅是parsing器可能会抗议的字面T_STRING 。 另一个频繁的变化是对于未加引号的文字HTML Unexpected '>'

  3. 非编程string引号

    如果您复制并粘贴来自博客或网站的代码,则有时会导致代码无效。 排版引号不是 PHP所期望的:

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

    排版/智能引号是Unicode符号。 PHP将它们视为邻接的字母数字文本的一部分。 例如”these被解释为不变的标识符。 但是任何下面的文本文字都被parsing器看作裸字/ T_STRING。

  4. 缺less分号; 再次

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

      ⇓ func1() function2(); 

    PHP只是不知道你是否打算继续运行两个函数,或者如果你打算乘以他们的结果,添加它们,比较它们,或者只运行一个|| 或者其他。

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

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

      ⇓ <?xml version="1.0"?> 

    PHP会看到<? 并回收它自己。 它不会明白什么是stream浪的xml意思。 它会被解释为常量。 但是这个version将被看作是另一个文字/常量。 而且由于parsing器无法理解两个后续的文字/值,而没有expression式运算符,这将是一个parsing器失败。

  6. 不可见的Unicode字符

    语法错误最可怕的原因是Unicode符号,例如不间断的空格 。 PHP允许Unicode字符作为标识符名称。 如果你得到一个T_STRINGparsing器投诉完全不可靠的代码,如:

     <?php print 123; 

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

    你可以缩小它与添加冗余; 语句分隔符在每一行开始:

     <?php ;print 123; 

    额外的; 这里的分号会把前面的不可见字符转换成一个未定义的常量引用(expression式作为语句)。 这反过来使PHP产生一个有用的通知。

意外的

开放括号通常遵循语言结构,如if / foreach / for / array / list或开始一个算术expression式。 在"strings" ,previous ()$ lone,以及一些典型的声明上下文中,它们在语法上是不正确的。

  1. 函数声明参数

    这个错误的一个罕见的发生是试图使用expression式作为默认的function参数 。 即使在PHP7中也不支持:

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

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

  2. 类属性默认值

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

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

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

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

  3. PHP中的Javascript语法

    使用Javascript或jQuery语法在PHP中不起作用,原因很明显:

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

    发生这种情况时,通常会指示一个未终止的前一个string; 和文字<script>部分泄露到PHP代码上下文中。

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

    isset()empty()都是语言内置的,而不是函数。 他们需要直接访问variables 。 If you inadvertently add a pair of parentheses too much, then you'd create an expression however:

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

    Same applies to any language construct that requires implicit variable name access. These built-ins are part of the language grammer, therefore don't permit decorative extra parens.

    User-level functions that require a variable reference -but get an expression result passed- lead to runtime errors instead.

Unexpected )

  1. Absent function parameter

    You cannot have stray commas last in a function call . PHP expects a value there and thusly complains about an early closing ) parenthesis.

      ⇓ callfunc(1, 2, ); 

    A trailing comma is only allowed in array() or list() constructs.

  2. Unfinished expressions

    If you forget something in an arithmetic expression, then the parser gives up. Because how should it possibly interpret that:

      ⇓ $var = 2 * (1 + ); 

    And if you forgot the closing ) even, then you'd get a complaint about the unexpected semicolon instead.

  3. Foreach as constant

    For forgotten variable $ prefixes in control statements you will see:

      ↓ ⇓ foreach ($array as wrong) { 

    PHP here sometimes tells you it expected a :: instead. Because a class::$variable could have satisfied the expected $variable expression..

Unexpected {

Curly braces { and } enclose code blocks. And syntax errors about them usually indicate some incorrec nesting.

  1. Unmatched subexpressions in an if

    Most commonly unbalanced ( and ) are the cause if the parser complains about the opening curly { appearing too early. 一个简单的例子:

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

    Count your parens or use an IDE which helps with that. Also don't write code without any spaces. Readability counts.

  2. { and } in expression context

    You can't use curly braces in expressions. If you confuse parentheses and curlys, it won't comply to the language grammer:

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

    There are a few exceptions for identifier construction, such as local scope variable ${references} .

  3. Variable variables or curly var expressions

    This is pretty rare. But you might also get { and } parser complaints for complex variable expressions:

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

    Though there's a higher likelihood for an unexpected } in such contexts.

Unexpected }

When getting an "unexpected } " error, you've mostly closed a code block too early.

  1. Last statement in a code block

    It can happen for any unterminated expression.

    And if the last line in a function/code block lacks a trailing ; semicolon:

     function whatever() { doStuff() } ⇧ 

    Here the parser can't tell if you perhaps still wanted to add + 25; to the function result or something else.

  2. Invalid block nesting / Forgotten {

    You'll sometimes see this parser error when a code block was } closed too early, or you forgot an opening { even:

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

    In above snippet the if didn't have an opening { curly brace. Thus the closing } one below became redundant. And therefore the next closing } , which was intended for the function, was not associatable to the original opening { curly brace.

    Such errors are even harder to find without proper code indentation. Use an IDE and bracket matching.

Unexpected { , expecting (

Language constructs which require a condition/declaration header and a code block will trigger this error.

  1. Parameter lists

    For example misdeclared functions without parameter list are not permitted:

      ⇓ function whatever { } 
  2. Control statement conditions

    And you can't likewise have an if without condition .

      ⇓ if { } 

    Which doesn't make sense, obviously. Same thing for the usual suspects, for / foreach and while / do etc.

    If you've got this particular error, you definitely should look up some manual examples.

Unexpected T_IS_EQUAL
Unexpected T_IS_GREATER_OR_EQUAL
Unexpected T_IS_IDENTICAL
Unexpected T_IS_NOT_EQUAL
Unexpected T_IS_NOT_IDENTICAL
Unexpected T_IS_SMALLER_OR_EQUAL
Unexpected <
Unexpected >

Comparison operators such as == , >= , === , != , <> , !== and <= or < and > mostly should be used just in expressions, such as if expressions. If the parser complains about them, then it often means incorrect paring or mismatched ( ) parens around them.

  1. Parens grouping

    In particular for if statements with multiple comparisons you must take care to correctly count opening and closing parenthesis :

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

    Here the if condition here was already terminated by the )

    Once your comparisons become sufficiently complex it often helps to split it up into multiple and nested if constructs rather.

  2. isset() mashed with comparing

    A common newcomer is pitfal is trying to combine isset() or empty() with comparisons:

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

    甚至:

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

    This doesn't make sense to PHP, because isset and empty are language constructs that only accept variable names. It doesn't make sense to compare the result either, because the output is only/already a boolean.

  3. Confusing >= greater-or-equal with => array operator

    Both operators look somewhat similar, so they sometimes get mixed up:

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

    You only need to remember that this comparison operator is called " greater than or equal " to get it right.

    See also: If statement structure in PHP

  4. Nothing to compare against

    You also can't combine two comparisons if they pertain the same variable name:

      ⇓ if ($xyz > 5 and < 100) 

    PHP can't deduce that you meant to compare the initial variable again. Expressions are usually paired according to operator precedence , so by the time the < is seen, there'd be only a boolean result left from the original variable.

    See also: unexpected T_IS_SMALLER_OR_EQUAL

  5. Comparison chains

    You can't compare against a variable with a row of operators:

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

    This has to be broken up into two comparisons, each against $x .

    This is actually more a case of blacklisted expressions (due to equivalent operator associativity). It's syntactically valid in a few C-style languages, but PHP wouldn't interpret it as expected comparison chain either.

  6. Unexpected >
    Unexpected <

    The greater than > or less than < operators don't have a custom T_XXX tokenizer name. And while they can be misplaced like all they others, you more often see the parser complain about them for misquoted strings and mashed HTML:

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

    This amounts to a string "<a href='z" being compared > to a literal constant Hello and then another < comparison. Or that's at least how PHP sees it. The actual cause and syntax mistake was the premature string " termination.

也可以看看:

Unexpected T_IF
Unexpected T_FOREACH
Unexpected T_FOR
Unexpected T_WHILE
Unexpected T_DO
Unexpected T_ECHO

Control constructs such as if , foreach , for , while , list , global , return , do , print , echo may only be used as statements. They usually reside on a line by themselves.

  1. Semicolon; where you at?

    Pretty universally have you missed a semicolon in the previous line if the parser complains about a control statement:

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

    Solution: look into the previous line; add semicolon.

  2. Class declarations

    Another location where this occurs is in class declarations . In the class section you can only list property initializations and method sections. No code may reside there.

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

    Such syntax errors commonly materialize for incorrectly nested { and } . In particular when function code blocks got closed too early.

  3. Statements in expression context

    Most language constructs can only be used as statements . They aren't meant to be placed inside other expressions:

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

    Likewise can't you use an if in strings, math expressions or elsewhere:

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

    For embedding if -like conditions in an expression specifically, you often want to use a ?: ternary evaluation .

    The same applies to for , while , global , echo and a lesser extend list .

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

    Whereas print() is a language builtin that may be used in expression context. (But rarely makes sense.)

  4. Reserved keywords as identifiers

    You also can't use do or if and other language constructs for user-defined functions or class names. (Perhaps in PHP7. But even then it wouldn't be advisable.)

Unexpected T_IF
Unexpected T_ELSEIF
Unexpected T_ELSE
Unexpected T_ENDIF

Conditional control blocks if , elseif and else follow a simple structure. When you encounter a syntax error, it's most likely just invalid block nesting → with missing { curly braces } – or one too many.

在这里输入图像描述

  1. Missing { or } due to incorrect indentation

    Mismatched code braces are common to less well-formatted code such as:

     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 your code looks like this, start afresh! Otherwise it's unfixable to you or anyone else. There's no point in showcasing this on the internet to inquire for help.

    You will only be able to fix it, if you can visually follow the nested structure and relation of if/else conditionals and their { code blocks } . Use your IDE to see if they're all paired.

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

    Any double } } will not just close a branch, but a previous condition structure. Therefore stick with one coding style; don't mix and match in nested if/else trees.

    Apart from consistency here, it turns out helpful to avoid lengthy conditions too. Use temporary variables or functions to avoid unreadable if -expressions.

  2. IF cannot be used in expressions

    A surprisingly frequent newcomer mistake is trying to use an if statement in an expression, such as a print statement:

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

    Which is invalid of course.

    You can use a ternary conditional , but beware of readability impacts.

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

    Otherwise break such output constructs up: use multiple if s and echo s .
    Better yet, use temporary variables , and place your conditionals before:

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

    Defining functions or methods for such cases often makes sense too.

    Control blocks don't return "results"

    Now this is less common, but a few coders even try to treat if as if it could return a result :

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

    Which is structurally identical to using if within a string concatenation / expression.

    • But control structures (if / foreach / while) don't have a "result" .
    • The literal string "true" would also just be a void statement.

    You'll have to use an assignment in the code block :

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

    Alternatively, resort to a ?: ternary comparison.

    If in If

    You cannot nest an if within a condition either:

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

    Which is obviously redundant, because the and (or or ) already allows chaining comparisons.

  3. Forgotton ; semicolons

    Once more: Each control block needs to be a statement. If the previous code piece isn't terminated by a semicolon, then that's a guaranteed syntax error:

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

    Btw, the last line in a {…} code block needs a semicolon too.

  4. Semicolon too early

    Now it's probably wrong to blame a particular coding style, as this pitfall is too easy to overlook:

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

    Which happens more often than you might imagine.

    • When you terminate the if () expression with ; it will execute a void statement. The ; becomes a an empty {} of its own!
    • The {…} block thus is detached from the if , and would always run.
    • So the else no longer had a relation to an open if construct, which is why this would lead to an Unexpected T_ELSE syntax error.

    Which also explains a likewise subtle variation of this syntax error:

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

    Where the ; after the code block {…} terminates the whole if construct, severing the else branch syntactically.

  5. Not using code blocks

    It's syntactically allowed to omit curly braces {} for code blocks in if / elseif / else branches. Which sadly is a syntax style very common to unversed coders. (Under the false assumption this was quicker to type or read).

    However that's highly likely to trip up the syntax. Sooner or later additional statements will find their way into the if/else branches:

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

    But to actually use code blocks, you do have to write {} them as such!

    Even seasoned programmers avoid this braceless syntax, or at least understand it as an exceptional exception to the rule.

  6. Else / Elseif in wrong order

    One thing to remind yourself is the conditional order , of course.

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

    You can have as many elseif s as you want, but else has to go last . That's just how it is.

  7. Class declarations

    As mentioned above , you can't have control statements in a class declaration:

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

    You either forgot a function definition, or closed one } too early in such cases.

  8. Unexpected T_ELSEIF / T_ELSE

    This is more or less a variation of incorrect indentation – presumably often based on wrong coding intentions.
    You cannot mash other statements inbetween if and elseif / else structural tokens:

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

    Either can only occur in {…} code blocks, not in between control structure tokens.

    • This wouldn't make sense anyway. It's not like that there was some "undefined" state when PHP jumps between if and else branches.
    • You'll have to make up your mind where print statements belong to / or if they need to be repeated in both branches.

    Nor can you part an if/else between different control structures:

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

    There is no syntactic relation between the if and else . The foreach lexical scope ends at } , so there's no point for the if structure to continue.

  9. T_ENDIF

    If an unexpected T_ENDIF is complained about, you're using the alternative syntax style if:elseif:else:endif; 。 Which you should really think twice about.

    • A common pitfall is confusing the eerily similar : colon for a ; semicolon . (Covered in "Semicolon too early")

    • As indentation is harder to track in template files, the more when using the alternative syntax – it's plausible your endif; does not match any if: .

    • Using } endif; is a doubled if -terminator.

    While an "unexpected $end" is usually the price for a forgotten closing } curly brace.

  10. Assignment vs. comparison

    So, this is not a syntax error, but worth mentioning in this context:

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

    That's not a == / === comparison, but an = assignment . This is rather subtle, and will easily lead some users to helplessly edit whole condition blocks. Watch out for unintended assignments first – whenver you experience a logic fault / misbeheviour.

Unexpected T_LNUMBER

IN PHP, and most other programming languages, variables cannot start with a number. The first character must be alphabetic or an underscore.

 $1 // bad $_1 // good