File: index.xml

package info (click to toggle)
php-doc 20140201-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 74,084 kB
  • ctags: 4,040
  • sloc: xml: 998,137; php: 20,812; cpp: 500; sh: 177; makefile: 63; awk: 28
file content (358 lines) | stat: -rw-r--r-- 11,624 bytes parent folder | download
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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 330100 $ -->
 <chapter xml:id="internals2.funcs" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Writing Functions</title>
  <para>
   Functions and Methods in PHP take much the same form, a method is simply a function with a specific scope; the scope of their class entry.
   The <code>Hacker</code> will read about class entries in other sections of the <code>Hacker's</code> guide.
   The purpose of this section is to introduce the <code>Hacker</code> to the anatomy of a function or method; 
   the <code>Hacker</code> will learn how to define functions, how to accept variables and how to return variables to the programmer of PHP.
  </para>

  <para>
   The anatomy of a function could not be simpler:
  </para>
  
  <screen>
<![CDATA[
PHP_FUNCTION(hackers_function) {
  /* your accepted arguments here */
  long number;
  
  /* accepting arguments */
  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &number) != SUCCESS) {
      return;
  }
  
  /* do some work on the input */
  number *= 2;
  
  /* set return value */
  RETURN_LONG(number);
}]]>
  </screen>
  
  <para>
   The <code>PHP_FUNCTION(hackers_function)</code> preprocessor instruction will result in the following declaration:
  </para>
  
  <screen>
<![CDATA[
void zif_hackers_function(INTERNAL_FUNCTION_PARAMETERS)
]]>
  </screen>
  
  <para>
   <code>INTERNAL_FUNCTION_PARAMETERS</code> is defined as a macro and explained in the following table:
  </para>
  
  <table xml:id="internals2.funcs.index.internal-func-params">
   <title>INTERNAL_FUNCTION_PARAMETERS</title>
   <tgroup cols="3">
    <thead>
     <row>
      <entry>Name and type</entry>
      <entry>Description</entry>
      <entry>Access macros</entry>
     </row>
    </thead>
    <tbody>
                                                    
     <row>
      <entry><code>int ht</code></entry>
      <entry>Number of actual parameters passed by user</entry>
      <entry><code>ZEND_NUM_ARGS()</code></entry>
     </row>

     <row>
      <entry><code>zval *return_value</code></entry>
      <entry>
       Pointer to a PHP variable that can be filled with the return value
       passed to the user. The default type is <code>IS_NULL</code>.
      </entry>
      <entry><code>RETVAL_*</code>, <code>RETURN_*</code></entry>
     </row>

     <row>
      <entry><code>zval **return_value_ptr</code></entry>
      <entry>When returning references to PHP set this to a pointer to
       your variable. It is not suggested to return references.</entry>
      <entry/>
     </row>

     <row>
      <entry><code>zval *this_ptr</code></entry>
      <entry>
       If this is a method call, points to the PHP variable
       holding the <code>$this</code> object.
      </entry>
      <entry><code>getThis()</code></entry>
     </row>

     <row>
      <entry><code>int return_value_used</code></entry>
      <entry>
       Flag indicating whether the returned value will be used by the
       caller.
      </entry>
      <entry/>
     </row>

    </tbody>
   </tgroup>
  </table>
  
  <para>
   For clarity, the fully expanded declaration for <code>PHP_FUNCTION(hackers_function)</code> looks like:
  </para>
  
  <screen>
<![CDATA[
void zif_hackers_function(int ht, zval* return_value, zval** return_value_ptr, zval* this_ptr, int return_value_used)
]]>
  </screen>
  
  <para>
    The precense of <code>this_ptr</code> may be confusing, classes are covered in detail in later sections, 
    suffice to say that <code>PHP_METHOD(MyClass, hackersFunction)</code> would result in the following declaration:
  </para>
  
  <screen>
<![CDATA[
void zim_MyClass_hackersFunction(INTERNAL_FUNCTION_PARAMETERS)
]]>
  </screen>
  
  <para>
   <code>hackers_function</code> doesn't do anything useful, it accepts a number using the <code>zend_parse_parameters</code> API, doubles it, and returns it to the engine.
   It is obvious that a normal function would have to do something more complex than double the input, for the purposes of education we are keeping it simple. 
   On entry to the function <code>return_value</code> is allocated and initialized to <code>null</code>, making <code>null</code> the default return value of any function in PHP.
  </para>
  
  <para>
   If <code>zend_parse_parameters</code> does not recieve what is specified by the <code>Hacker</code> as the correct arguments, and the arguments recieved cannot be converted
   to conform with <code>type_spec</code> an error will be raised, and by convention, the <code>Hacker</code> should <code>return</code> immediately.
  </para>
  
  <note>
   <para><code>Arrays</code>, <code>Objects</code>, and <code>Resources</code> cannot be converted.</para>
  </note>
  
  <table xml:id="internals2.funcs.parameters.api">
   <title>Parsing Parameters Prototypes</title>
   <tgroup cols="1">
    <tbody>
     <row>
      <entry><code>int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...)</code></entry>
     </row>
     <row>
      <entry><code>int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...)</code></entry>
     </row>
     <row>
      <entry><code>int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)</code></entry>
     </row>
    </tbody>
   </tgroup>
  </table>
  
  <note>
   <para>
    <code>zend_parse_parameter</code> is available from version 5.5, it behaves like <code>zend_parse_parameters_ex</code> 
    except that instead of reading the arguments from the stack, it receives a single zval to convert, which may be changed in place.
   </para>
  </note>
  
  <note>
   <para>
    <code>flags</code> is intended to be a mask, currently only <code>ZEND_PARSE_PARAMS_QUIET</code> will have any impact (supress warnings)
   </para>
  </note>
  
  <para>
   The variable arguments recieved by these API functions are expected to be the address of C variables, and should be considered the output of the <code>zend_parse_parameters</code> API functions.
  </para>

  <table xml:id="internals2.funcs.parameters.types">
   <title>Type Specifiers</title>
   <tgroup cols="3">
     <thead>
     <row>
      <entry>Spec</entry>
      <entry>Type</entry>
      <entry>Locals</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>a</entry>
      <entry><code>array</code></entry>
      <entry><code>zval*</code></entry>
     </row>
     <row>
      <entry>A</entry>
      <entry><code>array</code> or <code>object</code></entry>
      <entry><code>zval*</code></entry>
     </row>
     <row>
      <entry>b</entry>
      <entry><code>boolean</code></entry>
      <entry><code>zend_bool</code></entry>
     </row>
     <row>
      <entry>C</entry>
      <entry><code>class</code></entry>
      <entry><code>zend_class_entry*</code></entry>
     </row>
     <row>
      <entry>d</entry>
      <entry><code>double</code></entry>
      <entry><code>double</code></entry>
     </row>
     <row>
      <entry>f</entry>
      <entry><code>function</code></entry>
      <entry><code>zend_fcall_info*</code>, <code>zend_fcall_info_cache*</code></entry>
     </row>
     <row>
      <entry>h</entry>
      <entry><code>array</code></entry>
      <entry><code>HashTable*</code></entry>
     </row>
     <row>
      <entry>H</entry>
      <entry><code>array</code> or <code>object</code></entry>
      <entry><code>HashTable*</code></entry>
     </row>
     <row>
      <entry>l</entry>
      <entry><code>long</code></entry>
      <entry><code>long</code></entry>
     </row>
     <row>
      <entry>L</entry>
      <entry><code>long</code> (limits out-of-range LONG_MAX/LONG_MIN)</entry>
      <entry><code>long</code></entry>
     </row>
     <row>
      <entry>o</entry>
      <entry><code>object</code></entry>
      <entry><code>zval*</code></entry>
     </row>
     <row>
      <entry>O</entry>
      <entry><code>object</code> (of specified <code>zend_class_entry</code>)</entry>
      <entry><code>zval*</code>, <code>zend_class_entry*</code></entry>
     </row>
     <row>
      <entry>p</entry>
      <entry><code>string</code> (a valid path)</entry>
      <entry><code>char*</code>, <code>int</code></entry>
     </row>
     <row>
      <entry>r</entry>
      <entry><code>resource</code></entry>
      <entry><code>char*</code></entry>
     </row>
     <row>
      <entry>s</entry>
      <entry><code>string</code></entry>
      <entry><code>char*</code>, <code>uint</code></entry>
     </row>
     <row>
      <entry>z</entry>
      <entry><code>mixed</code></entry>
      <entry><code>zval*</code></entry>
     </row>
     <row>
      <entry>Z</entry>
      <entry><code>mixed</code></entry>
      <entry><code>zval**</code></entry>
     </row>
    </tbody>
   </tgroup>
  </table>
  
  <note>
   <para>
    Where the type specifier is <code>O</code>, the local <code>zend_class_entry*</code> is to be 
    considered input (part of the type spec) to <code>zend_parse_parameter</code>
   </para>
  </note>
  
  <table xml:id="internals2.funcs.parameters.advanced">
   <title>Advanced Type Specifiers</title>
   <tgroup cols="3">
     <thead>
     <row>
      <entry>Spec</entry>
      <entry>Description</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>*</entry>
      <entry>a variable number of argument of the preceeding type, 0 or more</entry>
     </row>
     <row>
      <entry>+</entry>
      <entry>a variable number of argument of the preceeding type, 1 or more</entry>
     </row>
     <row>
      <entry>|</entry>
      <entry>indicates that the remaining parameters are optional</entry>
     </row>
     <row>
      <entry>/</entry>
      <entry><code>SEPARATE_ZVAL_IF_NOT_REF</code> on the parameter it follows</entry>
     </row>
     <row>
      <entry>!</entry>
      <entry>
       the preceeding parameter can be of the specified type or <code>null</code>
       For 'b', 'l' and 'd', an extra argument of type zend_bool* must be passed after 
       the corresponding <code>bool*</code>, <code>long*</code> or <code>double*</code> 
       addresses which will be set <code>true</code> if <code>null</code> is recieved.
      </entry>
     </row>
    </tbody>
   </tgroup>
  </table>
  <note>
   <para>Consult <code>README.PARAMETER_PARSING_API</code> included in source distributions for more information on parsing parameters</para>
  </note>
  
  <para>
   Once the <code>Hacker's</code> function has executed whatever it was implemented to execute, it is time to set the <code>return_value</code> for the engine. 
   The <code>RETURN_</code> and <code>RETVAL_</code> macros are just wrappers around <code>Z_*_P</code> macros that work with <code>return_value</code>. 
  </para>
  
  <note>
   <para><code>RETURN_</code> macros cause execution to leave the function immediately (ie: <code>return;</code>), while <code>RETVAL_</code> macros allow execution to continue after <code>return_value</code> has been set.</para>
  </note>
  
  <para>
   The <code>Hacker</code> should now have a reasonable understanding of the anatomy of a function, and to some degree, the anatomy of a method.
  </para>

</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
-->