reference/funchand/functions/create-function.xml
39752929cd4ab78db8a7310dfb328444c558df99
...
...
@@ -3,11 +3,11 @@
3
3
<refentry xml:id="function.create-function" xmlns="http://docbook.org/ns/docbook">
4
4
<refnamediv>
5
5
<refname>create_function</refname>
6
-
<refpurpose>Create an anonymous (lambda-style) function</refpurpose>
6
+
<refpurpose>Create a function dynamically by evaluating a string of code</refpurpose>
7
7
</refnamediv>
8
8

9
9
<refsynopsisdiv>
10
-
&warn.deprecated.function-7-2-0;
10
+
&warn.deprecated.function-7-2-0.removed-8-0-0;
11
11
</refsynopsisdiv>
12
12

13
13
<refsect1 role="description">
...
...
@@ -18,17 +18,17 @@
18
18
<methodparam><type>string</type><parameter>code</parameter></methodparam>
19
19
</methodsynopsis>
20
20
<para>
21
-
Creates an anonymous function from the parameters passed, and
22
-
returns a unique name for it.
21
+
Creates a function dynamically from the parameters passed, and returns a unique name for it.
23
22
</para>
24
23
<caution>
25
24
<para>
26
25
This function internally performs an <function>eval</function> and as such has the
27
-
same security issues as <function>eval</function>. Additionally it has bad performance
28
-
and memory usage characteristics.
26
+
same security issues as <function>eval</function>. It also has bad performance
27
+
and memory usage characteristics, because the created functions are global and
28
+
can not be freed.
29
29
</para>
30
30
<para>
31
-
If you are using PHP 5.3.0 or newer a native
31
+
A native
32
32
<link linkend="functions.anonymous">anonymous function</link> should be used instead.
33
33
</para>
34
34
</caution>
...
...
@@ -36,16 +36,17 @@
36
36
<refsect1 role="parameters">
37
37
&reftitle.parameters;
38
38
<para>
39
-
Usually these parameters will be passed as single quote delimited strings.
40
-
The reason for using single quoted strings, is to protect the variable
41
-
names from parsing, otherwise, if you use double quotes there will be a
42
-
need to escape the variable names, e.g. <literal>\$avar</literal>.
39
+
It is normally advisable to pass these parameters as
40
+
<link linkend="language.types.string.syntax.single">single quoted</link>
41
+
strings. If using <link linkend="language.types.string.syntax.double">double quoted</link>
42
+
strings, variable names in the code need to be escaped carefully, e.g.
43
+
<literal>\$somevar</literal>.
43
44
<variablelist>
44
45
<varlistentry>
45
46
<term><parameter>args</parameter></term>
46
47
<listitem>
47
48
<para>
48
-
The function arguments.
49
+
The function arguments, as a single comma-separated string.
49
50
</para>
50
51
</listitem>
51
52
</varlistentry>
...
...
@@ -64,7 +65,10 @@
64
65
<refsect1 role="returnvalues">
65
66
&reftitle.returnvalues;
66
67
<para>
67
-
Returns a unique function name as a string, or &false; on error.
68
+
Returns a unique function name as a string, &return.falseforfailure;.
69
+
Note that the name contains a non-printable character (<literal>"\0"</literal>),
70
+
so care should be taken when printing the name or incorporating it in any other
71
+
string.
68
72
</para>
69
73
</refsect1>
70
74

...
...
@@ -73,36 +77,51 @@
73
77
<para>
74
78
<example>
75
79
<title>
76
-
Creating an anonymous function with <function>create_function</function>
80
+
Creating a function dynamically, with <function>create_function</function>
81
+
or anonymous functions
77
82
</title>
78
83
<para>
79
-
You can use this function, to (for example) create a function from
80
-
information gathered at run time:
84
+
You can use a dynamically created function, to (for example) create a function from
85
+
information gathered at run time. First, using <function>create_function</function>:
81
86
</para>
82
87
<programlisting role="php">
83
88
<![CDATA[
84
89
<?php
85
90
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
86
-
echo "New anonymous function: $newfunc\n";
87
91
echo $newfunc(2, M_E) . "\n";
88
-
// outputs
89
-
// New anonymous function: lambda_1
90
-
// ln(2) + ln(2.718281828459) = 1.6931471805599
91
92
?>
92
93
]]>
93
94
</programlisting>
95
+
<para>
96
+
Now the same code, using an <link linkend="functions.anonymous">anonymous function</link>;
97
+
note that the code and arguments are no longer contained in strings:
98
+
</para>
99
+
<programlisting role="php">
100
+
<![CDATA[
101
+
<?php
102
+
$newfunc = function($a,$b) { return "ln($a) + ln($b) = " . log($a * $b); };
103
+
echo $newfunc(2, M_E) . "\n";
104
+
?>
105
+
]]>
106
+
</programlisting>
107
+
&example.outputs;
108
+
<screen>
109
+
<![CDATA[
110
+
ln(2) + ln(2.718281828459) = 1.6931471805599
111
+
]]>
112
+
</screen>
94
113
</example>
95
114
</para>
96
115
<para>
97
-
Or, perhaps to have general handler function that can apply a set
98
-
of operations to a list of parameters:
99
-
</para>
100
-
<para>
101
116
<example>
102
117
<title>
103
-
Making a general processing function with
104
-
<function>create_function</function>
118
+
Making a general processing function, with <function>create_function</function>
119
+
or anonymous functions
105
120
</title>
121
+
<para>
122
+
Another use could be to have general handler function that can apply a set
123
+
of operations to a list of parameters:
124
+
</para>
106
125
<programlisting role="php">
107
126
<![CDATA[
108
127
<?php
...
...
@@ -114,29 +133,67 @@ function process($var1, $var2, $farr)
114
133
}
115
134

116
135
// create a bunch of math functions
117
-
$f1 = 'if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;}';
118
-
$f2 = "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);";
119
-
$f3 = 'if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; }';
120
136
$farr = array(
121
137
create_function('$x,$y', 'return "some trig: ".(sin($x) + $x*cos($y));'),
122
138
create_function('$x,$y', 'return "a hypotenuse: ".sqrt($x*$x + $y*$y);'),
123
-
create_function('$a,$b', $f1),
124
-
create_function('$a,$b', $f2),
125
-
create_function('$a,$b', $f3)
126
-
);
139
+
create_function('$a,$b', 'if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;}'),
140
+
create_function('$a,$b', "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);"),
141
+
create_function('$a,$b', 'if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; }')
142
+
);
127
143

128
-
echo "\nUsing the first array of anonymous functions\n";
144
+
echo "\nUsing the first array of dynamic functions\n";
129
145
echo "parameters: 2.3445, M_PI\n";
130
146
process(2.3445, M_PI, $farr);
131
147

132
148
// now make a bunch of string processing functions
133
149
$garr = array(
134
150
create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
135
-
'and \"$b\"\n** Look the same to me! (looking at the first 3 chars)";'),
136
-
create_function('$a,$b', '; return "CRCs: " . crc32($a) . ", ".crc32($b);'),
137
-
create_function('$a,$b', '; return "similar(a,b) = " . similar_text($a, $b, &$p) . "($p%)";')
138
-
);
139
-
echo "\nUsing the second array of anonymous functions\n";
151
+
'and \"$b\"\n** Look the same to me! (looking at the first 3 chars)";'),
152
+
create_function('$a,$b', 'return "CRCs: " . crc32($a) . ", ".crc32($b);'),
153
+
create_function('$a,$b', 'return "similar(a,b) = " . similar_text($a, $b, $p) . "($p%)";')
154
+
);
155
+
echo "\nUsing the second array of dynamic functions\n";
156
+
process("Twas brilling and the slithy toves", "Twas the night", $garr);
157
+
?>
158
+
]]>
159
+
</programlisting>
160
+
<para>
161
+
Again, here is the same code using
162
+
<link linkend="functions.anonymous">anonymous functions</link>.
163
+
Note that variable names in the code no longer need to be escaped,
164
+
because they are not enclosed in a string.
165
+
</para>
166
+
<programlisting role="php">
167
+
<![CDATA[
168
+
<?php
169
+
function process($var1, $var2, $farr)
170
+
{
171
+
foreach ($farr as $f) {
172
+
echo $f($var1, $var2) . "\n";
173
+
}
174
+
}
175
+

176
+
// create a bunch of math functions
177
+
$farr = array(
178
+
function($x,$y) { return "some trig: ".(sin($x) + $x*cos($y)); },
179
+
function($x,$y) { return "a hypotenuse: ".sqrt($x*$x + $y*$y); },
180
+
function($a,$b) { if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;} },
181
+
function($a,$b) { return "min(b^2+a, a^2,b) = " . min($a*$a+$b, $b*$b+$a); },
182
+
function($a,$b) { if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; } }
183
+
);
184
+

185
+
echo "\nUsing the first array of dynamic functions\n";
186
+
echo "parameters: 2.3445, M_PI\n";
187
+
process(2.3445, M_PI, $farr);
188
+

189
+
// now make a bunch of string processing functions
190
+
$garr = array(
191
+
function($b,$a) { if (strncmp($a, $b, 3) == 0) return "** \"$a\" " .
192
+
"and \"$b\"\n** Look the same to me! (looking at the first 3 chars)"; },
193
+
function($a,$b) { return "CRCs: " . crc32($a) . ", ".crc32($b); },
194
+
function($a,$b) { return "similar(a,b) = " . similar_text($a, $b, $p) . "($p%)"; }
195
+
);
196
+
echo "\nUsing the second array of dynamic functions\n";
140
197
process("Twas brilling and the slithy toves", "Twas the night", $garr);
141
198
?>
142
199
]]>
...
...
@@ -144,7 +201,7 @@ process("Twas brilling and the slithy toves", "Twas the night", $garr);
144
201
&example.outputs;
145
202
<screen>
146
203
<![CDATA[
147
-
Using the first array of anonymous functions
204
+
Using the first array of dynamic functions
148
205
parameters: 2.3445, M_PI
149
206
some trig: -1.6291725057799
150
207
a hypotenuse: 3.9199852871011
...
...
@@ -152,23 +209,23 @@ b*a^2 = 4.8103313314525
152
209
min(b^2+a, a^2,b) = 8.6382729035898
153
210
ln(a)/b = 0.27122299212594
154
211

155
-
Using the second array of anonymous functions
212
+
Using the second array of dynamic functions
156
213
** "Twas the night" and "Twas brilling and the slithy toves"
157
214
** Look the same to me! (looking at the first 3 chars)
158
-
CRCs: -725381282, 342550513
215
+
CRCs: 3569586014, 342550513
159
216
similar(a,b) = 11(45.833333333333%)
160
217
]]>
161
218
</screen>
162
219
</example>
163
220
</para>
164
221
<para>
165
-
But perhaps the most common use for of lambda-style (anonymous) functions
166
-
is to create callback functions, for example when using
167
-
<function>array_walk</function> or <function>usort</function>
168
-
</para>
169
-
<para>
170
222
<example>
171
-
<title>Using anonymous functions as callback functions</title>
223
+
<title>Using dynamic functions as callback functions</title>
224
+
<para>
225
+
Perhaps the most common use for dynamic functions
226
+
is to pass them as callbacks, for example when using
227
+
<function>array_walk</function> or <function>usort</function>.
228
+
</para>
172
229
<programlisting role="php">
173
230
<![CDATA[
174
231
<?php
...
...
@@ -178,6 +235,18 @@ print_r($av);
178
235
?>
179
236
]]>
180
237
</programlisting>
238
+
<para>
239
+
Converted to an <link linkend="functions.anonymous">anonymous function</link>:
240
+
</para>
241
+
<programlisting role="php">
242
+
<![CDATA[
243
+
<?php
244
+
$av = array("the ", "a ", "that ", "this ");
245
+
array_walk($av, function(&$v,$k) { $v = $v . "mango"; });
246
+
print_r($av);
247
+
?>
248
+
]]>
249
+
</programlisting>
181
250
&example.outputs;
182
251
<screen>
183
252
<![CDATA[
...
...
@@ -191,46 +260,47 @@ Array
191
260
]]>
192
261
</screen>
193
262
<para>
194
-
an array of strings ordered from shorter to longer
263
+
Sorting strings from longest to shortest with <function>create_function</function>:
195
264
</para>
196
265
<programlisting role="php">
197
266
<![CDATA[
198
267
<?php
199
-

200
-
$sv = array("small", "larger", "a big string", "it is a string thing");
268
+
$sv = array("small", "a big string", "larger", "it is a string thing");
269
+
echo "Original:\n";
270
+
print_r($sv);
271
+
echo "Sorted:\n";
272
+
usort($sv, create_function('$a,$b','return strlen($b) - strlen($a);'));
201
273
print_r($sv);
202
-

203
274
?>
204
275
]]>
205
276
</programlisting>
206
-
&example.outputs;
207
-
<screen>
208
-
<![CDATA[
209
-
Array
210
-
(
211
-
[0] => small
212
-
[1] => larger
213
-
[2] => a big string
214
-
[3] => it is a string thing
215
-
)
216
-
]]>
217
-
</screen>
218
277
<para>
219
-
sort it from longer to shorter
278
+
Converted to an <link linkend="functions.anonymous">anonymous function</link>:
220
279
</para>
221
280
<programlisting role="php">
222
281
<![CDATA[
223
282
<?php
224
-

225
-
usort($sv, create_function('$a,$b','return strlen($b) - strlen($a);'));
283
+
$sv = array("small", "a big string", "larger", "it is a string thing");
284
+
echo "Original:\n";
285
+
print_r($sv);
286
+
echo "Sorted:\n";
287
+
usort($sv, function($a,$b) { return strlen($b) - strlen($a); });
226
288
print_r($sv);
227
-

228
289
?>
229
290
]]>
230
291
</programlisting>
231
292
&example.outputs;
232
293
<screen>
233
294
<![CDATA[
295
+
Original:
296
+
Array
297
+
(
298
+
[0] => small
299
+
[1] => a big string
300
+
[2] => larger
301
+
[3] => it is a string thing
302
+
)
303
+
Sorted:
234
304
Array
235
305
(
236
306
[0] => it is a string thing
237
307