每个人都遇到语法错误。即使是有经验的程序员也会犯错误。对于新手来说,这只是学习过程的一部分。但是,通常很容易解释错误消息,例如:
PHP Parse错误:语法错误,第20行的index.php中的意外“{”
意想不到的符号并不总是真正的罪魁祸首。但是行号给出了从哪里开始寻找的粗略想法。
始终查看代码上下文。语法错误通常隐藏在以前的代码行中提到的或中。将您的代码与手册中的语法示例进行比较。
虽然不是每个案例都匹配另一个案例。然而,有一些general steps to solve syntax mistakes。 这篇文章总结了常见的陷阱:
Unexpected T_CONSTANT_ENCAPSED_STRING
Unexpected T_ENCAPSED_AND_WHITESPACE
Unexpected continue (T_CONTINUE)
Unexpected continue (T_BREAK)
Unexpected continue (T_RETURN)
Unexpected T_SL ...
Unexpected ,
(逗号)
Unpexected .
(期间)
Unexpected ;
(分号)
Unexpected *
(星号)
Unexpected :
(冒号)
密切相关的参考文献:
“”
smart ‘’
quotes mean nothing to PHP 和
虽然Stack Overflow也欢迎新秀编码员,但它主要针对专业编程问题。
如果您的浏览器显示错误消息,例如“SyntaxError:非法字符”,那么它实际上并非php - 相关,而是javascript - syntax error
在供应商代码上引发的语法错误:最后,考虑如果编辑代码库没有引发语法错误,但是在安装或升级外部供应商软件包之后,可能是由于PHP版本不兼容,因此请根据您的平台设置检查供应商的要求。
答案 0 :(得分:105)
我认为这个主题完全过度讨论/过于复杂。使用IDE是完全避免任何语法错误的方法。我甚至会说没有IDE的工作有点不专业。为什么?因为现代IDE会在您键入的每个字符后检查语法。当你编码并且你的整行变成红色,并且一个大的警告通知显示语法错误的确切类型和确切位置时,那么绝对不需要搜索另一个解决方案。
您(有效地)永远不会再次遇到语法错误,只是因为您在键入时看到它们正确。严重。强>
具有语法检查的优秀IDE(所有这些都适用于Linux,Windows和Mac):
答案 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
"意味着有一个文字$variable
名称,它不适合当前的表达式/语句结构。
最常见的是前一行a missing semicolon。语句后面的变量赋值是一个很好的指标:
⇓
func1()
$var = 1 + 2; # parse error in line +2
频繁发生的事故是string concatenations被遗忘的.
运营商:
⇓
print "Here comes the value: " $value;
顺便说一句,只要有助于提高可读性,你应该更喜欢string interpolation(双引号中的基本变量)。这避免了这些语法问题。
字符串插值是一种脚本语言核心功能。利用它并不羞耻。忽略关于变量
.
连接的任何微优化建议更快。 不是。
当然,在其他表达式中也会出现同样的问题,例如算术运算:
⇓
print 4 + 7 $var;
如果变量应该被添加,减去或比较等,那么PHP不能猜测。
语法列表相同,例如在数组中,解析器也指示预期的逗号,
,例如:
⇓
$var = array("1" => $val, $val2, $val3 $val4);
或函数参数列表:
⇓
function myfunc($param1, $param2 $param3, $param4)
您是否在list
或global
语句中或;
循环中缺少for
分号时看到这一点。
此解析器错误也会发生in class declarations。您只能分配静态常量,而不能分配表达式。因此,解析器将变量作为分配的数据抱怨:
class xyz { ⇓
var $value = $_GET["input"];
无法匹配的}
花括号可以特别引领。如果方法过早终止(使用适当的缩进!),那么杂散变量通常被错放到类声明体中。
你也永远不能直接拥有a variable follow an identifier:
⇓
$this->myFunc$VAR();
不过,这是一个常见的例子,其意图是使用variable variables。在这种情况下,例如使用$this->{"myFunc$VAR"}();
进行变量属性查找。
请记住,使用变量变量应该是例外。即使阵列更简单,更合适,新手也会经常尝试使用它们。
if
和for
以及foreach
语句:
⇓
foreach $array as $key) {
解决方案:在语句和变量之间添加缺少的开头(
。
⇓
else ($var >= 0)
解决方案:从else
删除条件或使用elseif
。
⇓
function() uses $var {}
解决方案:在$var
周围添加括号。
正如reference answer中提到的那样" Invisible stray Unicode" (例如non-breaking space),你可能也会看到这个错误,因为我不知道如下代码:
<?php
⇐
$var = new PDO(...);
它在文件开头和复制粘贴代码中相当普遍。如果您的代码在视觉上看起来不包含语法问题,请使用hexeditor进行检查。
答案 3 :(得分:31)
笨拙的名称T_CONSTANT_ENCAPSED_STRING
和T_ENCAPSED_AND_WHITESPACE
引用引用的 "string"
文字。
它们在不同的上下文中使用,但语法问题非常相似。 T_ENCAPSED ... 警告发生在双引号字符串上下文中,而 T_CONSTANT ... 字符串在普通的PHP表达式或语句中经常是误入歧途。
最常出现错误的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实际上使用了不同的语法着色。
如果一个字符串跟在一个表达式后面,但没有连接或其他操作符,那么你会看到PHP抱怨字符串文字:
⇓
print "Hello " . WORLD " !";
虽然对你我来说很明显,但PHP不能猜测该字符串是否附加在那里。
confounding string delimiters时出现相同的语法错误。由单个'
或双"
引号启动的字符串也以相同的结尾。
⇓
print "<a href="' . $link . '">click here</a>";
⌞⎽⎽⎽⎽⎽⎽⎽⎽⌟⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟⌞⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⌟
该示例以双引号开头。但双引号也注定了HTML属性。然而,预期的连接运算符被解释为单引号中的第二个字符串的一部分。
提示:将编辑器/ IDE设置为对单引号和双引号字符串使用略微不同的着色。 (它还有助于应用程序逻辑更喜欢例如双引号字符串用于文本输出,而单引号字符串仅用于类似常量的值。)
这是一个很好的例子,你不应该首先打破双引号。相反,只需使用proper \"
escapes作为HTML属性的引号:
print "<a href=\"{$link}\">click here</a>";
虽然这也会导致语法混乱,但所有更好的IDE /编辑器都会通过不同的方式为转义引号着色提供帮助。
等同于forgotten opening "
/'
quotes解析器错误的配方:
⇓
make_url(login', 'open');
此处', '
将成为裸字后的字符串文字,显然login
是字符串参数。
如果您错过了数组创建块中的,
逗号,解析器将看到两个连续的字符串:
array( ⇓
"key" => "value"
"next" => "....",
);
请注意,最后一行可能总是包含一个额外的逗号,但忽略其间的逗号是不可原谅的。如果没有语法高亮,很难发现。
同样的事情for function calls:
⇓
myfunc(123, "text", "and" "more")
一个常见的变体是完全被遗忘的字符串终结符:
⇓
mysql_evil("SELECT * FROM stuffs);
print "'ok'";
⇑
这里PHP抱怨两个字符串文字直接相互跟随。但真正的原因当然是未公开的前一串。
另见
答案 4 :(得分:22)
T_STRING
有点用词不当。它没有引用引用的"string"
。这意味着遇到了原始标识符。这可以是bare
个单词到剩余的CONSTANT
或函数名称,忘记的未加引号的字符串或任何纯文本。
但是,对于错误引用的字符串值,此语法错误最常见。任何未转义和流浪的"
或'
引号都会形成无效的表达式:
⇓ ⇓
echo "<a href="http://example.com">click here</a>";
语法突出显示会使这样的错误超级明显。重要的是要记住使用反斜杠来转义\"
双引号或\'
单引号 - 取决于用作string enclosure的内容。
"
双引号。echo
/ print
行,而不是转发和转出。更好的是考虑一个HEREDOC部分。另请参阅 What is the difference between single-quoted and double-quoted strings in PHP? 。
如果您miss a closing "
,则语法错误通常会在以后生效。未终止的字符串通常会消耗一些代码,直到下一个预期的字符串值为止:
⇓
echo "Some text", $a_variable, "and some runaway string ;
success("finished");
⇯
然后解析器可能会抗议文字T_STRING
。对于未加引号的文字HTML,另一种常见的变体是Unexpected '>'
。
如果您从博客或网站复制并粘贴代码,有时会导致代码无效。 Typographic quotes aren't PHP期望:
$text = ’Something something..’ + ”these ain't quotes”;
印刷/智能引号是Unicode符号。 PHP将它们视为邻接的字母数字文本的一部分。例如,”these
被解释为常量标识符。但是,随后的任何文本文字都被解析器视为一个单词/ T_STRING。
如果您在前面的行中有未终止的表达式,则以下任何语句或语言构造都将被视为原始标识符:
⇓
func1()
function2();
PHP无法知道您是否打算逐个运行两个函数,或者您是想要将结果相乘,添加它们,比较它们,还是只运行一个||
或另一个。
<?xml
标题这种情况相当罕见。但是如果启用了short_open_tags,则无法启动PHP脚本with an XML declaration:
⇓
<?xml version="1.0"?>
PHP将看到<?
并自行回收它。它不会理解流浪xml
的含义。它会被解释为不变的。但version
将被视为另一个文字/常量。并且由于解析器无法理解两个后续的文字/值,而中间没有表达式运算符,这将是一个解析器失败。
语法错误最可怕的原因是Unicode符号,例如non-breaking space。 PHP允许Unicode字符作为标识符名称。如果您收到完全不可靠的代码的T_STRING解析器投诉,例如:
<?php
print 123;
你需要打破另一个文本编辑器。或者甚至是hexeditor。这里看起来像普通空格和换行符的内容可能包含不可见的常量。基于Java的IDE有时无视UTF-8 BOM内部,零宽度空间,段落分隔符等。尝试重新编辑所有内容,删除空格并重新添加正常空格。
您可以通过在每行开头添加冗余;
语句分隔符来缩小范围:
<?php
;print 123;
此处的额外;
分号将前面的不可见字符转换为未定义的常量引用(表达式为语句)。作为回报,PHP会产生有用的通知。
Variables in PHP由美元符号后跟变量名称表示。
美元符号($
)是sigil,它将标识符标记为变量的名称。如果没有此标识,标识符可以是language keyword或constant。
当PHP代码为"translated" from code written in another language(C,Java,JavaScript等)时,这是一个常见错误。在这种情况下,变量类型的声明(当原始代码用使用类型化变量的语言编写时)也可能会偷偷摸摸并产生此错误。
如果在字符串中使用\
,则它具有特殊含义。这称为“Escape Character”,通常告诉解析器按字面意思取下一个字符。
示例:echo 'Jim said \'Hello\'';
将打印Jim said 'hello'
如果你转义字符串的结束引号,则结尾引用将按字面意思而不是按预期进行,即作为字符串的一部分的可打印引用而不是关闭字符串。在打开下一个字符串或脚本结束后,这通常会显示为解析错误。
在Windows中指定路径时出现非常常见的错误:"C:\xampp\htdocs\"
错误。您需要"C:\\xampp\\htdocs\\"
。
答案 5 :(得分:15)
(
打开括号通常遵循if
/ foreach
/ for
/ array
/ list
等语言结构,或者启动算术表达式。在"strings"
,之前的()
,单独的$
以及某些典型的声明语境中,它们在语法上不正确。
此错误的罕见情况是trying to use expressions as default function parameters。即使在PHP7中也不支持此功能:
function header_fallback($value, $expires = time() + 90000) {
函数声明中的参数只能是文字值或常量表达式。与函数调用不同,您可以自由使用whatever(1+something()*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;
常量表达式。
使用JavaScript或jQuery syntax因为显而易见的原因而无法在PHP中工作:
<?php ⇓
print $(document).text();
当发生这种情况时,它通常表示未终止的前一个字符串;和文字<script>
部分泄漏到PHP代码上下文中。
isset()
和empty()
都是语言内置函数,而不是函数。他们need to access a variable directly。如果你无意中添加了一对括号,那么你就创建了一个表达式:
⇓
if (isset(($_GET["id"]))) {
这同样适用于需要隐式变量名访问的任何语言构造。这些内置函数是语言语法的一部分,因此不允许使用额外的括号。
需要变量引用的用户级函数 - 但是传递表达式结果 - 导致运行时错误。
)
你不能有流浪commas last in a function call。 PHP期望有一个值,因此抱怨早期关闭)
括号。
⇓
callfunc(1, 2, );
只有array()
或list()
个结构才允许使用尾随逗号。
如果你忘记了算术表达式中的某些东西,那么解析器就会放弃。因为它应该如何解释:
⇓
$var = 2 * (1 + );
如果你忘了结束)
,那么你就会得到关于意外分号的投诉。
constant
对于forgotten variable $
prefixes in control statements,您会看到:
↓ ⇓
foreach ($array as wrong) {
这里的PHP有时会告诉你它需要::
。因为class :: $ variable可以满足预期的$ variable表达式..
{
大括号{
和}
包含代码块。关于它们的语法错误通常表明存在一些错误的嵌套。
if
如果解析器抱怨开放卷曲{
太早出现,则最常见的是unbalanced (
and )
。misdeclared functions without parameter list。一个简单的例子:
⇓
if (($x == $y) && (2 == true) {
计算您的parens或使用有助于此的IDE。也不要在没有任何空格的情况下编写代码。可读性很重要。
您无法在表达式中使用花括号。如果你混淆括号和卷曲,它就不符合语言语法:
⇓
$var = 5 * {7 + $x};
标识符构造有一些例外,例如局部范围变量${references}
。
这非常罕见。但是对于复杂的变量表达式,您可能还会得到{
和}
个解析器投诉:
⇓
print "Hello {$world[2{]} !";
虽然在这种情况下出现意外}
的可能性较高。
}
获得&#34;意外}
&#34;错误,您过早关闭了代码块。
任何未终止的表达都可能发生。
如果函数/代码块中的最后一行缺少尾随;
分号:
function whatever() {
doStuff()
} ⇧
此处解析器无法判断您是否仍想将+ 25;
添加到函数结果或其他内容。
{
当代码块}
过早关闭,或者您忘记了{
开放时,您有时会看到此解析器错误:
function doStuff() {
if (true) ⇦
print "yes";
}
} ⇧
在上面的代码段中,if
没有开放{
大括号。因此,下面的}
结束变得多余。因此,用于该函数的下一个结束}
无法与原始的开放{
大括号相关联。
如果没有适当的代码缩进,这些错误就更难找到。使用IDE和括号匹配。
{
,期待(
需要条件/声明标题和代码块的语言结构将触发此错误。
例如,不允许if
without condition:
⇓
function whatever {
}
你也不能{{3}}。
⇓
if {
}
显然,这没有任何意义。通常的嫌疑人for
/ foreach
,while
/ do
等同样的事情。
如果您遇到此特定错误,您肯定应该查看一些手动示例。
答案 6 :(得分:14)
当PHP谈到“意外的$end
”时,这意味着您的代码提前结束。 (从字面上看,这个消息有点误导。它不是一个名为“$ end”的变量,有时候是新人所假设的。它指的是“文件结束”, EOF 。)
原因:代码块/函数或类声明的不平衡
{
和}
。
关于前面的代码块关闭缺少}
大括号的几乎总是。
再次,使用适当的缩进来避免此类问题。
使用支架匹配的IDE,找出}
不对的位置。
大多数IDE和文本编辑器都有键盘快捷键:
大多数IDE还突出显示匹配大括号,括号和括号。 这使得检查它们的相关性非常容易:
对于未终止的表达式或语句,也可能出现Unexpected $end
语法/解析器错误:
$var = func(1,
?>
EOF 所以,先看一下脚本的结尾。对于任何PHP脚本中的最后一个语句,尾随;
通常是多余的。但你应该有一个。正是因为它缩小了这种语法问题。
HEREDOC or NOWDOC字符串会出现另一种常见情况。使用前导空格,制表符等忽略终止标记:
print <<< END
Content...
Content....
END;
# ↑ terminator isn't exactly at the line start
因此,解析器假定HEREDOC字符串一直持续到文件结尾(因此“意外的$ end”)。几乎所有的IDE和语法高亮的编辑器都会使这个显而易见或警告它。
如果在字符串中使用\
,则它具有特殊含义。这称为“Escape Character”,通常告诉解析器按字面意思取下一个字符。
示例:echo 'Jim said \'Hello\'';
将打印Jim said 'hello'
如果您转义字符串的结束引号,则结尾引用将按字面意思而不是按预期进行,即作为字符串的一部分的可打印引用而不是关闭字符串。在打开下一个字符串或脚本结束后,这通常会显示为解析错误。
在Windows中指定路径时出现非常常见的错误:"C:\xampp\htdocs\"
错误。您需要"C:\\xampp\\htdocs\\"
。
在模板中使用语句/代码块的替代语法时,您会看到此语法错误。例如,使用if:
和else:
以及缺少endif;
。
答案 7 :(得分:13)
条件控制块if
,elseif
和else
遵循一个简单的结构。当您遇到语法错误时,它很可能只是无效的块嵌套→缺少{
花括号}
- 或者太多。
{
或}
不匹配的代码括号对于格式较差的代码是常见的,例如:
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
- 表达式。
IF
不能在表达式一个令人惊讶的频繁新手错误是尝试在表达式中使用if
语句,例如print语句:
⇓
echo "<a href='" . if ($link == "example.org") { echo …
当然这是无效的。
您可以使用a ternary conditional,但要注意可读性影响。
echo "<a href='" . ($link ? "http://yes" : "http://no") . "</a>";
否则打破这样的输出构造:使用multiple if
s and echo
s。
更好的是,使用temporary variables,并将您的条件放在:
if ($link) { $href = "yes"; } else { $href = "no"; }
echo "<a href='$href'>Link</a>";
为这种情况定义函数或方法通常也是有意义的。
现在这种情况不太常见,但有些程序员甚至会尝试将if
视为可以返回结果:
$var = if ($x == $y) { "true" };
在结构上与在字符串连接/表达式中使用if
相同。
您必须在代码块中使用作业:
if ($x == $y) { $var = "true"; }
或者,可以采用?:
三元比较。
您在条件中cannot nest an if
:
⇓
if ($x == true and (if $y != false)) { ... }
这显然是多余的,因为and
(或or
)已经允许进行链接比较。
;
分号再一次:每个控制块都需要是一个声明。如果前面的代码段没有以分号结束,那么这是一个有保证的语法错误:
⇓
$var = 1 + 2 + 3
if (true) { … }
顺便说一下,{…}
代码块中的最后一行也需要一个分号。
现在责怪特定的编码风格可能是错误的,因为这个陷阱太容易被忽视了:
⇓
if ($x == 5);
{
$y = 7;
}
else ←
{
$x = -1;
}
这种情况比你想象的更频繁。
if ()
expression with ;
时,它将执行一个void语句。 ;
变成了自己的{}
!{…}
块因此与if
分离,并且始终会运行。else
不再与开放的if
结构有关系,
这就是为什么这会导致意外的T_ELSE语法错误。
这也解释了这种语法错误的同样微妙的变化:
if ($x) { x_is_true(); }; else { something_else(); };
代码块;
之后的{…}
终止整个if
构造,在句法上切断else
分支。
语法允许在{
/ }
/ if
分支中的代码块中省略大括号elseif
... else
。遗憾的是,对于非反向编码人员来说,这种语法风格很常见。 (在错误的假设下,输入或读取的速度更快)。
然而,这很可能会绊倒语法。迟早会有其他语句进入if / else分支:
if (true)
$x = 5;
elseif (false)
$x = 6;
$y = 7; ←
else
$z = 0;
但是要实际使用代码块, 确实有 来编写{
... }
这样的代码!
即使是经验丰富的程序员也会避免这种无法使用的语法,或者至少 将其理解为规则的一个例外。
提醒自己的一件事当然是conditional order。
if ($a) { … }
else { … }
elseif ($b) { … }
↑
您可以拥有任意数量的elseif
,但else
has to go last。这就是它的原因。
作为mentioned above,您不能在类声明中拥有控制语句:
class xyz {
if (true) {
function ($var) {}
}
在这种情况下,您要么forgot a function定义,要么过早关闭}
。
混合使用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 if
和elseif
/ else
结构代币:
if (true) {
}
echo "in between"; ←
elseif (false) {
}
?> text <?php ←
else {
}
任何一个都只能出现在{…}
个代码块中,而不能出现在控制结构标记之间。
if
和else
分支之间跳转时的状态。你也不能在不同的控制结构之间分配if / else :
foreach ($array as $i) {
if ($i) { … }
}
else { … }
if
和else
之间没有syntactic relation。 foreach
词汇范围在}
结束,因此if
结构无法继续。
如果有人抱怨意外的T_ENDIF,您可以使用其他语法风格if:
⋯elseif:
⋯else:
⋯endif;
。你应该三思而后行。
一个常见的陷阱令人感到困惑similar :
colon for a ;
semicolon。 (涵盖在&#34;分号太早&#34;)
由于缩进在模板文件中难以跟踪,因此在使用替代语法时越多 - 您的endif;
与任何if:
都不匹配。
使用} endif;
是 doubled if
- 终止符。
虽然&#34;意外的$ end&#34;通常是忘记结束}
花括号的价格。
因此,这不是语法错误,但在此上下文中值得一提:
⇓
if ($x = true) { }
else { do_false(); }
那不是==
/===
comparison, but an =
assignment。这是相当微妙的,很容易导致一些用户无助地编辑整个条件块。当你遇到逻辑错误/不当行为时,请先注意意外的任务。
答案 8 :(得分:11)
控制if
,foreach
,for
,while
,list
,global
,return
等构造,{ {1}},do
,print
只能用作对帐单。他们通常独自居住。
如果解析器抱怨控制语句,那么上一行中普遍有missed a semicolon:
echo
解决方案:查看上一行;添加分号。
发生这种情况的另一个位置是in class declarations。在类部分中,您只能列出属性初始化和方法部分。没有代码可以驻留在那里。
⇓
$x = myfunc()
if (true) {
此类语法错误通常会导致错误嵌套的class xyz {
if (true) {}
foreach ($var) {}
和{
。特别是当功能代码块过早关闭时。
大多数语言结构都可以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。
这同样适用于if
,for
,while
,global
以及较小的echo
。
list
⇓
echo 123, echo 567, "huh?";
是一种可以在表达式上下文中使用的内置语言。 (但很少有道理。)
您也不能将print()
或do
以及其他语言结构用于用户定义的函数或类名。 (也许在PHP7中。但即使这样也不可取。)
答案 9 :(得分:10)
<
>
比较运算符,例如==
,>=
,===
,!=
,<>
,!==
和<=
或{ {1}}和<
主要应仅用于表达式,例如>
表达式。如果解析器抱怨它们,那么它通常意味着不正确的配对或不匹配if
(
围绕它们。
特别是对于多重比较的)
语句,您必须注意正确计算opening and closing parenthesis:
if
此处此 ⇓
if (($foo < 7) && $bar) > 5 || $baz < 9) { ... }
↑
条件已由if
一旦你的比较变得足够复杂,通常有助于将它分成多个嵌套的)
结构。
一个普通的新人是pitfal试图将isset()
或empty()
与比较结合起来:
if
甚至:
⇓
if (empty($_POST["var"] == 1)) {
这对PHP没有意义,因为 ⇓
if (isset($variable !== "value")) {
和isset
是只接受变量名的语言结构。比较结果也没有意义,因为输出只是/已经是布尔值。
empty
数组运算符>=
大于或等于
两个运营商看起来有些相似,所以他们有时会混淆:
=>
您只需记住此比较运算符被称为“大于或相等”以使其正确。
如果它们属于相同的变量名,则也无法组合两个比较:
⇓
if ($var => 5) { ... }
PHP无法推断您是想再次比较初始变量。表达式通常根据operator precedence进行配对,因此在看到 ⇓
if ($xyz > 5 and < 100)
时,原始变量只剩下一个布尔结果。
您无法与具有一行运算符的变量进行比较:
<
这必须分为两个比较,每个比较针对 ⇓
$reult = (5 < $x < 10);
。
这实际上更多是列入黑名单的表达式(由于等效的运算符关联性)。它在几种C风格的语言中在语法上有效,但PHP也不会将其解释为预期的比较链。
$x
>
大于<
或小于>
的运算符没有自定义<
标记符名称。虽然它们可能像其他人一样错位,但您经常会看到解析器因错误引用字符串和混合HTML而抱怨它们:
T_XXX
这相当于一个字符串 ⇓
print "<a href='z">Hello</a>";
↑
被比较"<a href='z"
到文字常量>
,然后是另一个Hello
比较。或者至少是PHP如何看待它。实际的原因和语法错误是过早的字符串<
终止。
也无法嵌套PHP开始标记:
"
另见:
答案 10 :(得分:6)
如果您尝试在PHP 7之前的PHP版本中使用空合并运算符??
,则会出现此错误。
<?= $a ?? 2; // works in PHP 7+
<?= (!empty($a)) ? $a : 2; // All versions of PHP
可以为空的类型发生类似的错误,如:
function add(?int $sum): ?int {
这再次表明正在使用过时的PHP版本(CLI版本php -v
或网络服务器绑定了一个phpinfo();
)。
答案 11 :(得分:5)
令牌T_LNUMBER
指的是“长”/数字。
在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
不同。)
array declarations时也会发生意外的长时间 - 当缺少,
逗号时:
# ↓ ↓
$xy = array(1 2 3);
或者类似于函数调用和声明,以及其他构造:
func(1, 2 3);
function xy($z 2);
for ($i=2 3<$z)
因此,通常会因为分隔列表或表达式而遗漏;
或,
。
同样,misquoted strings是流浪数字的常见来源:
# ↓ ↓
echo "<td colspan="3">something bad</td>";
此类案件应该或多或少地被视为Unexpected T_STRING错误。
函数,类和namespaces都不能以数字开头命名:
↓
function 123shop() {
与变量名称几乎相同。
答案 12 :(得分:2)
这可能是由于变量名中包含无效字符引起的。变量名称必须遵循以下规则:
变量名称与PHP中的其他标签遵循相同的规则。有效的变量名称以字母或下划线开头,后跟任意数量的字母,数字或下划线。作为正则表达式,它将这样表示:“ [[a-zA-Z_ \ x7f- \ xff] [a-zA-Z0-9_ \ x7f- \ xff] *”
答案 13 :(得分:1)
continue
是一个语句(例如for或if),并且必须独立出现。它不能用作表达式的一部分。部分是因为continue不返回值,但是在表达式中,每个子表达式都必须得到某个值,因此整个表达式都将得到一个值。这就是语句和表达式之间的区别。
这意味着continue
不能用于三元语句或任何需要返回值的语句。
当然break;
也一样。它在表达式上下文中也不可用,而是严格的语句(与foreach
或if
块处于同一级别)。
现在,对于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)
语法使用冒号-如果没有冒号,则会发生上述错误
<?php while($query->fetch()): ?>
....
<?php endwhile; ?>
该语法的替代方法是使用大括号
<?php while($query->fetch()) { ?>
....
<?php } ?>
答案 16 :(得分:0)
错误地将类静态引用Parse error: syntax error, unexpected ':'
编写为Class::$Variable
可能导致以Class:$Variable
开头的错误消息。
答案 17 :(得分:0)
:
意外的 ':',期待 ',' 或 ')'
如果尝试在 PHP < 8 版本中使用 PHP 8 的新命名参数功能,则会发生此错误:
$table->string(column:'Name');
解决方案:
::
分隔符以解析错误开头的错误消息:语法错误,意外的“:”可能是由于错误地将类静态引用 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 将不断向您显示错误。只有在您保存文件后,错误信息才会消失。