mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00
1649 lines
42 KiB
XML
1649 lines
42 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Functions</title>
|
|
|
|
<sect1 xml:id="functions.user-defined">
|
|
<title>User-defined functions</title>
|
|
|
|
<para>
|
|
A function may be defined using syntax such as the following:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Pseudo code to demonstrate function uses</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
|
|
{
|
|
echo "Example function.\n";
|
|
return $retval;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
Any valid PHP code may appear inside a function, even other
|
|
functions and <link linkend="language.oop5.basic.class">class</link>
|
|
definitions.
|
|
</simpara>
|
|
<para>
|
|
Function names follow the same rules as other labels in PHP. A
|
|
valid function name starts with a letter or underscore, followed
|
|
by any number of letters, numbers, or underscores. As a regular
|
|
expression, it would be expressed thus:
|
|
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
|
|
</para>
|
|
&tip.userlandnaming;
|
|
<simpara>
|
|
Functions need not be defined before they are referenced,
|
|
<emphasis>except</emphasis> when a function is conditionally defined as
|
|
shown in the two examples below.
|
|
</simpara>
|
|
<para>
|
|
When a function is defined in a conditional manner such as the two
|
|
examples shown. Its definition must be processed <emphasis>prior</emphasis>
|
|
to being called.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Conditional functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$makefoo = true;
|
|
|
|
/* We can't call foo() from here
|
|
since it doesn't exist yet,
|
|
but we can call bar() */
|
|
|
|
bar();
|
|
|
|
if ($makefoo) {
|
|
function foo()
|
|
{
|
|
echo "I don't exist until program execution reaches me.\n";
|
|
}
|
|
}
|
|
|
|
/* Now we can safely call foo()
|
|
since $makefoo evaluated to true */
|
|
|
|
if ($makefoo) foo();
|
|
|
|
function bar()
|
|
{
|
|
echo "I exist immediately upon program start.\n";
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Functions within functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo()
|
|
{
|
|
function bar()
|
|
{
|
|
echo "I don't exist until foo() is called.\n";
|
|
}
|
|
}
|
|
|
|
/* We can't call bar() yet
|
|
since it doesn't exist. */
|
|
|
|
foo();
|
|
|
|
/* Now we can call bar(),
|
|
foo()'s processing has
|
|
made it accessible. */
|
|
|
|
bar();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
All functions and classes in PHP have the global scope - they can be
|
|
called outside a function even if they were defined inside and vice versa.
|
|
</para>
|
|
<simpara>
|
|
PHP does not support function overloading, nor is it possible to
|
|
undefine or redefine previously-declared functions.
|
|
</simpara>
|
|
<note>
|
|
<simpara>
|
|
Function names are case-insensitive for the ASCII characters <literal>A</literal> to <literal>Z</literal>, though it is usually good form
|
|
to call functions as they appear in their declaration.
|
|
</simpara>
|
|
</note>
|
|
<simpara>
|
|
Both <link linkend="functions.variable-arg-list">variable number of
|
|
arguments</link> and <link linkend="functions.arguments.default">default
|
|
arguments</link> are supported in functions. See also the function
|
|
references for
|
|
<function>func_num_args</function>,
|
|
<function>func_get_arg</function>, and
|
|
<function>func_get_args</function> for more information.
|
|
</simpara>
|
|
|
|
<para>
|
|
It is possible to call recursive functions in PHP.
|
|
<example>
|
|
<title>Recursive functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function recursion($a)
|
|
{
|
|
if ($a < 20) {
|
|
echo "$a\n";
|
|
recursion($a + 1);
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<note>
|
|
<simpara>
|
|
Recursive function/method calls with over 100-200 recursion levels can
|
|
smash the stack and cause a termination of the current script. Especially,
|
|
infinite recursion is considered a programming error.
|
|
</simpara>
|
|
</note>
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.arguments">
|
|
<title>Function arguments</title>
|
|
|
|
<simpara>
|
|
Information may be passed to functions via the argument list,
|
|
which is a comma-delimited list of expressions. The arguments are
|
|
evaluated from left to right, before the function is actually called
|
|
(<emphasis>eager</emphasis> evaluation).
|
|
</simpara>
|
|
|
|
<para>
|
|
PHP supports passing arguments by value (the default), <link
|
|
linkend="functions.arguments.by-reference">passing by
|
|
reference</link>, and <link
|
|
linkend="functions.arguments.default">default argument
|
|
values</link>. <link linkend="functions.variable-arg-list">Variable-length
|
|
argument lists</link> and <link linkend="functions.named-arguments">Named Arguments</link>
|
|
are also supported.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Passing arrays to functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function takes_array($input)
|
|
{
|
|
echo "$input[0] + $input[1] = ", $input[0]+$input[1];
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
As of PHP 8.0.0, the list of function arguments may include a trailing comma, which
|
|
will be ignored. That is particularly useful in cases where the list of arguments is
|
|
long or contains long variable names, making it convenient to list arguments vertically.
|
|
</para>
|
|
<example>
|
|
<title>Function Argument List with trailing Comma</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function takes_many_args(
|
|
$first_arg,
|
|
$second_arg,
|
|
$a_very_long_argument_name,
|
|
$arg_with_default = 5,
|
|
$again = 'a default string', // This trailing comma was not permitted before 8.0.0.
|
|
)
|
|
{
|
|
// ...
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
As of PHP 8.0.0, declaring mandatory arguments after optional arguments
|
|
is deprecated. This can generally be resolved by dropping the default value.
|
|
One exception to this rule are arguments of the form
|
|
<code>Type $param = null</code>, where the &null; default makes the type implicitly
|
|
nullable. This usage remains allowed, though it is recommended to use an
|
|
explicit nullable type instead.
|
|
</para>
|
|
<example>
|
|
<title>Declaring optional arguments after mandatory arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($a = [], $b) {} // Before
|
|
function foo($a, $b) {} // After
|
|
|
|
function bar(A $a = null, $b) {} // Still allowed
|
|
function bar(?A $a, $b) {} // Recommended
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<sect2 xml:id="functions.arguments.by-reference">
|
|
<title>Passing arguments by reference</title>
|
|
|
|
<simpara>
|
|
By default, function arguments are passed by value (so that if
|
|
the value of the argument within the function is changed, it does
|
|
not get changed outside of the function). To allow a function to modify its
|
|
arguments, they must be passed by reference.
|
|
</simpara>
|
|
<para>
|
|
To have an argument to a function always passed by reference, prepend an
|
|
ampersand (&) to the argument name in the function definition:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Passing function parameters by reference</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function add_some_extra(&$string)
|
|
{
|
|
$string .= 'and something extra.';
|
|
}
|
|
$str = 'This is a string, ';
|
|
add_some_extra($str);
|
|
echo $str; // outputs 'This is a string, and something extra.'
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
It is an error to pass a value as argument which is supposed to be passed by reference.
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="functions.arguments.default">
|
|
<title>Default argument values</title>
|
|
|
|
<para>
|
|
A function may define C++-style default values for scalar
|
|
arguments as follows:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Use of default parameters in functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makecoffee($type = "cappuccino")
|
|
{
|
|
return "Making a cup of $type.\n";
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(null);
|
|
echo makecoffee("espresso");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Making a cup of cappuccino.
|
|
Making a cup of .
|
|
Making a cup of espresso.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
PHP also allows the use of <type>array</type>s and the special type &null;
|
|
as default values, for example:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Using non-scalar types as default values</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
|
|
{
|
|
$device = is_null($coffeeMaker) ? "hands" : $coffeeMaker;
|
|
return "Making a cup of ".join(", ", $types)." with $device.\n";
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(array("cappuccino", "lavazza"), "teapot");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</para>
|
|
<simpara>
|
|
The default value must be a constant expression, not (for
|
|
example) a variable, a class member or a function call.
|
|
</simpara>
|
|
<para>
|
|
Note that when using default arguments, any defaults should be on
|
|
the right side of any non-default arguments; otherwise, things
|
|
will not work as expected. Consider the following code snippet:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Incorrect usage of default function arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makeyogurt($type = "acidophilus", $flavour)
|
|
{
|
|
return "Making a bowl of $type $flavour.\n";
|
|
}
|
|
|
|
echo makeyogurt("raspberry"); // won't work as expected
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Warning: Missing argument 2 in call to makeyogurt() in
|
|
/usr/local/etc/httpd/htdocs/phptest/functest.html on line 41
|
|
Making a bowl of raspberry .
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Now, compare the above with this:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Correct usage of default function arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makeyogurt($flavour, $type = "acidophilus")
|
|
{
|
|
return "Making a bowl of $type $flavour.\n";
|
|
}
|
|
|
|
echo makeyogurt("raspberry"); // works as expected
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Making a bowl of acidophilus raspberry.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Arguments that are passed by reference may have a default value.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="functions.variable-arg-list">
|
|
<title>Variable-length argument lists</title>
|
|
|
|
<simpara>
|
|
PHP has support for variable-length argument lists in
|
|
user-defined functions by using the
|
|
<literal>...</literal> token.
|
|
</simpara>
|
|
|
|
<note>
|
|
<simpara>
|
|
It is also possible to achieve variable-length arguments by using
|
|
<function>func_num_args</function>,
|
|
<function>func_get_arg</function>, and
|
|
<function>func_get_args</function> functions.
|
|
This technique is not recommended as it was used prior to the introduction
|
|
of the <literal>...</literal> token.
|
|
</simpara>
|
|
</note>
|
|
|
|
<para>
|
|
Argument lists may include the
|
|
<literal>...</literal> token to denote that the function accepts a
|
|
variable number of arguments. The arguments will be passed into the
|
|
given variable as an array; for example:
|
|
|
|
<example>
|
|
<title>Using <literal>...</literal> to access variable arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function sum(...$numbers) {
|
|
$acc = 0;
|
|
foreach ($numbers as $n) {
|
|
$acc += $n;
|
|
}
|
|
return $acc;
|
|
}
|
|
|
|
echo sum(1, 2, 3, 4);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
10
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
<literal>...</literal> can also be used when calling functions to unpack
|
|
an <type>array</type> or <classname>Traversable</classname> variable or
|
|
literal into the argument list:
|
|
|
|
<example>
|
|
<title>Using <literal>...</literal> to provide arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function add($a, $b) {
|
|
return $a + $b;
|
|
}
|
|
|
|
echo add(...[1, 2])."\n";
|
|
|
|
$a = [1, 2];
|
|
echo add(...$a);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
3
|
|
3
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
You may specify normal positional arguments before the
|
|
<literal>...</literal> token. In this case, only the trailing arguments
|
|
that don't match a positional argument will be added to the array
|
|
generated by <literal>...</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
It is also possible to add a
|
|
<link linkend="language.types.declarations">type declaration</link> before the
|
|
<literal>...</literal> token. If this is present, then all arguments
|
|
captured by <literal>...</literal> must match that parameter type.
|
|
|
|
<example>
|
|
<title>Type declared variable arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function total_intervals($unit, DateInterval ...$intervals) {
|
|
$time = 0;
|
|
foreach ($intervals as $interval) {
|
|
$time += $interval->$unit;
|
|
}
|
|
return $time;
|
|
}
|
|
|
|
$a = new DateInterval('P1D');
|
|
$b = new DateInterval('P2D');
|
|
echo total_intervals('d', $a, $b).' days';
|
|
|
|
// This will fail, since null isn't a DateInterval object.
|
|
echo total_intervals('d', null);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
3 days
|
|
Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
Finally, variable arguments can also be passed
|
|
<link linkend="functions.arguments.by-reference">by reference</link> by
|
|
prefixing the <literal>...</literal> with an ampersand
|
|
(<literal>&</literal>).
|
|
</para>
|
|
|
|
<sect3 xml:id="functions.variable-arg-list.old">
|
|
<title>Older versions of PHP</title>
|
|
|
|
<para>
|
|
No special syntax is required to note that a function is variadic;
|
|
however access to the function's arguments must use
|
|
<function>func_num_args</function>, <function>func_get_arg</function>
|
|
and <function>func_get_args</function>.
|
|
</para>
|
|
|
|
<para>
|
|
The first example above would be implemented as follows in old versions of PHP:
|
|
|
|
<example>
|
|
<title>Accessing variable arguments in old PHP versions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function sum() {
|
|
$acc = 0;
|
|
foreach (func_get_args() as $n) {
|
|
$acc += $n;
|
|
}
|
|
return $acc;
|
|
}
|
|
|
|
echo sum(1, 2, 3, 4);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
10
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="functions.named-arguments">
|
|
<title>Named Arguments</title>
|
|
|
|
<para>
|
|
PHP 8.0.0 introduced named arguments as an extension of the existing
|
|
positional parameters. Named arguments allow passing arguments to a
|
|
function based on the parameter name, rather than the parameter position.
|
|
This makes the meaning of the argument self-documenting, makes the
|
|
arguments order-independent and allows skipping default values arbitrarily.
|
|
</para>
|
|
|
|
<para>
|
|
Named arguments are passed by prefixing the value with the parameter name
|
|
followed by a colon. Using reserved keywords as parameter names is allowed.
|
|
The parameter name must be an identifier, specifying dynamically
|
|
is not allowed.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Named argument syntax</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
myFunction(paramName: $value);
|
|
array_foobar(array: $value);
|
|
|
|
// NOT supported.
|
|
function_name($variableStoringParamName: $value);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Positional arguments versus named arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Using positional arguments:
|
|
array_fill(0, 100, 50);
|
|
|
|
// Using named arguments:
|
|
array_fill(start_index: 0, count: 100, value: 50);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
The order in which the named arguments are passed does not matter.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Same example as above with a different order of parameters</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
array_fill(value: 50, count: 100, start_index: 0);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Named arguments can be combined with positional arguments. In this case,
|
|
the named arguments must come after the positional arguments.
|
|
It is also possible to specify only some of the optional arguments of a
|
|
function, regardless of their order.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Combining named arguments with positional arguments</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
htmlspecialchars($string, double_encode: false);
|
|
// Same as
|
|
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Passing the same parameter multiple times results in an Error exception.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Error exception when passing the same parameter multiple times</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($param) { ... }
|
|
|
|
foo(param: 1, param: 2);
|
|
// Error: Named parameter $param overwrites previous argument
|
|
foo(1, param: 2);
|
|
// Error: Named parameter $param overwrites previous argument
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.returning-values">
|
|
<title>Returning values</title>
|
|
|
|
<para>
|
|
Values are returned by using the optional return statement. Any
|
|
type may be returned, including arrays and objects. This causes the
|
|
function to end its execution immediately and pass control back to
|
|
the line from which it was called. See <function>return</function>
|
|
for more information.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
If the <function>return</function> is omitted the value &null; will be
|
|
returned.
|
|
</para>
|
|
</note>
|
|
|
|
<sect2>
|
|
<title>Use of return</title>
|
|
<para>
|
|
<example>
|
|
<title>Use of <function>return</function></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function square($num)
|
|
{
|
|
return $num * $num;
|
|
}
|
|
echo square(4); // outputs '16'.
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
A function can not return multiple values, but similar results can be
|
|
obtained by returning an array.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Returning an array to get multiple values</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function small_numbers()
|
|
{
|
|
return [0, 1, 2];
|
|
}
|
|
// Array destructuring will collect each member of the array individually
|
|
[$zero, $one, $two] = small_numbers();
|
|
|
|
// Prior to 7.1.0, the only equivalent alternative is using list() construct
|
|
list($zero, $one, $two) = small_numbers();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
To return a reference from a function, use the reference operator & in
|
|
both the function declaration and when assigning the returned value to a
|
|
variable:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Returning a reference from a function</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &returns_reference()
|
|
{
|
|
return $someref;
|
|
}
|
|
|
|
$newref =& returns_reference();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
For more information on references, please check out <link
|
|
linkend="language.references">References Explained</link>.
|
|
</simpara>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.variable-functions">
|
|
<title>Variable functions</title>
|
|
|
|
<para>
|
|
PHP supports the concept of variable functions. This means that if
|
|
a variable name has parentheses appended to it, PHP will look for
|
|
a function with the same name as whatever the variable evaluates
|
|
to, and will attempt to execute it. Among other things, this can
|
|
be used to implement callbacks, function tables, and so forth.
|
|
</para>
|
|
<para>
|
|
Variable functions won't work with language constructs such
|
|
as <function>echo</function>, <function>print</function>,
|
|
<function>unset</function>, <function>isset</function>,
|
|
<function>empty</function>, <function>include</function>,
|
|
<function>require</function> and the like. Utilize wrapper functions to make
|
|
use of any of these constructs as variable functions.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Variable function example</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo() {
|
|
echo "In foo()<br />\n";
|
|
}
|
|
|
|
function bar($arg = '')
|
|
{
|
|
echo "In bar(); argument was '$arg'.<br />\n";
|
|
}
|
|
|
|
// This is a wrapper function around echo
|
|
function echoit($string)
|
|
{
|
|
echo $string;
|
|
}
|
|
|
|
$func = 'foo';
|
|
$func(); // This calls foo()
|
|
|
|
$func = 'bar';
|
|
$func('test'); // This calls bar()
|
|
|
|
$func = 'echoit';
|
|
$func('test'); // This calls echoit()
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Object methods can also be called with the variable functions syntax.
|
|
<example>
|
|
<title>Variable method example</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
function Variable()
|
|
{
|
|
$name = 'Bar';
|
|
$this->$name(); // This calls the Bar() method
|
|
}
|
|
|
|
function Bar()
|
|
{
|
|
echo "This is Bar";
|
|
}
|
|
}
|
|
|
|
$foo = new Foo();
|
|
$funcname = "Variable";
|
|
$foo->$funcname(); // This calls $foo->Variable()
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
When calling static methods, the function call is stronger than the static property operator:
|
|
<example>
|
|
<title>Variable method example with static properties</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
static $variable = 'static property';
|
|
static function Variable()
|
|
{
|
|
echo 'Method Variable called';
|
|
}
|
|
}
|
|
|
|
echo Foo::$variable; // This prints 'static property'. It does need a $variable in this scope.
|
|
$variable = "Variable";
|
|
Foo::$variable(); // This calls $foo->Variable() reading $variable in this scope.
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Complex callables</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
static function bar()
|
|
{
|
|
echo "bar\n";
|
|
}
|
|
function baz()
|
|
{
|
|
echo "baz\n";
|
|
}
|
|
}
|
|
|
|
$func = array("Foo", "bar");
|
|
$func(); // prints "bar"
|
|
$func = array(new Foo, "baz");
|
|
$func(); // prints "baz"
|
|
$func = "Foo::bar";
|
|
$func(); // prints "bar"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<sect2 role="seealso">
|
|
&reftitle.seealso;
|
|
<para>
|
|
<simplelist>
|
|
<member><function>is_callable</function></member>
|
|
<member><function>call_user_func</function></member>
|
|
<member><function>function_exists</function></member>
|
|
<member><link linkend="language.variables.variable">variable variables</link></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.internal">
|
|
<title>Internal (built-in) functions</title>
|
|
|
|
<para>
|
|
PHP comes standard with many functions and constructs. There are also
|
|
functions that require specific PHP extensions compiled in, otherwise
|
|
fatal "undefined function" errors will appear. For example, to use
|
|
<link linkend="ref.image">image</link> functions such as
|
|
<function>imagecreatetruecolor</function>, PHP must be compiled with
|
|
<productname>GD</productname> support. Or, to use
|
|
<function>mysqli_connect</function>, PHP must be compiled with
|
|
<link linkend="book.mysqli">MySQLi</link> support. There are many core functions
|
|
that are included in every version of PHP, such as the
|
|
<link linkend="ref.strings">string</link> and
|
|
<link linkend="ref.var">variable</link> functions. A call
|
|
to <function>phpinfo</function> or
|
|
<function>get_loaded_extensions</function> will show which extensions are
|
|
loaded into PHP. Also note that many extensions are enabled by default and
|
|
that the PHP manual is split up by extension. See the
|
|
<link linkend="configuration">configuration</link>,
|
|
<link linkend="install">installation</link>, and individual
|
|
extension chapters, for information on how to set up PHP.
|
|
</para>
|
|
<para>
|
|
Reading and understanding a function's prototype is explained within the
|
|
manual section titled <link linkend="about.prototypes">how to read a
|
|
function definition</link>. It's important to realize what a function
|
|
returns or if a function works directly on a passed in value. For example,
|
|
<function>str_replace</function> will return the modified string while
|
|
<function>usort</function> works on the actual passed in variable
|
|
itself. Each manual page also has specific information for each
|
|
function like information on function parameters, behavior changes,
|
|
return values for both success and failure, and availability information.
|
|
Knowing these important (yet often subtle) differences is crucial for
|
|
writing correct PHP code.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
If the parameters given to a function are not what it expects, such as
|
|
passing an <type>array</type> where a <type>string</type> is expected,
|
|
the return value of the function is undefined. In this case it will
|
|
likely return &null; but this is just a convention, and cannot be relied
|
|
upon.
|
|
As of PHP 8.0.0, a <classname>TypeError</classname> exception is supposed to
|
|
be thrown in this case.
|
|
</simpara>
|
|
</note>
|
|
|
|
<sect2 role="seealso">
|
|
&reftitle.seealso;
|
|
<para>
|
|
<simplelist>
|
|
<member><function>function_exists</function></member>
|
|
<member><link linkend="funcref">the function reference</link></member>
|
|
<member><function>get_extension_funcs</function></member>
|
|
<member><function>dl</function></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.anonymous">
|
|
<title>Anonymous functions</title>
|
|
|
|
<simpara>
|
|
Anonymous functions, also known as <literal>closures</literal>, allow the
|
|
creation of functions which have no specified name. They are most useful as
|
|
the value of <type>callable</type>
|
|
parameters, but they have many other uses.
|
|
</simpara>
|
|
<simpara>
|
|
Anonymous functions are implemented using the <link linkend="class.closure">
|
|
<classname>Closure</classname></link> class.
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Anonymous function example</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo preg_replace_callback('~-([a-z])~', function ($match) {
|
|
return strtoupper($match[1]);
|
|
}, 'hello-world');
|
|
// outputs helloWorld
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<simpara>
|
|
Closures can also be used as the values of variables; PHP automatically
|
|
converts such expressions into instances of the
|
|
<classname>Closure</classname> internal class. Assigning a closure to a
|
|
variable uses the same syntax as any other assignment, including the
|
|
trailing semicolon:
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Anonymous function variable assignment example</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$greet = function($name)
|
|
{
|
|
printf("Hello %s\r\n", $name);
|
|
};
|
|
|
|
$greet('World');
|
|
$greet('PHP');
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<simpara>
|
|
Closures may also inherit variables from the parent scope. Any such
|
|
variables must be passed to the <literal>use</literal> language construct.
|
|
As of PHP 7.1, these variables must not include &link.superglobals;,
|
|
<varname>$this</varname>, or variables with the same name as a parameter.
|
|
A return type declaration of the function has to be placed
|
|
<emphasis>after</emphasis> the <literal>use</literal> clause.
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Inheriting variables from the parent scope</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$message = 'hello';
|
|
|
|
// No "use"
|
|
$example = function () {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Inherit $message
|
|
$example = function () use ($message) {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Inherited variable's value is from when the function
|
|
// is defined, not when called
|
|
$message = 'world';
|
|
$example();
|
|
|
|
// Reset message
|
|
$message = 'hello';
|
|
|
|
// Inherit by-reference
|
|
$example = function () use (&$message) {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// The changed value in the parent scope
|
|
// is reflected inside the function call
|
|
$message = 'world';
|
|
$example();
|
|
|
|
// Closures can also accept regular arguments
|
|
$example = function ($arg) use ($message) {
|
|
var_dump($arg . ' ' . $message);
|
|
};
|
|
$example("hello");
|
|
|
|
// Return type declaration comes after the use clause
|
|
$example = function () use ($message): string {
|
|
return "hello $message";
|
|
};
|
|
var_dump($example());
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Notice: Undefined variable: message in /example.php on line 6
|
|
NULL
|
|
string(5) "hello"
|
|
string(5) "hello"
|
|
string(5) "hello"
|
|
string(5) "world"
|
|
string(11) "hello world"
|
|
string(11) "hello world"
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
As of PHP 8.0.0, the list of scope-inherited variables may include a trailing
|
|
comma, which will be ignored.
|
|
</para>
|
|
<simpara>
|
|
Inheriting variables from the parent scope is <emphasis>not</emphasis>
|
|
the same as using global variables.
|
|
Global variables exist in the global scope, which is the same no
|
|
matter what function is executing. The parent scope of a closure is the
|
|
function in which the closure was declared (not necessarily the function it
|
|
was called from). See the following example:
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Closures and scoping</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// A basic shopping cart which contains a list of added products
|
|
// and the quantity of each product. Includes a method which
|
|
// calculates the total price of the items in the cart using a
|
|
// closure as a callback.
|
|
class Cart
|
|
{
|
|
const PRICE_BUTTER = 1.00;
|
|
const PRICE_MILK = 3.00;
|
|
const PRICE_EGGS = 6.95;
|
|
|
|
protected $products = array();
|
|
|
|
public function add($product, $quantity)
|
|
{
|
|
$this->products[$product] = $quantity;
|
|
}
|
|
|
|
public function getQuantity($product)
|
|
{
|
|
return isset($this->products[$product]) ? $this->products[$product] :
|
|
FALSE;
|
|
}
|
|
|
|
public function getTotal($tax)
|
|
{
|
|
$total = 0.00;
|
|
|
|
$callback =
|
|
function ($quantity, $product) use ($tax, &$total)
|
|
{
|
|
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
|
|
strtoupper($product));
|
|
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
|
|
};
|
|
|
|
array_walk($this->products, $callback);
|
|
return round($total, 2);
|
|
}
|
|
}
|
|
|
|
$my_cart = new Cart;
|
|
|
|
// Add some items to the cart
|
|
$my_cart->add('butter', 1);
|
|
$my_cart->add('milk', 3);
|
|
$my_cart->add('eggs', 6);
|
|
|
|
// Print the total with a 5% sales tax.
|
|
print $my_cart->getTotal(0.05) . "\n";
|
|
// The result is 54.29
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Automatic binding of <literal>$this</literal></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Test
|
|
{
|
|
public function testing()
|
|
{
|
|
return function() {
|
|
var_dump($this);
|
|
};
|
|
}
|
|
}
|
|
|
|
$object = new Test;
|
|
$function = $object->testing();
|
|
$function();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
object(Test)#1 (0) {
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
When declared in the context of a class, the current class is
|
|
automatically bound to it, making <literal>$this</literal> available
|
|
inside of the function's scope. If this automatic binding of the current
|
|
class is not wanted, then
|
|
<link linkend="functions.anonymous-functions.static">static anonymous
|
|
functions</link> may be used instead.
|
|
</para>
|
|
|
|
<sect2 xml:id="functions.anonymous-functions.static">
|
|
<title>Static anonymous functions</title>
|
|
<para>
|
|
Anonymous functions may be declared statically. This
|
|
prevents them from having the current class automatically bound to
|
|
them. Objects may also not be bound to them at runtime.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Attempting to use <literal>$this</literal> inside a static anonymous function</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Foo
|
|
{
|
|
function __construct()
|
|
{
|
|
$func = static function() {
|
|
var_dump($this);
|
|
};
|
|
$func();
|
|
}
|
|
};
|
|
new Foo();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Notice: Undefined variable: this in %s on line %d
|
|
NULL
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Attempting to bind an object to a static anonymous function</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$func = static function() {
|
|
// function body
|
|
};
|
|
$func = $func->bindTo(new StdClass);
|
|
$func();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Warning: Cannot bind an instance to a static closure in %s on line %d
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="changelog">
|
|
&reftitle.changelog;
|
|
<para>
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>7.1.0</entry>
|
|
<entry>
|
|
Anonymous functions may not close over &link.superglobals;,
|
|
<varname>$this</varname>, or any variable with the same name as a
|
|
parameter.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="notes">
|
|
&reftitle.notes;
|
|
<note>
|
|
<simpara>
|
|
It is possible to use <function>func_num_args</function>,
|
|
<function>func_get_arg</function>, and <function>func_get_args</function>
|
|
from within a closure.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
<sect1 xml:id="functions.arrow">
|
|
<title>Arrow Functions</title>
|
|
|
|
<simpara>
|
|
Arrow functions were introduced in PHP 7.4 as a more concise syntax for
|
|
<link linkend="functions.anonymous">anonymous functions</link>.
|
|
</simpara>
|
|
<simpara>
|
|
Both anonymous functions and arrow functions are implemented using the
|
|
<link linkend="class.closure"><classname>Closure</classname></link> class.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
Arrow functions have the basic form
|
|
<code>fn (argument_list) => expr</code>.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
Arrow functions support the same features as
|
|
<link linkend="functions.anonymous">anonymous functions</link>,
|
|
except that using variables from the parent scope is always automatic.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
When a variable used in the expression is defined in the parent scope
|
|
it will be implicitly captured by-value.
|
|
In the following example, the functions <varname>$fn1</varname> and
|
|
<varname>$fn2</varname> behave the same way.
|
|
</simpara>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Arrow functions capture variables by value automatically</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$y = 1;
|
|
|
|
$fn1 = fn($x) => $x + $y;
|
|
// equivalent to using $y by value:
|
|
$fn2 = function ($x) use ($y) {
|
|
return $x + $y;
|
|
};
|
|
|
|
var_export($fn1(3));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
4
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
This also works if the arrow functions are nested:
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Arrow functions capture variables by value automatically, even when nested</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$z = 1;
|
|
$fn = fn($x) => fn($y) => $x * $y + $z;
|
|
// Outputs 51
|
|
var_export($fn(5)(10));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Similarly to anonymous functions,
|
|
the arrow function syntax allows arbitrary function signatures,
|
|
including parameter and return types, default values, variadics,
|
|
as well as by-reference passing and returning.
|
|
All of the following are valid examples of arrow functions:
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Examples of arrow functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
fn(array $x) => $x;
|
|
static fn(): int => $x;
|
|
fn($x = 42) => $x;
|
|
fn(&$x) => $x;
|
|
fn&($x) => $x;
|
|
fn($x, ...$rest) => $rest;
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Arrow functions use by-value variable binding.
|
|
This is roughly equivalent to performing a <code>use($x)</code> for every
|
|
variable <varname>$x</varname> used inside the arrow function.
|
|
A by-value binding means that it is not possible to modify any values
|
|
from the outer scope.
|
|
<link linkend="functions.anonymous">Anonymous functions</link>
|
|
can be used instead for by-ref bindings.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Values from the outer scope cannot be modified by arrow functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$x = 1;
|
|
$fn = fn() => $x++; // Has no effect
|
|
$fn();
|
|
var_export($x); // Outputs 1
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<sect2 role="changelog">
|
|
&reftitle.changelog;
|
|
<para>
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>7.4.0</entry>
|
|
<entry>
|
|
Arrow functions became available.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="notes">
|
|
&reftitle.notes;
|
|
<note>
|
|
<simpara>
|
|
It is possible to use <function>func_num_args</function>,
|
|
<function>func_get_arg</function>, and <function>func_get_args</function>
|
|
from within an arrow function.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.first_class_callable_syntax">
|
|
<title>First class callable syntax</title>
|
|
|
|
<para>
|
|
The first class callable syntax is introduced as of PHP 8.1.0, as a way of creating <link linkend="functions.anonymous">anonymous functions</link> from <link linkend="language.types.callable">callable</link>.
|
|
It supersedes existing callable syntax using strings and arrays.
|
|
The advantage of this syntax is that it is accessible to static analysis, and uses the scope at the point where the callable is acquired.
|
|
</para>
|
|
|
|
<para>
|
|
<code>CallableExpr(...)</code> syntax is used to create a <classname>Closure</classname> object from callable. <code>CallableExpr</code> accepts any expression that can be directly called in the PHP grammar:
|
|
<example>
|
|
<title>Simple first class callable syntax</title>
|
|
<programlisting role="php">
|
|
<;
|
|
$f9 = [Foo::class, 'staticmethod'](...);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The <code>...</code> is part of the syntax, and not an omission.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
<code>CallableExpr(...)</code> has the same semantics as <methodname>Closure::fromCallable</methodname>.
|
|
That is, unlike callable using strings and arrays, <code>CallableExpr(...)</code> respects the scope at the point where it is created:
|
|
<example>
|
|
<title>Scope comparison of <code>CallableExpr(...)</code> and traditional callable</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Foo {
|
|
public function getPrivateMethod() {
|
|
return [$this, 'privateMethod'];
|
|
}
|
|
|
|
private function privateMethod() {
|
|
echo __METHOD__, "\n";
|
|
}
|
|
}
|
|
|
|
$foo = new Foo;
|
|
$privateMethod = $foo->getPrivateMethod();
|
|
$privateMethod();
|
|
// Fatal error: Call to private method Foo::privateMethod() from global scope
|
|
// This is because call is performed outside from Foo and visibility will be checked from this point.
|
|
|
|
class Foo1 {
|
|
public function getPrivateMethod() {
|
|
// Uses the scope where the callable is acquired.
|
|
return $this->privateMethod(...); // identical to Closure::fromCallable([$this, 'privateMethod']);
|
|
}
|
|
|
|
private function privateMethod() {
|
|
echo __METHOD__, "\n";
|
|
}
|
|
}
|
|
|
|
$foo1 = new Foo1;
|
|
$privateMethod = $foo1->getPrivateMethod();
|
|
$privateMethod(); // Foo1::privateMethod
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Object creation by this syntax (e.g <code>new Foo(...)</code>) is not supported, because <code>new Foo()</code> syntax is not considered a call.
|
|
</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>
|
|
The first-class callable syntax cannot be combined with the nullsafe operator. Both of the following result in a compile-time error:
|
|
<example>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$obj?->method(...);
|
|
$obj?->prop->method(...);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</note>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|