reference/funchand/functions/create-function.xml
39752929cd4ab78db8a7310dfb328444c558df99
...
...
@@ -3,9 +3,13 @@
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
+
<refsynopsisdiv>
10
+
&warn.deprecated.function-7-2-0.removed-8-0-0;
11
+
</refsynopsisdiv>
12
+

9
13
<refsect1 role="description">
10
14
&reftitle.description;
11
15
<methodsynopsis>
...
...
@@ -14,17 +18,17 @@
14
18
<methodparam><type>string</type><parameter>code</parameter></methodparam>
15
19
</methodsynopsis>
16
20
<para>
17
-
Creates an anonymous function from the parameters passed, and
18
-
returns a unique name for it.
21
+
Creates a function dynamically from the parameters passed, and returns a unique name for it.
19
22
</para>
20
23
<caution>
21
24
<para>
22
25
This function internally performs an <function>eval</function> and as such has the
23
-
same security issues as <function>eval</function>. Additionally it has bad performance
24
-
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.
25
29
</para>
26
30
<para>
27
-
If you are using PHP 5.3.0 or newer a native
31
+
A native
28
32
<link linkend="functions.anonymous">anonymous function</link> should be used instead.
29
33
</para>
30
34
</caution>
...
...
@@ -32,16 +36,17 @@
32
36
<refsect1 role="parameters">
33
37
&reftitle.parameters;
34
38
<para>
35
-
Usually these parameters will be passed as single quote delimited strings.
36
-
The reason for using single quoted strings, is to protect the variable
37
-
names from parsing, otherwise, if you use double quotes there will be a
38
-
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>.
39
44
<variablelist>
40
45
<varlistentry>
41
46
<term><parameter>args</parameter></term>
42
47
<listitem>
43
48
<para>
44
-
The function arguments.
49
+
The function arguments, as a single comma-separated string.
45
50
</para>
46
51
</listitem>
47
52
</varlistentry>
...
...
@@ -60,7 +65,10 @@
60
65
<refsect1 role="returnvalues">
61
66
&reftitle.returnvalues;
62
67
<para>
63
-
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.
64
72
</para>
65
73
</refsect1>
66
74

...
...
@@ -69,36 +77,51 @@
69
77
<para>
70
78
<example>
71
79
<title>
72
-
Creating an anonymous function with <function>create_function</function>
80
+
Creating a function dynamically, with <function>create_function</function>
81
+
or anonymous functions
73
82
</title>
74
83
<para>
75
-
You can use this function, to (for example) create a function from
76
-
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>:
77
86
</para>
78
87
<programlisting role="php">
79
88
<![CDATA[
80
89
<?php
81
90
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
82
-
echo "New anonymous function: $newfunc\n";
83
91
echo $newfunc(2, M_E) . "\n";
84
-
// outputs
85
-
// New anonymous function: lambda_1
86
-
// ln(2) + ln(2.718281828459) = 1.6931471805599
87
92
?>
88
93
]]>
89
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>
90
113
</example>
91
114
</para>
92
115
<para>
93
-
Or, perhaps to have general handler function that can apply a set
94
-
of operations to a list of parameters:
95
-
</para>
96
-
<para>
97
116
<example>
98
117
<title>
99
-
Making a general processing function with
100
-
<function>create_function</function>
118
+
Making a general processing function, with <function>create_function</function>
119
+
or anonymous functions
101
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>
102
125
<programlisting role="php">
103
126
<![CDATA[
104
127
<?php
...
...
@@ -110,29 +133,67 @@ function process($var1, $var2, $farr)
110
133
}
111
134

112
135
// create a bunch of math functions
113
-
$f1 = 'if ($a >=0) {return "b*a^2 = ".$b*sqrt($a);} else {return false;}';
114
-
$f2 = "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);";
115
-
$f3 = 'if ($a > 0 && $b != 0) {return "ln(a)/b = ".log($a)/$b; } else { return false; }';
116
136
$farr = array(
117
137
create_function('$x,$y', 'return "some trig: ".(sin($x) + $x*cos($y));'),
118
138
create_function('$x,$y', 'return "a hypotenuse: ".sqrt($x*$x + $y*$y);'),
119
-
create_function('$a,$b', $f1),
120
-
create_function('$a,$b', $f2),
121
-
create_function('$a,$b', $f3)
122
-
);
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
+
);
123
143

124
-
echo "\nUsing the first array of anonymous functions\n";
144
+
echo "\nUsing the first array of dynamic functions\n";
125
145
echo "parameters: 2.3445, M_PI\n";
126
146
process(2.3445, M_PI, $farr);
127
147

128
148
// now make a bunch of string processing functions
129
149
$garr = array(
130
150
create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
131
-
'and \"$b\"\n** Look the same to me! (looking at the first 3 chars)";'),
132
-
create_function('$a,$b', '; return "CRCs: " . crc32($a) . ", ".crc32($b);'),
133
-
create_function('$a,$b', '; return "similar(a,b) = " . similar_text($a, $b, &$p) . "($p%)";')
134
-
);
135
-
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";
136
197
process("Twas brilling and the slithy toves", "Twas the night", $garr);
137
198
?>
138
199
]]>
...
...
@@ -140,7 +201,7 @@ process("Twas brilling and the slithy toves", "Twas the night", $garr);
140
201
&example.outputs;
141
202
<screen>
142
203
<![CDATA[
143
-
Using the first array of anonymous functions
204
+
Using the first array of dynamic functions
144
205
parameters: 2.3445, M_PI
145
206
some trig: -1.6291725057799
146
207
a hypotenuse: 3.9199852871011
...
...
@@ -148,23 +209,23 @@ b*a^2 = 4.8103313314525
148
209
min(b^2+a, a^2,b) = 8.6382729035898
149
210
ln(a)/b = 0.27122299212594
150
211

151
-
Using the second array of anonymous functions
212
+
Using the second array of dynamic functions
152
213
** "Twas the night" and "Twas brilling and the slithy toves"
153
214
** Look the same to me! (looking at the first 3 chars)
154
-
CRCs: -725381282, 342550513
215
+
CRCs: 3569586014, 342550513
155
216
similar(a,b) = 11(45.833333333333%)
156
217
]]>
157
218
</screen>
158
219
</example>
159
220
</para>
160
221
<para>
161
-
But perhaps the most common use for of lambda-style (anonymous) functions
162
-
is to create callback functions, for example when using
163
-
<function>array_walk</function> or <function>usort</function>
164
-
</para>
165
-
<para>
166
222
<example>
167
-
<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>
168
229
<programlisting role="php">
169
230
<![CDATA[
170
231
<?php
...
...
@@ -174,6 +235,18 @@ print_r($av);
174
235
?>
175
236
]]>
176
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>
177
250
&example.outputs;
178
251
<screen>
179
252
<![CDATA[
...
...
@@ -187,46 +260,47 @@ Array
187
260
]]>
188
261
</screen>
189
262
<para>
190
-
an array of strings ordered from shorter to longer
263
+
Sorting strings from longest to shortest with <function>create_function</function>:
191
264
</para>
192
265
<programlisting role="php">
193
266
<![CDATA[
194
267
<?php
195
-

196
-
$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);'));
197
273
print_r($sv);
198
-

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

221
-
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); });
222
288
print_r($sv);
223
-

224
289
?>
225
290
]]>
226
291
</programlisting>
227
292
&example.outputs;
228
293
<screen>
229
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:
230
304
Array
231
305
(
232
306
[0] => it is a string thing
233
307