Sophie

Sophie

distrib > Mageia > 4 > i586 > by-pkgid > f800694edefe91adea2624f711a41a2d > files > 8281

php-manual-en-5.5.7-1.mga4.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Writing Functions</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="internals2.variables.objects.html">Working with Objects</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="internals2.classes.html">Writing Classes</a></div>
 <div class="up"><a href="internals2.html">PHP at the Core: A Hacker's Guide</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="internals2.funcs" class="chapter">
  <h1>Writing Functions</h1>

  <p class="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 class="code">Hacker</code> will read about class entries in other sections of the <code class="code">Hacker&#039;s</code> guide.
   The purpose of this section is to introduce the <code class="code">Hacker</code> to the anatomy of a function or method; 
   the <code class="code">Hacker</code> will learn how to define functions, how to accept variables and how to return variables to the programmer of PHP.
  </p>

  <p class="para">
   The anatomy of a function could not be simpler:
  </p>
  
  <div class="example-contents screen">
<div class="cdata"><pre>
PHP_FUNCTION(hackers_function) {
  /* your accepted arguments here */
  long number;
  
  /* accepting arguments */
  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, &quot;l&quot;, &amp;number) != SUCCESS) {
      return;
  }
  
  /* do some work on the input */
  number *= 2;
  
  /* set return value */
  RETURN_LONG(number);
}</pre></div>
  </div>
  
  <p class="para">
   The <code class="code">PHP_FUNCTION(hackers_function)</code> preprocessor instruction will result in the following declaration:
  </p>
  
  <div class="example-contents screen">
<div class="cdata"><pre>
void zif_hackers_function(INTERNAL_FUNCTION_PARAMETERS)
</pre></div>
  </div>
  
  <p class="para">
   <code class="code">INTERNAL_FUNCTION_PARAMETERS</code> is defined as a macro and explained in the following table:
  </p>
  
  <table id="internals2.funcs.index.internal-func-params" class="doctable table">
   <caption><strong>INTERNAL_FUNCTION_PARAMETERS</strong></caption>
   
    <thead>
     <tr>
      <th>Name and type</th>
      <th>Description</th>
      <th>Access macros</th>
     </tr>

    </thead>

    <tbody class="tbody">
                                                    
     <tr>
      <td><code class="code">int ht</code></td>
      <td>Number of actual parameters passed by user</td>
      <td><code class="code">ZEND_NUM_ARGS()</code></td>
     </tr>


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


     <tr>
      <td><code class="code">zval **return_value_ptr</code></td>
      <td>When returning references to PHP set this to a pointer to
       your variable. It is not suggested to return references.</td>
      <td class="empty">&nbsp;</td>
     </tr>


     <tr>
      <td><code class="code">zval *this_ptr</code></td>
      <td>
       If this is a method call, points to the PHP variable
       holding the <code class="code">$this</code> object.
      </td>
      <td><code class="code">getThis()</code></td>
     </tr>


     <tr>
      <td><code class="code">int return_value_used</code></td>
      <td>
       Flag indicating whether the returned value will be used by the
       caller.
      </td>
      <td class="empty">&nbsp;</td>
     </tr>


    </tbody>
   
  </table>

  
  <p class="para">
   For clarity, the fully expanded declaration for <code class="code">PHP_FUNCTION(hackers_function)</code> looks like:
  </p>
  
  <div class="example-contents screen">
<div class="cdata"><pre>
void zif_hackers_function(int ht, zval* return_value, zval** return_value_ptr, zval* this_ptr, int return_value_used)
</pre></div>
  </div>
  
  <p class="para">
    The precense of <code class="code">this_ptr</code> may be confusing, classes are covered in detail in later sections, 
    suffice to say that <code class="code">PHP_METHOD(MyClass, hackersFunction)</code> would result in the following declaration:
  </p>
  
  <div class="example-contents screen">
<div class="cdata"><pre>
void zim_MyClass_hackersFunction(INTERNAL_FUNCTION_PARAMETERS)
</pre></div>
  </div>
  
  <p class="para">
   <code class="code">hackers_function</code> doesn&#039;t do anything useful, it accepts a number using the <code class="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 class="code">return_value</code> is allocated and initialized to <code class="code">null</code>, making <code class="code">null</code> the default return value of any function in PHP.
  </p>
  
  <p class="para">
   If <code class="code">zend_parse_parameters</code> does not recieve what is specified by the <code class="code">Hacker</code> as the correct arguments, and the arguments recieved cannot be converted
   to conform with <code class="code">type_spec</code> an error will be raised, and by convention, the <code class="code">Hacker</code> should <code class="code">return</code> immediately.
  </p>
  
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para"><code class="code">Arrays</code>, <code class="code">Objects</code>, and <code class="code">Resources</code> cannot be converted.</p>
  </p></blockquote>
  
  <table id="internals2.funcs.parameters.api" class="doctable table">
   <caption><strong>Parsing Parameters Prototypes</strong></caption>
   
    <tbody class="tbody">
     <tr>
      <td><code class="code">int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...)</code></td>
     </tr>

     <tr>
      <td><code class="code">int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...)</code></td>
     </tr>

     <tr>
      <td><code class="code">int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)</code></td>
     </tr>

    </tbody>
   
  </table>

  
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para">
    <code class="code">zend_parse_parameter</code> is available from version 5.5, it behaves like <code class="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.
   </p>
  </p></blockquote>
  
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para">
    <code class="code">flags</code> is intended to be a mask, currently only <code class="code">ZEND_PARSE_PARAMS_QUIET</code> will have any impact (supress warnings)
   </p>
  </p></blockquote>
  
  <p class="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 class="code">zend_parse_parameters</code> API functions.
  </p>

  <table id="internals2.funcs.parameters.types" class="doctable table">
   <caption><strong>Type Specifiers</strong></caption>
   
     <thead>
     <tr>
      <th>Spec</th>
      <th>Type</th>
      <th>Locals</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>a</td>
      <td><code class="code">array</code></td>
      <td><code class="code">zval*</code></td>
     </tr>

     <tr>
      <td>A</td>
      <td><code class="code">array</code> or <code class="code">object</code></td>
      <td><code class="code">zval*</code></td>
     </tr>

     <tr>
      <td>b</td>
      <td><code class="code">boolean</code></td>
      <td><code class="code">zend_bool</code></td>
     </tr>

     <tr>
      <td>C</td>
      <td><code class="code">class</code></td>
      <td><code class="code">zend_class_entry*</code></td>
     </tr>

     <tr>
      <td>d</td>
      <td><code class="code">double</code></td>
      <td><code class="code">double</code></td>
     </tr>

     <tr>
      <td>f</td>
      <td><code class="code">function</code></td>
      <td><code class="code">zend_fcall_info*</code>, <code class="code">zend_fcall_info_cache*</code></td>
     </tr>

     <tr>
      <td>h</td>
      <td><code class="code">array</code></td>
      <td><code class="code">HashTable*</code></td>
     </tr>

     <tr>
      <td>H</td>
      <td><code class="code">array</code> or <code class="code">object</code></td>
      <td><code class="code">HashTable*</code></td>
     </tr>

     <tr>
      <td>l</td>
      <td><code class="code">long</code></td>
      <td><code class="code">long</code></td>
     </tr>

     <tr>
      <td>L</td>
      <td><code class="code">long</code> (limits out-of-range LONG_MAX/LONG_MIN)</td>
      <td><code class="code">long</code></td>
     </tr>

     <tr>
      <td>o</td>
      <td><code class="code">object</code></td>
      <td><code class="code">zval*</code></td>
     </tr>

     <tr>
      <td>O</td>
      <td><code class="code">object</code> (of specified <code class="code">zend_class_entry</code>)</td>
      <td><code class="code">zval*</code>, <code class="code">zend_class_entry*</code></td>
     </tr>

     <tr>
      <td>p</td>
      <td><code class="code">string</code> (a valid path)</td>
      <td><code class="code">char*</code>, <code class="code">int</code></td>
     </tr>

     <tr>
      <td>r</td>
      <td><code class="code">resource</code></td>
      <td><code class="code">char*</code></td>
     </tr>

     <tr>
      <td>s</td>
      <td><code class="code">string</code></td>
      <td><code class="code">char*</code>, <code class="code">uint</code></td>
     </tr>

     <tr>
      <td>z</td>
      <td><code class="code">mixed</code></td>
      <td><code class="code">zval*</code></td>
     </tr>

     <tr>
      <td>Z</td>
      <td><code class="code">mixed</code></td>
      <td><code class="code">zval**</code></td>
     </tr>

    </tbody>
   
  </table>

  
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para">
    Where the type specifier is <code class="code">O</code>, the local <code class="code">zend_class_entry*</code> is to be 
    considered input (part of the type spec) to <code class="code">zend_parse_parameter</code>
   </p>
  </p></blockquote>
  
  <table id="internals2.funcs.parameters.advanced" class="doctable table">
   <caption><strong>Advanced Type Specifiers</strong></caption>
   
     <thead>
     <tr>
      <th>Spec</th>
      <th>Description</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>*</td>
      <td>a variable number of argument of the preceeding type, 0 or more</td>
     </tr>

     <tr>
      <td>+</td>
      <td>a variable number of argument of the preceeding type, 1 or more</td>
     </tr>

     <tr>
      <td>|</td>
      <td>indicates that the remaining parameters are optional</td>
     </tr>

     <tr>
      <td>/</td>
      <td><code class="code">SEPARATE_ZVAL_IF_NOT_REF</code> on the parameter it follows</td>
     </tr>

     <tr>
      <td>!</td>
      <td>
       the preceeding parameter can be of the specified type or <code class="code">null</code>
       For &#039;b&#039;, &#039;l&#039; and &#039;d&#039;, an extra argument of type zend_bool* must be passed after 
       the corresponding <code class="code">bool*</code>, <code class="code">long*</code> or <code class="code">double*</code> 
       addresses which will be set <code class="code">true</code> if <code class="code">null</code> is recieved.
      </td>
     </tr>

    </tbody>
   
  </table>

  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para">Consult <code class="code">README.PARAMETER_PARSING_API</code> included in source distributions for more information on parsing parameters</p>
  </p></blockquote>
  
  <p class="para">
   Once the <code class="code">Hacker&#039;s</code> function has executed whatever it was implemented to execute, it is time to set the <code class="code">return_value</code> for the engine. 
   The <code class="code">RETURN_</code> and <code class="code">RETVAL_</code> macros are just wrappers around <code class="code">Z_*_P</code> macros that work with <code class="code">return_value</code>. 
  </p>
  
  <blockquote class="note"><p><strong class="note">Note</strong>: 
   <p class="para"><code class="code">RETURN_</code> macros cause execution to leave the function immediately (ie: <code class="code">return;</code>), while <code class="code">RETVAL_</code> macros allow execution to continue after <code class="code">return_value</code> has been set.</p>
  </p></blockquote>
  
  <p class="para">
   The <code class="code">Hacker</code> should now have a reasonable understanding of the anatomy of a function, and to some degree, the anatomy of a method.
  </p>

</div>
<hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="internals2.variables.objects.html">Working with Objects</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="internals2.classes.html">Writing Classes</a></div>
 <div class="up"><a href="internals2.html">PHP at the Core: A Hacker's Guide</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>