mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 16:38:54 +00:00
Actually add type declaration page...
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@351366 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
parent
a9a6224ca9
commit
46e0f25dcd
1 changed files with 812 additions and 0 deletions
812
language/types/declarations.xml
Executable file
812
language/types/declarations.xml
Executable file
|
@ -0,0 +1,812 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
<sect1 xml:id="language.types.declarations">
|
||||
<title>Type declarations</title>
|
||||
|
||||
<para>
|
||||
Type declarations can be added to function arguments, return values,
|
||||
and, as of PHP 7.4.0, class properties. They ensure that the value
|
||||
is of the specified type at call time, otherwise a
|
||||
<classname>TypeError</classname> is thrown.
|
||||
</para>
|
||||
|
||||
<!-- Find better place where to put this note -->
|
||||
<note>
|
||||
<!-- TODO Link to covariance section -->
|
||||
<para>
|
||||
When overriding a parent method, the child's method must match any return
|
||||
type declaration on the parent. If the parent doesn't define a return
|
||||
type, then the child method may do so.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<sect2 xml:id="language.types.declarations.base">
|
||||
<title>Single types</title>
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>&Type;</entry>
|
||||
<entry>&Description;</entry>
|
||||
<entry>&Version;</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Class/interface name</entry>
|
||||
<entry>
|
||||
The value must be an &instanceof; the given class or interface.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>self</type></entry>
|
||||
<entry>
|
||||
The value must be an &instanceof; the same class as the one the
|
||||
method is defined on.
|
||||
Can only be used in classes.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>array</type></entry>
|
||||
<entry>
|
||||
The value must be an <type>array</type>.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>callable</type></entry>
|
||||
<entry>
|
||||
The value must be a valid <type>callable</type>.
|
||||
Cannot be used as a class property type declaration.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry>
|
||||
The value must be a boolean value.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>float</type></entry>
|
||||
<entry>
|
||||
The value must be a floating point number.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>int</type></entry>
|
||||
<entry>
|
||||
The value must be an integer.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>string</type></entry>
|
||||
<entry>
|
||||
The value must be a <type>string</type>.
|
||||
</entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>iterable</type></entry>
|
||||
<entry>
|
||||
The value must be either an <type>array</type> or an &instanceof; <classname>Traversable</classname>.
|
||||
</entry>
|
||||
<entry>PHP 7.1.0</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>object</type></entry>
|
||||
<entry>
|
||||
The value must be an <type>object</type>.
|
||||
</entry>
|
||||
<entry>PHP 7.2.0</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><type>mixed</type></entry>
|
||||
<entry>
|
||||
The value can be any value.
|
||||
</entry>
|
||||
<entry>PHP 8.0.0</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
Aliases for the above scalar types are not supported.
|
||||
Instead, they are treated as class or interface names.
|
||||
For example, using <literal>boolean</literal> as a type declaration
|
||||
it will require the value to be an &instanceof; the class or
|
||||
interface <literal>boolean</literal>, rather than of type
|
||||
<type>bool</type>:
|
||||
</para>
|
||||
<para>
|
||||
<example>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function test(boolean $param) {}
|
||||
test(true);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs.8;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
|
||||
|
||||
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
|
||||
Stack trace:
|
||||
#0 -(3): test(true)
|
||||
#1 {main}
|
||||
thrown in - on line 2
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</para>
|
||||
</warning>
|
||||
|
||||
<sect3 xml:id="language.types.declarations.examples">
|
||||
&reftitle.examples;
|
||||
<example>
|
||||
<title>Basic class type declaration</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
class C {}
|
||||
class D extends C {}
|
||||
|
||||
// This doesn't extend C.
|
||||
class E {}
|
||||
|
||||
function f(C $c) {
|
||||
echo get_class($c)."\n";
|
||||
}
|
||||
|
||||
f(new C);
|
||||
f(new D);
|
||||
f(new E);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs.8;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
C
|
||||
D
|
||||
|
||||
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
|
||||
Stack trace:
|
||||
#0 -(14): f(Object(E))
|
||||
#1 {main}
|
||||
thrown in - on line 8
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Basic interface type declaration</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
interface I { public function f(); }
|
||||
class C implements I { public function f() {} }
|
||||
|
||||
// This doesn't implement I.
|
||||
class E {}
|
||||
|
||||
function f(I $i) {
|
||||
echo get_class($i)."\n";
|
||||
}
|
||||
|
||||
f(new C);
|
||||
f(new E);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs.8;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
C
|
||||
|
||||
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
|
||||
Stack trace:
|
||||
#0 -(13): f(Object(E))
|
||||
#1 {main}
|
||||
thrown in - on line 8
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Basic return type declaration</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function sum($a, $b): float {
|
||||
return $a + $b;
|
||||
}
|
||||
|
||||
// Note that a float will be returned.
|
||||
var_dump(sum(1, 2));
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
float(3)
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Returning an object</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
class C {}
|
||||
|
||||
function getC(): C {
|
||||
return new C;
|
||||
}
|
||||
|
||||
var_dump(getC());
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
object(C)#1 (0) {
|
||||
}
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="language.types.declarations.nullable">
|
||||
<title>Nullable type</title>
|
||||
|
||||
<para>
|
||||
As of PHP 7.1.0, type declarations can be marked nullable by prefixing the
|
||||
type name with a question mark (<literal>?</literal>).
|
||||
This signifies that the value can be of the specified type or &null;.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<example>
|
||||
<title>Nullable argument type declaration</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
class C {}
|
||||
|
||||
function f(?C $c) {
|
||||
var_dump($c);
|
||||
}
|
||||
|
||||
f(new C);
|
||||
f(null);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
object(C)#1 (0) {
|
||||
}
|
||||
NULL
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Nullable return type declaration</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function get_item(): ?string {
|
||||
if (isset($_GET['item'])) {
|
||||
return $_GET['item'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Prior to PHP 7.1.0, it was possible to achieve nullable arguments by making
|
||||
<literal>null</literal> the default value.
|
||||
This is not recommended as this breaks during inheritance.
|
||||
</para>
|
||||
<example>
|
||||
<title>Old way to make arguments nullable</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
class C {}
|
||||
|
||||
function f(C $c = null) {
|
||||
var_dump($c);
|
||||
}
|
||||
|
||||
f(new C);
|
||||
f(null);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
object(C)#1 (0) {
|
||||
}
|
||||
NULL
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</note>
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="language.types.declarations.union">
|
||||
<title>Union types</title>
|
||||
<para>
|
||||
A union type declaration accepts values of multiple different types,
|
||||
rather than a single one.
|
||||
Union types are specified using the syntax <literal>T1|T2|...</literal>.
|
||||
Union types are available as of PHP 8.0.0.
|
||||
</para>
|
||||
|
||||
<sect3 xml:id="language.types.declarations.union.nullable">
|
||||
<title>Nullable union types</title>
|
||||
<para>
|
||||
The <literal>null</literal> type is supported as part of unions,
|
||||
such that <literal>T1|T2|null</literal> can be used to create a nullable union.
|
||||
The existing <literal>?T</literal> notation is considered a shorthand
|
||||
for the common case of <literal>T|null</literal>.
|
||||
</para>
|
||||
|
||||
<caution>
|
||||
<simpara>
|
||||
<literal>null</literal> cannot be used as a standalone type.
|
||||
</simpara>
|
||||
</caution>
|
||||
</sect3>
|
||||
|
||||
<sect3 xml:id="language.types.declarations.union.false">
|
||||
<title>false pseudo-type</title>
|
||||
<para>
|
||||
The <literal>false</literal> literal type is supported as part of unions,
|
||||
and is included as for historical reasons many internal functions return
|
||||
<literal>false</literal> instead of <literal>null</literal> for failures.
|
||||
A classic example of such a function is <function>strpos</function>.
|
||||
</para>
|
||||
|
||||
<caution>
|
||||
<simpara>
|
||||
<literal>false</literal> cannot be used as a standalone type (including
|
||||
nullable standalone type).
|
||||
As such, all of <literal>false</literal>, <literal>false|null</literal>
|
||||
and <literal>?false</literal> are not permitted.
|
||||
</simpara>
|
||||
</caution>
|
||||
<caution>
|
||||
<simpara>
|
||||
The <literal>true</literal> literal type does <emphasis>not</emphasis>
|
||||
exist.
|
||||
</simpara>
|
||||
</caution>
|
||||
</sect3>
|
||||
|
||||
<sect3 xml:id="language.types.declarations.union.redundant">
|
||||
<title>Duplicate and redundant types</title>
|
||||
<para>
|
||||
To catch simple bugs in union type declarations, redundant types that
|
||||
can be detected without performing class loading will result in a
|
||||
compile-time error. This includes:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
Each name-resolved type may only occur once. Types such as
|
||||
<literal>int|string|INT</literal> result in an error.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
If <type>bool</type> is used, <type>false</type> cannot be used additionally.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
If <type>object</type> is used, class types cannot be used additionally.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
If <type>iterable</type> is used, <type>array</type>
|
||||
and <classname>Traversable</classname> cannot be used additionally.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<simpara>
|
||||
This does not guarantee that the type is “minimal”, because doing so would
|
||||
require loading all used class types.
|
||||
</simpara>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
For example, if <literal>A</literal> and <literal>B</literal> are class
|
||||
aliases, then <literal>A|B</literal> remains a legal union type, even
|
||||
though it could be reduced to either <literal>A</literal> or
|
||||
<literal>B</literal>.
|
||||
Similarly, if class <code>B extends A {}</code>, then <literal>A|B</literal>
|
||||
is also a legal union type, even though it could be reduced to just
|
||||
<literal>A</literal>.
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function foo(): int|INT {} // Disallowed
|
||||
function foo(): bool|false {} // Disallowed
|
||||
|
||||
use A as B;
|
||||
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
|
||||
|
||||
class_alias('X', 'Y');
|
||||
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="language.types.declarations.return-only">
|
||||
<title>Return only types</title>
|
||||
|
||||
<sect3 xml:id="language.types.declarations.void">
|
||||
<title>void</title>
|
||||
<para>
|
||||
<literal>void</literal> is a return type indicating the function does not
|
||||
return a value.
|
||||
Therefore it cannot be part of a union type declaration.
|
||||
Available as of PHP 7.1.0.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 xml:id="language.types.declarations.static">
|
||||
<title>static</title>
|
||||
<para>
|
||||
The value must be an &instanceof; the same class as the one the
|
||||
method is called in.
|
||||
Available as of PHP 8.0.0.
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="language.types.declarations.strict">
|
||||
<title>Strict typing</title>
|
||||
|
||||
<para>
|
||||
By default, PHP will coerce values of the wrong type into the expected
|
||||
scalar type declaration if possible. For example, a function that is given
|
||||
an <type>int</type> for a parameter that expects a <type>string</type>
|
||||
will get a variable of type <type>string</type>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is possible to enable strict mode on a per-file basis. In strict
|
||||
mode, only a value corresponding exactly to the type declaration will be
|
||||
accepted, otherwise a <classname>TypeError</classname> will be thrown.
|
||||
The only exception to this rule is that an <type>int</type> value will
|
||||
pass a <type>float</type> type declaration.
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<simpara>
|
||||
Function calls from within internal functions will not be affected by
|
||||
the <literal>strict_types</literal> declaration.
|
||||
</simpara>
|
||||
</warning>
|
||||
|
||||
<para>
|
||||
To enable strict mode, the &declare; statement is used with the
|
||||
<literal>strict_types</literal> declaration:
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Strict typing applies to function calls made from
|
||||
<emphasis>within</emphasis> the file with strict typing enabled, not to
|
||||
the functions declared within that file. If a file without strict
|
||||
typing enabled makes a call to a function that was defined in a file
|
||||
with strict typing, the caller's preference (coercive typing) will be
|
||||
respected, and the value will be coerced.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Strict typing is only defined for scalar type declarations.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<example>
|
||||
<title>Strict typing for arguments values</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
function sum(int $a, int $b) {
|
||||
return $a + $b;
|
||||
}
|
||||
|
||||
var_dump(sum(1, 2));
|
||||
var_dump(sum(1.5, 2.5));
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs.8;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
int(3)
|
||||
|
||||
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
|
||||
Stack trace:
|
||||
#0 -(9): sum(1.5, 2.5)
|
||||
#1 {main}
|
||||
thrown in - on line 4
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Coercive typing for argument values</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function sum(int $a, int $b) {
|
||||
return $a + $b;
|
||||
}
|
||||
|
||||
var_dump(sum(1, 2));
|
||||
|
||||
// These will be coerced to integers: note the output below!
|
||||
var_dump(sum(1.5, 2.5));
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
int(3)
|
||||
int(3)
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Strict typing for return values</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
function sum($a, $b): int {
|
||||
return $a + $b;
|
||||
}
|
||||
|
||||
var_dump(sum(1, 2));
|
||||
var_dump(sum(1, 2.5));
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
int(3)
|
||||
|
||||
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
|
||||
Stack trace:
|
||||
#0 -(9): sum(1, 2.5)
|
||||
#1 {main}
|
||||
thrown in - on line 5
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="language.types.declarations.union.coercive">
|
||||
<title>Coercive typing with union types</title>
|
||||
<para>
|
||||
When <literal>strict_types</literal> is not enabled, scalar type declarations
|
||||
are subject to limited implicit type coercions.
|
||||
If the exact type of the value is not part of the union, then the target type
|
||||
is chosen in the following order of preference:
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<type>int</type>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<type>float</type>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<type>string</type>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<type>bool</type>
|
||||
</simpara>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
If the type both exists in the union, and the value can be coerced to the
|
||||
type under PHPs existing type checking semantics, then the type is chosen.
|
||||
Otherwise the next type is tried.
|
||||
</para>
|
||||
|
||||
<caution>
|
||||
<para>
|
||||
As an exception, if the value is a string and both int and float are part
|
||||
of the union, the preferred type is determined by the existing
|
||||
“numeric string” semantics.
|
||||
For example, for <literal>"42"</literal> <type>int</type> is chosen,
|
||||
while for <literal>"42.0"</literal> <type>float</type> is chosen.
|
||||
</para>
|
||||
</caution>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Types that are not part of the above preference list are not eligible
|
||||
targets for implicit coercion. In particular no implicit coercions to
|
||||
the <literal>null</literal> and <literal>false</literal> types occur.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<example>
|
||||
<title>Example of types being coerced into a type part of the union</title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
// int|string
|
||||
42 --> 42 // exact type
|
||||
"42" --> "42" // exact type
|
||||
new ObjectWithToString --> "Result of __toString()"
|
||||
// object never compatible with int, fall back to string
|
||||
42.0 --> 42 // float compatible with int
|
||||
42.1 --> 42 // float compatible with int
|
||||
1e100 --> "1.0E+100" // float too large for int type, fall back to string
|
||||
INF --> "INF" // float too large for int type, fall back to string
|
||||
true --> 1 // bool compatible with int
|
||||
[] --> TypeError // array not compatible with int or string
|
||||
|
||||
// int|float|bool
|
||||
"45" --> 45 // int numeric string
|
||||
"45.0" --> 45.0 // float numeric string
|
||||
|
||||
"45X" --> true // not numeric string, fall back to bool
|
||||
"" --> false // not numeric string, fall back to bool
|
||||
"X" --> true // not numeric string, fall back to bool
|
||||
[] --> TypeError // array not compatible with int, float or bool
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</example>
|
||||
</sect2>
|
||||
|
||||
<!-- TODO figure out what do to with these things -->
|
||||
<sect2 xml:id="language.types.declarations.misc">
|
||||
<title>Misc</title>
|
||||
<example>
|
||||
<title>Typed pass-by-reference Parameters</title>
|
||||
<simpara>
|
||||
Declared types of reference parameters are checked on function entry, but
|
||||
not when the function returns, so after the function had returned, the
|
||||
argument's type may have changed.
|
||||
</simpara>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
function array_baz(array &$param)
|
||||
{
|
||||
$param = 1;
|
||||
}
|
||||
$var = [];
|
||||
array_baz($var);
|
||||
var_dump($var);
|
||||
array_baz($var);
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs.8;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
int(1)
|
||||
|
||||
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
|
||||
Stack trace:
|
||||
#0 -(9): array_baz(1)
|
||||
#1 {main}
|
||||
thrown in - on line 2
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Catching <classname>TypeError</classname></title>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
function sum(int $a, int $b) {
|
||||
return $a + $b;
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(sum(1, 2));
|
||||
var_dump(sum(1.5, 2.5));
|
||||
} catch (TypeError $e) {
|
||||
echo 'Error: ', $e->getMessage();
|
||||
}
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
&example.outputs.8;
|
||||
<screen>
|
||||
<![CDATA[
|
||||
int(3)
|
||||
Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
<!-- 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
|
||||
-->
|
Loading…
Reference in a new issue