-
Notifications
You must be signed in to change notification settings - Fork 109
Expand file tree
/
Copy pathcallable.xml
More file actions
269 lines (229 loc) · 7.65 KB
/
callable.xml
File metadata and controls
269 lines (229 loc) · 7.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 312c0c7b39d0722c419f6784cbda24823220dfb3 Maintainer: dallas Status: ready -->
<!-- CREDITS: Luffy, mowangjuanzi -->
<sect1 xml:id="language.types.callable">
<title>Callable</title>
<simpara>
callable 是对函数或方法的引用,作为参数传递给其他函数,使用 <type>callable</type> 类型声明来表示。
</simpara>
<informalexample>
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
function foo(callable $callback) {
$callback();
}
?>
]]>
</programlisting>
</informalexample>
<simpara>
一些函数接受回调函数作为参数,例如 <function>array_map</function>、<function>usort</function>
或 <function>preg_replace_callback</function>。
</simpara>
<sect2 xml:id="language.types.callable.passing">
<title>callable 的创建</title>
<simpara>
callable 是一种表示可调用内容的类型。Callable 可作为参数传递给需要回调参数的函数或方法,也可直接调用。<type>callable</type>
类型不能用于类属性的类型声明,此时应使用 <classname>Closure</classname> 类型声明。
</simpara>
<simpara>
Callable 可通过多种方式创建:
</simpara>
<itemizedlist>
<listitem>
<simpara><classname>Closure</classname> 对象</simpara>
</listitem>
<listitem>
<simpara>包含函数名或方法名的 &string;</simpara>
</listitem>
<listitem>
<simpara>
索引 0 为类名或者 <type>object</type>,索引 1 是方法名的 &array;
</simpara>
</listitem>
<listitem>
<simpara>
实现了 <link linkend="object.invoke">__invoke()</link> 魔术方法的 &object;
</simpara>
</listitem>
</itemizedlist>
<simpara>
<classname>Closure</classname> 对象可通过<link
linkend="functions.anonymous">匿名函数</link>语法、<link linkend="functions.arrow">箭头函数</link>语法、<link
linkend="functions.first_class_callable_syntax">一级可调用语法</link>,或
<methodname>Closure::fromCallable</methodname> 方法创建。
</simpara>
<note>
<simpara>
<link linkend="functions.first_class_callable_syntax">一级可调用语法</link> 仅自 PHP 8.1.0 起可用。
</simpara>
</note>
<example>
<title>
使用 <classname>Closure</classname> 的 Callback 示例
</title>
<programlisting role="php">
<![CDATA[
<?php
// 使用匿名函数语法
$double1 = function ($a) {
return $a * 2;
};
// 使用一级可调用语法
function double_function($a) {
return $a * 2;
}
$double2 = double_function(...);
// 使用箭头函数语法
$double3 = fn($a) => $a * 2;
// 使用 Closure::fromCallable
$double4 = Closure::fromCallable('double_function');
// 此处使用 closure 作为回调,将范围内每个元素的值翻倍。
$new_numbers = array_map($double1, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double2, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double3, range(1, 5));
print implode(' ', $new_numbers) . PHP_EOL;
$new_numbers = array_map($double4, range(1, 5));
print implode(' ', $new_numbers);
?>
]]>
</programlisting>
&example.outputs.81;
<screen>
<![CDATA[
2 4 6 8 10
2 4 6 8 10
2 4 6 8 10
2 4 6 8 10
]]>
</screen>
</example>
<simpara>
callable 也可以是包含函数名或静态方法名的字符串。除语言结构(如
<function>array</function>、<function>echo</function>、<function>empty</function>、<function>eval</function>、<function>isset</function>、<function>list</function>、<function>print</function>
或 <function>unset</function>)外,任何内置或用户自定义函数均可使用。
</simpara>
<simpara>
静态类方法可在不实例化该类 <type>object</type> 的情况下使用,方式包括:创建数组,其中索引 0
为类名,索引 1 为方法名;或使用作用域解析运算符 <literal>::</literal>
的特殊语法,例如 <literal>'ClassName::methodName'</literal>。
</simpara>
<simpara>
已实例化 <type>object</type> 的方法在以数组形式提供时可作为 callable,其中索引 0
为该 <type>object</type>,索引 1 为方法名。
</simpara>
<simpara>
<classname>Closure</classname> 对象与 <type>callable</type> 类型的主要区别在于,<classname>Closure</classname>
对象与作用域无关,始终可直接调用,而 callable 类型可能依赖于作用域,不一定能直接调用。创建 callable
时,推荐使用 <classname>Closure</classname>。
</simpara>
<note>
<simpara>
<classname>Closure</classname> 对象绑定于其创建时所在的作用域,而以字符串或数组形式引用类方法的 callable
则在其被调用的作用域中解析。若需从 private 或 protected 方法创建可在类作用域外部调用的可调用项,应使用
<methodname>Closure::fromCallable</methodname> 或<link linkend="functions.first_class_callable_syntax">一级可调用语法</link>。
</simpara>
</note>
<simpara>
PHP 允许创建 callable,可用作回调参数,但无法直接调用。它们是上下文相关的 callable,引用类继承层次中的某个类方法,例如
<literal>'parent::method'</literal> 或 <literal>["static", "method"]</literal>。
</simpara>
<note>
<simpara>
自 PHP 8.2.0 起,已弃用上下文相关的 callable 。应通过将 <literal>'parent::method'</literal> 替换为
<literal>parent::class . '::method'</literal>,或使用<link
linkend="functions.first_class_callable_syntax">一级可调用语法</link>,以消除上下文依赖。
</simpara>
</note>
<example>
<title>
使用 <function>call_user_function</function> 调用各类 callable
</title>
<programlisting role="php">
<![CDATA[
<?php
// callback 函数示例
function my_callback_function() {
echo 'hello world!', PHP_EOL;
}
// callback 方法示例
class MyClass {
static function myCallbackMethod() {
echo 'Hello World!', PHP_EOL;
}
}
// 类型 1:简单回调
call_user_func('my_callback_function');
// 类型2:静态类方法回调
call_user_func(['MyClass', 'myCallbackMethod']);
// 类型 3:对象方法回调
$obj = new MyClass();
call_user_func([$obj, 'myCallbackMethod']);
// 类型 4:静态类方法回调
call_user_func('MyClass::myCallbackMethod');
// 类型 5:使用 ::class 关键字的静态类方法回调
call_user_func([MyClass::class, 'myCallbackMethod']);
// 类型 6:相对静态类方法调用
class A {
public static function who() {
echo 'A', PHP_EOL;
}
}
class B extends A {
public static function who() {
echo 'B', PHP_EOL;
}
}
call_user_func(['B', 'parent::who']); // 自 PHP 8.2.0 起弃用
// 类型 7:实现 __invoke 的对象用于 callable
class C {
public function __invoke($name) {
echo 'Hello ', $name;
}
}
$c = new C();
call_user_func($c, 'PHP!');
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
hello world!
Hello World!
Hello World!
Hello World!
Hello World!
Deprecated: Callables of the form ["B", "parent::who"] are deprecated in script on line 41
A
Hello PHP!
]]>
</screen>
</example>
¬e.func-callback-exceptions;
</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
-->