Statements
General
Syntax
statement: compound-statement named-label-statement expression-statement selection-statement iteration-statement jump-statement try-statement declare-statement echo-statement unset-statement const-declaration function-definition class-declaration interface-declaration trait-declaration namespace-definition namespace-use-declaration global-declaration function-static-declaration
Compound Statements
Syntax
compound-statement: { statement-listopt } statement-list: statement statement-list statement
Semantics
A compound statement allows a group of zero or more statements to be treated syntactically as a single statement. A compound statement is often referred to as a block.
Examples
if (condition)
{ // braces are needed as the true path has more than one statement
// statement-1
// statement-2
}
else
{ // braces are optional as the false path has only one statement
// statement-3
}
// -----------------------------------------
while (condition)
{ // the empty block is equivalent to a null statement
}
Labeled Statements
Syntax
named-label-statement: name :
Constraints
Named labels must be unique within a function.
Semantics
A named label can be used as the target of a goto
statement.
The presence of a label does not by itself alter the flow of execution.
Expression Statements
Syntax
expression-statement: expressionopt ;
Semantics
If present, expression is evaluated for its side effects, if any, and any resulting value is discarded. If expression is omitted, the statement is a null statement, which has no effect on execution.
Examples
$i = 10; // $i is assigned the value 10; result (10) is discarded
++$i; // $i is incremented; result (11) is discarded
$i++; // $i is incremented; result (11) is discarded
DoIt(); // function DoIt is called; result (return value) is discarded
// -----------------------------------------
$i; // no side effects, result is discarded. Vacuous but permitted
123; // likewise for this one and the two statements following
34.5 * 12.6 + 11.987;
TRUE;
// -----------------------------------------
function findValue($table, $value) // where $table is 2x3 array
{
for ($row = 0; $row <= 1; ++$row)
{
for ($colm = 0; $colm <= 2; ++$colm)
{
if ($table[$row][$colm] == $value)
{
// ...
goto done;
}
}
}
// ...
done:
; // null statement needed as a label must precede a statement
}
Selection Statements
General
Syntax
selection-statement: if-statement switch-statement
Semantics
Based on the value of a controlling expression, a selection statement selects among a set of statements.
The if
Statement
Syntax
if-statement: if ( expression ) statement elseif-clauses-1opt else-clause-1opt if ( expression ) : statement-list elseif-clauses-2opt else-clause-2opt endif ; elseif-clauses-1: elseif-clause-1 elseif-clauses-1 elseif-clause-1 elseif-clause-1: elseif ( expression ) statement else-clause-1: else statement elseif-clauses-2: elseif-clause-2 elseif-clauses-2 elseif-clause-2 elseif-clause-2: elseif ( expression ) : statement-list else-clause-2: else : statement-list
Semantics
The two forms of the if
statement are equivalent; they simply provide
alternate styles.
The result of the controlling expression expression will be converted to type bool
if it does not have this type.
If expression is TRUE
, the statement that follows immediately is
executed. Otherwise, if an elseif
clause is present its expression is evaluated
in turn, and if it is TRUE
, the statement immediately following the elseif
is executed.
This repeats for every elseif
clause in turn. If none of those tests TRUE
, if an
else
clause is present the statement immediately following the else
is
executed.
An else
clause is associated with the lexically nearest preceding if
or
elseif
that is permitted by the syntax.
Examples
if ($count > 0)
{
...
...
...
}
// -----------------------------------------
goto label1;
echo "Unreachable code\n";
if ($a)
{
label1:
...
}
else
{
...
}
// -----------------------------------------
if (1)
...
if (0)
...
else // this else does NOT go with the outer if
...
if (1)
{
...
if (0)
...
}
else // this else does go with the outer if
...
The switch
Statement
Syntax
switch-statement: switch ( expression ) { case-statementsopt } switch ( expression ) : case-statementsopt endswitch; case-statements: case-statement case-statementsopt default-statement case-statementsopt case-statement: case expression case-default-label-terminator statement-listopt default-statement: default case-default-label-terminator statement-listopt case-default-label-terminator: : ;
Constraints
There must be at most one default label.
Semantics
The two forms of the switch
statement are equivalent; they simply
provide alternate styles.
Based on the value of its expression, a switch
statement transfers
control to a case label, to a default label, if one
exists; or to the statement immediately following the end of the switch
statement. A case or default label is only reachable directly within its
closest enclosing switch
statement.
On entry to the switch
statement, the controlling expression is
evaluated and then compared with the value of the case label expression
values, in lexical order, using the same semantics as ==
.
If one matches, control transfers to the
statement following the corresponding case label. If there is no match,
then if there is a default label, control transfers to the statement
following that; otherwise, control transfers to the statement
immediately following the end of the switch
statement. If a switch
contains more than one case label whose values compare equal to the
controlling expression, the first in lexical order is considered the
match.
An arbitrary number of statements can be associated with any case or
default label. In the absence of a break
statement at the end
of a set of such statements, the execution continues into any following
statements, ignoring the associated labels. If all cases and the default end in break
and there are no duplicate-valued case labels, the order of case and
default labels is insignificant.
Case-label values can be runtime expressions, and the types of sibling case-label values need not be the same.
Switches may be nested, in which case, each switch
has its own set of
switch
clauses.
Examples
$v = 10;
switch ($v)
{
default:
echo "default case: \$v is $v\n";
break; // break ends "group" of default statements
case 20:
echo "case 20\n";
break; // break ends "group" of case 20 statements
case 10:
echo "case 10\n"; // no break, so execution continues to the next label's "group"
case 30:
echo "case 30\n"; // no break, but then none is really needed either
}
// -----------------------------------------
$v = 30;
switch ($v)
{
case 30.0: // <===== this case matches with 30
echo "case 30.0\n";
break;
default:
echo "default case: \$v is $v\n";
break;
case 30: // <===== rather than this case matching with 30
echo "case 30\n";
break;
}
// -----------------------------------------
switch ($v)
{
case 10 + $b: // non-constant expression
// ...
case $v < $a: // non-constant expression
// ...
// ...
}
Iteration Statements
General
Syntax
iteration-statement: while-statement do-statement for-statement foreach-statement
The while
Statement
Syntax
while-statement: while ( expression ) statement while ( expression ) : statement-list endwhile ;
Semantics
The two forms of the while
statement are equivalent; they simply provide
alternate styles.
The result of the controlling expression expression is converted to type bool
if it does not have this type.
If expression tests TRUE
, the statement that follows immediately is
executed, and the process is repeated. If expression tests FALSE
,
control transfers to the point immediately following the end of the
while
statement. The loop body is executed zero or more
times.
Examples
$i = 1;
while ($i <= 10):
echo "$i\t".($i * $i)."\n"; // output a table of squares
++$i;
endwhile;
// -----------------------------------------
while (TRUE)
{
// ...
if ($done)
break; // break out of the while loop
// ...
}
The do
Statement
Syntax
do-statement: do statement while ( expression ) ;
(Note: There is no alternate syntax).
Constraints
The controlling expression expression must have type bool
or be
implicitly convertible to that type.
Semantics
First, statement is executed and then expression is evaluated.
The result of the controlling expression expression is converted to type bool
if it does not have this type.
If the value tests TRUE
, the process is repeated. If expression tests FALSE
,
control transfers to the point immediately following the end of the do
statement. The loop body, statement, is executed one or more times.
Examples
$i = 1;
do
{
echo "$i\t".($i * $i)."\n"; // output a table of squares
++$i;
}
while ($i <= 10);
The for
Statement
Syntax
for-statement: for ( for-initializeropt ; for-controlopt ; for-end-of-loopopt ) statement for ( for-initializeropt ; for-controlopt ; for-end-of-loopopt ) : statement-list endfor ; for-initializer: for-expression-group for-control: for-expression-group for-end-of-loop: for-expression-group for-expression-group: expression for-expression-group , expression
Note: Unlike C/C++, PHP does not support a comma operator, per se.
However, the syntax for the for
statement has been extended from that of
C/C++ to achieve the same results in this context.
Semantics
The two forms of the for
statement are equivalent; they simply provide
alternate styles.
The group of expressions in for-initializer is evaluated once,
left-to-right, for their side effects. Then the group of expressions in
for-control is evaluated left-to-right (with all but the right-most
one for their side effects only), with the right-most expression’s value
being converted to type bool
.
If the result is TRUE
, statement is executed, and the group
of expressions in for-end-of-loop is evaluated left-to-right, for
their side effects only. Then the process is repeated starting with
for-control. Once the right-most expression in for-control is
FALSE
, control transfers to the point immediately following the end of
the for
statement. The loop body, statement, is executed zero or more
times.
If for-initializer is omitted, no action is taken at the start of the
loop processing. If for-control is omitted, this is treated as if
for-control was an expression with the value TRUE
. If
for-end-of-loop is omitted, no action is taken at the end of each
iteration.
Examples
for ($i = 1; $i <= 10; ++$i)
{
echo "$i\t".($i * $i)."\n"; // output a table of squares
}
// -----------------------------------------
// omit 1st and 3rd expressions
$i = 1;
for (; $i <= 10;):
echo "$i\t".($i * $i)."\n"; // output a table of squares
++$i;
endfor;
// -----------------------------------------
// omit all 3 expressions
$i = 1;
for (;;)
{
if ($i > 10)
break;
echo "$i\t".($i * $i)."\n"; // output a table of squares
++$i;
}
// -----------------------------------------
// use groups of expressions
for ($a = 100, $i = 1; ++$i, $i <= 10; ++$i, $a -= 10)
{
echo "$i\t$a\n";
}
The foreach
Statement
Syntax
foreach-statement: foreach ( foreach-collection-name as foreach-keyopt foreach-value ) statement foreach ( foreach-collection-name as foreach-keyopt foreach-value ) : statement-list endforeach ; foreach-collection-name: expression foreach-key: expression => foreach-value: &opt expression list-intrinsic
Constraints
The result of the expression foreach-collection-name must be a collection, i.e. either array or object implementing Traversable.
expression in foreach-value and foreach-key should designate a variable.
Semantics
The two forms of the foreach
statement are equivalent; they simply
provide alternate styles.
The foreach statement iterates over the set of elements in the
collection designated by foreach-collection-name, starting at the
beginning, executing statement each iteration. On each iteration, if
the &
is present in foreach-value, the variable designated by the
corresponding expression is made an alias to the current element. If
the &
is omitted, the value of the current element is assigned to the
corresponding variable. The loop body, statement, is executed zero or
more times. After the loop terminates, the variable designated by expression
in foreach-value has the same value as it had after the final iteration, if any.
If foreach-key is present, the variable designated by its expression is assigned the current element’s key value.
In the list-intrinsic case, a value that is an array is split into individual elements.
Examples
$colors = array("red", "white", "blue");
foreach ($colors as $color):
// ...
endforeach;
// -----------------------------------------
foreach ($colors as $key => $color)
{
// ...
}
// -----------------------------------------
// Modify the local copy of an element's value
foreach ($colors as $color)
{
$color = "black";
}
// -----------------------------------------
// Modify the the actual element itself
foreach ($colors as &$color) // note the &
{
$color = "black";
}
Jump Statements
General
Syntax
jump-statement: goto-statement continue-statement break-statement return-statement throw-statement
The goto
Statement
Syntax
goto-statement: goto name ;
Constraints
The name in a goto
statement must be that of a named label located
somewhere in the current script. Control must not be transferred into or
out of a function, or into an iteration statement or a switch
statement.
A goto
statement must not attempt to transfer control out of a
finally-block.
Semantics
A goto
statement transfers control unconditionally to the named label.
A goto
statement may break out of a construct that is fully contained
within a finally-block.
Examples
function findValue($table, $v) // where $table is 2x3 array
{
for ($row = 0; $row <= 1; ++$row)
{
for ($colm = 0; $colm <= 2; ++$colm)
{
if ($table[$row][$colm] == $v)
{
echo "$v was found at row $row, column $colm\n";
goto done; // not quite the same as break 2!
}
}
}
echo "$v was not found\n";
done:
; // note that a label must always precede a statement
}
The continue
Statement
Syntax
continue-statement: continue breakout-levelopt ; breakout-level: integer-literal ( breakout-level )
Constraints
The breakout level must be greater than zero, and it must not exceed the level of
actual enclosing iteration and/or switch
statements.
A continue
statement must not attempt to break out of a finally-block.
Semantics
A continue
statement terminates the execution of the innermost enclosing
iteration or switch
statement.
breakout-level specifies which of these statements is targeted, with innermost being assigned
number 1
and containing statements having levels increasing by 1.
A continue
statement terminates the execution of one or more enclosing
iteration or switch
statements,
up to the specified level. If the statement at the breakout-level is an iteration statement,
the next iteration (if any) of the iteration statement is started.
If that statement is a for
statement and it has a for-end-of-loop, its
end-of-loop expression group for the current iteration is evaluated first. If it
is a switch
statement, a warning is emitted and the behavior is the same as a
break
statement at the same breakout-level. If
breakout-level is omitted, a level of 1 is assumed.
A continue
statement may break out of a construct that is fully
contained within a finally-block.
Examples
for ($i = 1; $i <= 5; ++$i)
{
if (($i % 2) == 0)
continue;
echo "$i is odd\n";
}
The break
Statement
Syntax
break-statement: break breakout-levelopt ;
Constraints
The breakout level must be greater than zero, and it must not exceed the level of
actual enclosing iteration and/or switch
statements.
A break
statement must not attempt to break out of a finally-block.
Semantics
A break
statement terminates the execution of one or more enclosing
iteration or []switch
](#the-switch-statement) statements. The number of levels
broken out is specified by breakout-level. If breakout-level is
omitted, a level of 1 is assumed.
A break
statement may break out of a construct that is fully contained
within a finally-block.
Examples
$i = 1;
for (;;)
{
if ($i > 10)
break;
// ...
++$i;
}
// -----------------------------------------
for ($row = 0; $row <= 1; ++$row)
{
for ($colm = 0; $colm <= 2; ++$colm)
{
if (some-condition-set)
{
break 2;
}
// ...
}
}
// -----------------------------------------
for ($i = 10; $i <= 40; $i +=10)
{
switch($i)
{
case 10: /* ... */; break; // breaks to the end of the switch
case 20: /* ... */; break 2; // breaks to the end of the for
case 30: /* ... */; break; // breaks to the end of the switch
}
}
The return
Statement
Syntax
return-statement: return expressionopt ;
Semantics
A return
statement from within a function terminates the execution of
that function normally, and depending on how the function was defined,
it returns the value of expression to the function’s caller
by value or byRef. If expression is omitted the value NULL
is used.
If execution flows into the closing brace (}
) of a function, return NULL;
is implied.
Explicit return
statements with expression given are not permitted within a
function with a void
return type and cause
a fatal error.
A function may have any number of return
statements, whose returned
values may have different types.
If an undefined variable is returned byRef, that variable becomes
defined, with a value of NULL
.
A return
statement is permitted in a try-block
and a catch-block and in finally-block.
Using a return
statement inside a finally-block will override any other
return
statement or thrown exception from the try-block and all its
catch-blocks. Code execution in the parent stack will continue as if
the exception was never thrown.
If an uncaught exception exists when a finally-block is executed, if
that finally-block executes a return
statement, the uncaught exception
is discarded.
A return
statement may occur in a script outside any function. In an
included file,
such statement terminates processing of that script file and
returns control to the including file. If expression is present, that
is the value returned; otherwise, the value NULL
is returned. If
execution flows to the end of the script, return 1;
is implied. However,
if execution flows to the end of the top level of a script, return 0;
is
implied. Likewise, if expression is omitted at the top level. (See also
exit
).
Returning from a constructor or destructor behaves just like returning from a function.
A return
statement inside a generator function causes the generator to
terminate.
A generator function can contain a statement of the form return
expression ;
. The value this returns
can be fetched using the method Generator::getReturn
, which can only be called once the generator
has finishing yielding values. The value cannot be returned byRef.
Return statements can also be used in the body of anonymous functions.
return
also terminates the execution of source code given to the intrinsic
eval
.
Examples
function f() { return 100; } // f explicitly returns a value
function g() { return; } // g explicitly returns an implicit NULL
function h() { } // h implicitly returns NULL
// -----------------------------------------
// j returns one of three dissimilarly-typed values
function j($x)
{
if ($x > 0)
{
return "Positive";
}
else if ($x < 0)
{
return -1;
}
// for zero, implied return NULL
}
function &compute() { ...; return $value; } // returns $value byRef
// -----------------------------------------
class Point
{
private static $pointCount = 0;
public static function getPointCount()
{
return self::$pointCount;
}
...
}
Implementation Notes
Although expression is a full expression, and there is a
sequence point at the end of that expression,
a side effect need not be executed if it can be determined that
no other program code relies on its having happened. (For example, in
the cases of return $a++;
and return ++$a;
, it is obvious what value
must be returned in each case, but if $a
is a variable local to the
enclosing function, $a
need not actually be incremented.
The throw
Statement
Syntax
throw-statement: throw expression ;
Constraints
The type of expression must be Exception or a subclass of that class.
expression must be such that an alias to it can be created.
Semantics
A throw
statement throws an exception immediately and unconditionally.
Control never reaches the statement immediately following the throw. See
exception handling and try-statement
for more details of throwing and catching exceptions, and how uncaught exceptions are dealt with.
Rather than handle an exception, a catch-block may (re-)throw the same exception that it caught, or it can throw an exception of a different type.
Examples
throw new Exception;
throw new Exception("Some message", 123);
class MyException extends Exception { ... }
throw new MyException;
The try
Statement
Syntax
try-statement: try compound-statement catch-clauses try compound-statement finally-clause try compound-statement catch-clauses finally-clause catch-clauses: catch-clause catch-clauses catch-clause catch-clause: catch ( catch-name-list variable-name ) compound-statement catch-name-list: qualified-name catch-name-list | qualified-name finally-clause: finally compound-statement
Constraints
Each qualified-name inside a catch-name-list must name a type derivated from
Exception
.
Semantics
In a catch-clause, variable-name designates an exception variable passed in by value. This variable corresponds to a local variable with a scope that extends over the catch-block. During execution of the catch-block, the exception variable represents the exception currently being handled.
Once an exception is thrown, the Engine searches for the nearest catch-block that can handle the exception. The process begins at the current function level with a search for a try-block that lexically encloses the throw point. All catch-blocks associated with that try-block are considered in lexical order. If no catch-block is found that can handle the run-time type of the exception, the function that called the current function is searched for a lexically enclosing try-block that encloses the call to the current function. This process continues until a catch-block is found that can handle the current exception.
The matching is done by considering the classes specified by qualified-name in catch-name-list and comparing it to the type of the exception. If the exception is an instance of one of the specified classes then the clause matches.
If a matching catch-block is located, the Engine prepares to transfer control to the first statement of that catch-block. However, before execution of that catch-block can start, the Engine first executes, in order, any finally-blocks associated with try-blocks nested more deeply than the one that caught the exception.
If no matching catch-block is found, the exception is uncaught and the behavior is implementation-defined.
Examples
function getTextLines($filename)
{
$infile = fopen($filename, 'r');
if ($infile == FALSE) { /* deal with an file-open failure */ }
try
{
while ($textLine = fgets($infile)) // while not EOF
{
yield $textLine; // leave line terminator attached
}
}
finally
{
fclose($infile);
}
}
// -----------------------------------------
class DeviceException extends Exception { ... }
class DiskException extends DeviceException { ... }
class RemovableDiskException extends DiskException { ... }
class FloppyDiskException extends RemovableDiskException { ... }
try
{
process(); // call a function that might generate a disk-related exception
}
catch (FloppyDiskException $fde) { ... }
catch (RemovableDiskException $rde) { ... }
catch (DiskException $de) { ... }
catch (DeviceException $dve) { ... }
finally { ... }
The declare
Statement
Syntax
declare-statement: declare ( declare-directive ) statement declare ( declare-directive ) : statement-list enddeclare ; declare ( declare-directive ) ; declare-directive: ticks = literal encoding = literal strict_types = literal
Constraints
The literal for ticks must designate a value that is, or can be converted, to an integer having a non-negative value.
The literal for encoding must designate a string whose value names an 8-bit-character encoding.
Except for white space, a declare-statement in a script that specifies character-encoding must be the first thing in that script.
The literal for strict_types should be either 0
or 1
. Only the statement-less
form can be used for strict_types declare. The strict_types declare should be the first statement
in the script, excepting other declare statements.
Semantics
The first two forms of the declare
statement are equivalent; they simply
provide alternate styles.
The declare
statement sets an execution directive for its statement
body, or for the ;
-form, for the remainder of the script or until the
statement is overridden by another declare-statement, whichever comes
first.
ticks: as the parser is executing, certain statements are considered
tickable. For every tick-count ticks, an event occurs, which can be
serviced by the function previously registered by the library function
register_tick_function
.
Tick event monitoring can be disabled by calling the library function
unregister_tick_function
.
This facility allows a profiling mechanism to be developed.
encoding: character encoding can be specified on a script-by-script basis using the encoding directive. The joint ISO and IEC standard ISO/IEC 8859 standard series specifies a number of 8-bit-character encodings whose names can be used with this directive. This directive applies only to the file it appears in, and does not affect the included files.
strict_types: if set to 1
, scalar type checking for function calls will be
checked using strict mode. If set to 0
, the coercive mode (default) is used.
This directive applies only to the file it appears in, and does not affect the included files.
Examples
declare(ticks = 1) { ... }
declare(encoding = 'ISO-8859-1'); // Latin-1 Western European
declare(encoding = 'ISO-8859-5'); // Latin/Cyrillic
The echo
Statement
Syntax
echo-statement: echo expression-list ; expression-list: expression expression-list , expression
Constraints
The expression value must be
convertable to a string.
In particular, it should not be an array and if it is an object, it must implement
a __toString
method.
Semantics
After converting each of its expressions’ values to strings, if
necessary, echo
concatenates them in order given, and writes the
resulting string to STDOUT
. Unlike print
, it does
not produce a result.
See also: double quoted strings and heredoc documents, conversion to string.
Examples
$v1 = TRUE;
$v2 = 123;
echo '>>' . $v1 . '|' . $v2 . "<<\n"; // outputs ">>1|123<<"
echo '>>' , $v1 , '|' , $v2 , "<<\n"; // outputs ">>1|123<<"
echo ('>>' . $v1 . '|' . $v2 . "<<\n"); // outputs ">>1|123<<"
$v3 = "qqq{$v2}zzz";
echo "$v3\n";
The unset
Statement
Syntax
unset-statement: unset ( variable-list ,opt ) ;
Semantics
This statement unsets the variables designated by each variable in variable-list. No value is returned. An attempt to unset a non-existent variable (such as a non-existent element in an array) is ignored.
When called from inside a function, this statement behaves, as follows:
- For a variable declared
global
in that function,unset
removes the alias to that variable from the scope of the current call to that function. The global variable remains set. (To unset the global variable, use unset on the corresponding$GLOBALS
array entry. - For a variable passed byRef to that function,
unset
removes the alias to that variable from the scope of the current call to that function. Once the function returns, the passed-in argument variable is still set. - For a variable declared static in that function,
unset
removes the alias to that variable from the scope of the current call to that function. In subsequent calls to that function, the static variable is still set and retains its value from call to call.
Any visible instance property may be unset, in which case, the property is removed from that instance.
If this statement is used with an expression that designates a dynamic
property, then if the class of that property has an __unset
method, that method is called.
Examples
unset($v);
unset($v1, $v2, $v3);
unset($x->m); // if m is a dynamic property, $x->__unset("m") is called