<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "/usr/local/share/xml/docbook/4.2/docbookx.dtd">
<article class="techreport" lang="fr">

<!--  ================================= Entetes info ============================= -->
  <articleinfo>
    <date>Février 2008</date>
    <author>
      <firstname>Ivan</firstname>
      <surname>Kurzweg</surname>  
      <email>ik-r@wanadoo.fr</email>
    </author>

    <title>Scripting with Php</title>

    <copyright>
      
      <year>2008</year>
      <holder>Ivan KURZWEG, <emphasis>ik-r@wanadoo.fr</emphasis></holder>
    </copyright>

    <legalnotice>
      <para>Permission to use, copy, modify, and distribute this documentation for any purpose with or without fee is here by granted, provided that the above copyright notice and this permission notice appear in all copies.
</para>        
    </legalnotice>

    <keywordset>
      <keyword>Programmation, php, ligne de commande, mode interactif, commande, ligne </keyword>
    </keywordset>

  </articleinfo>
  
  <abstract> 
    <para>Ce document présente une introduction à la programmation PHP, mais en se focalisant sur un usage interactif plus que sur une vision orientée "Web" du développement en PHP. Les exemples de ce cours sont données sous Linux, mais devraient pouvoir, sans trop de soucis, être adaptés à un environnement Windows. </para>
  </abstract>








<!--  ================================= Chapitre 1 ============================= -->
  <sect1>
    <title>Notions de bases</title>





    <sect2>
      <title>Présentation de Php</title> 
      <para><acronym>Php</acronym> pour <foreignphrase>PHP:Hypertext Preprocessor</foreignphrase> est un langage de script, écrit en PERL, spécialement conçu pour permettre la création de pages Web dynamiques. Néanmoins, Php permet de s'initier à la programmation fonctionnelle, et nous nous intéresserons dans ce cours plus particulièrement à son utilisation en ligne de commande.
</para>
      <para>
Php fait donc partie de la famille des langages de programmation <emphasis>interprété</emphasis>, contrairement à d'autres langages dits <emphasis>compilés</emphasis> (ADA, C, C++,...). La différence de ces deux grandes familles est la manière dont le compilateur traduit une fois pour toute le code source en un<emphasis> fichier indépendant exécutable</emphasis> (donc utilisant du code machine ou du code d'assemblage), alors que l'interpréteur est nécessaire <emphasis>à chaque lancement</emphasis> du programme interprété, pour traduire au fur et à mesure le code source en code machine. Cette traduction à la volée a pour conséquence la relative lenteur des programmes interprétés par rapport aux programmes compilés, malgré les progrés des processeurs et des interpréteurs. Néanmois, la facilité d'évolution d'un programme interprété et la rapidité de mise en place de petits programmes (généralement destinés au Web) pèsent dans la balance en faveur des langages interprétés. </para>
<para>
Il est à noter qu'une troisième famille de langage peut-être placé entre les deux précédentes, il s'agit des langages permettant une première compilation en langage intermédiaire, l'exécution se faisant au sein d'une machine virtuelle sur le système cible. L'exemple le plus connu est ainsi <trademark>JAVA</trademark>. 

 </para>

    </sect2>




    <sect2>
      <title>L'interpréteur PHP</title>
      <para>Sous Linux, l'interpréteur PHP est installé via le paquet <filename>PHP-CLI</filename>. Une fois ce paquet installé, la commande <command>php</command> est disponible. Sa localisation dans le filesystem peut s'obtenir grâce à la commande : 
 <programlisting width="100"><![CDATA[
ikare@ix:~$ which php
/usr/bin/php
]]>
</programlisting> 
L'appel de l'interpréteur Php va permettre bien sûr d'exécuter un script Php, mais la commande dispose de nombreuses options : 
<programlisting width="100"><![CDATA[
ikare@ix:~$ /usr/bin/php -h
Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
  -c <path>|<file> Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse and execute <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin

  --ini            Show configuration file names

  --rf <name>      Show information about function <name>.
  --rc <name>      Show information about class <name>.
  --re <name>      Show information about extension <name>.
  --ri <name>      Show configuration for extension <name>.
]]>
</programlisting>
</para>
</sect2>





    <sect2>
      <title>Instructions, expressions, commentaires, ...</title>
      <para>Un programme / script PHP est une suite d'instructions exécutées séquentiellement par l'interpréteur. Chaque instruction est séparé de la suivante par un <emphasis>point virgule</emphasis>. Une instruction peut-être considérée comme du code PHP dont l'exécution va modifier l'état de la machine.</para>
<para>
Certaines instructions peuvent contenir des <emphasis>expressions</emphasis>. Les instructions sont exécutés, les expressions sont évaluées. </para>
<para>
Les instructions peuvent être regroupées dans des <emphasis>blocs</emphasis>, délimités par <filename>{ }</filename>. Un bloc garanti que toutes les instructions sont exécutées de manière séquentielles de la première à la dernière.</para>
<para>Le langage PHP est dit sensible à la casse (il fait la différence entre les majuscules et les minuscules) pour les variables, objets ou fonctions définies par le programmeur. A l'inverse, il n'est pas sensible à la casse pour l'ensemble des mots-clefs et des primitives du langage.</para>
      <para>les commentaires ne sont pas pris en compte par l'interpréteur, mais il convient de prendre la bonne habitude de commenter les codes que vous produisez. Les caractères encadrant des commentaires sur plusieurs lignes sont <command>/*   */</command> ou <command>//</command> permettant de commenter le reste d'une seule ligne. </para>
<para>Enfin, la présence ou non de retours chariots, tabulations ou espaces n'a pas d'influence sur le comportement du programme. </para>
    </sect2>






<sect2>
      <title>Le fameux hello world</title>
      <para>
Commençons donc par l'indémodable "bonjour au monde", programme classique. Voici le code source du programme :

<example>
  <title>Hello world </title>
 <programlisting>
<![CDATA[
#!/usr/bin/php 
<?
   echo "Hello World \n";
?>
]]>
 </programlisting>
</example>
L'exécution du programme se fait soit par l'appel de la commande php en passant le nom du fichier en paramètre, soit sous Linux en modifiant les droits du fichier  : 
 <programlisting width="100"><![CDATA[
ikare@ix $ ls
hello.php
ikare@ix $ php hello.php 
Hello World 
ikare@ix $ chmod u+x hello.php 
ikare@ix $ ./hello.php 
Hello World 
]]>
</programlisting>
Le changement de permission sur le fichier (<command>chmod</command>) permet de rendre le script exécutable via le lancement de l'interpréteur indiqué dans la première ligne du fichier source (<foreignphrase>shebang</foreignphrase>).
</para>
</sect2>




    <sect2>
      <title>Types de données</title>
   <para>Php utilise les types de données scalaires classiques : 
<itemizedlist>
	  <listitem>
	    <para><emphasis>Entiers :</emphasis> la plage des nommbres entiers disponibles dépend de la plate forme d'exécution, mais est généralement comprise entre -2 147 483 648 et +2 147 483 647. Les entiers peuvent être représentés sous leur forme décimale, octale (commençant par un 0) ou hexadécimale (commençant par 0x), précédée de leur signe : 
<programlisting><![CDATA[
//des entiers décimaux
1998
-641
+33

//des entiers octaux
0755 // valeur decimale 493
+010 // valeur decimale 8

//des entiers héxadécimaux
0xFF    // valeur decimale 255
0x10    //  valeur decimale  16
-0xDAD1 //  valeur decimale -56017
]]>
</programlisting>

</para></listitem> 
	  <listitem>
	    <para><emphasis>Nombres à virgule flottante :</emphasis> Comme les entiers, les nombres à virgule prennent leur valeur sur une plage fonction de la plate forme cible. Usuellement, de 1.7E-3308 à 1.7E+308, avec une précision de 15 chiffres après la virgule. Il est à noter que Php comprends les notations scientifiques : 
<programlisting><![CDATA[
3.14
0.017
-7.1
0.314E1      // 0.314*101, soit 3.14
17.0E-3      // 17.0*10-3, soit 0.017


]]>
</programlisting>
Attention, la représentation des nombres à virgule flottante est souvent une approximation sur de nombrex systèmes. Par exemple, 3.1 est parfois représenté par la valeur 3.09999999999999. Dans ce cas, la comparaison de deux nombres réels peut poser certains soucis, et il est souvent nécessaire de passer par une conversion en entier pour vérifier une égalité à X décimales prêt. 
</para></listitem>
	  <listitem>
	    <para><emphasis>Chaînes de caractères :</emphasis> elles sont délimités soient par des apostrophes, soit par des guillemets. Dans le premier cas, les variables inclues dans la chaîne de caractères ne sont pas résolues, dans le second, elles sont remplacées par leur valeur (cf paragraphe sur les variables). Il est à noter un certain nombre  de caractères d'échappement : 
<programlisting><![CDATA[
\"     //le CARACTERE guillemets
\n     //saut de ligne
\t     //tabulation
\\     //CARACTERE Antislash
]]>
</programlisting>
</para></listitem>
	  <listitem>
	    <para><emphasis>Booléens : </emphasis> les booléens prennent les valeurs vrai ou faux. Par défaut, toutes les valeurs sont VRAI, sauf : le mot clef <command>FALSE</command>, l'entier 0, le réel 0.0, la chaîne vide "", un tableau avec aucun élément, ou la valeur <command>NULL</command>.
</para></listitem>
	  <listitem>
	    <para><emphasis>Arrays : </emphasis> Les tableaux multidimentsions sont gérés sous Php. Un paragraphe leur est consacré. il permettent de stocker des valeurs multiples dans une même variable.</para></listitem>
</itemizedlist>
</para>
</sect2>


    <sect2>
      <title>Variables</title>
   <para>
Une variable est un espace mémoire utilisé pour stocker une information. Elle est définie par un nom. On peut affecter une valeur à une variable, et utiliser cette valeur plus tard dans le programme. Un exemple d'utilisation des variables peut être de stocker les données entrées par un utilisateur, ou encore des résultats intermédiaires lors de traitements. 
    </para>
      <para>
Si les noms des variables sont au choix du programmeur, il est important de noter quelques règles de nommages :
<itemizedlist>
	  <listitem>
	    <para>les noms de variables commencent par un $</para></listitem>
	  <listitem>
	    <para>les noms de variables sont de longueur quelconque</para></listitem>
	  <listitem>
	    <para>les noms de variables peuvent contenir des chiffres, des lettres et le signe underscore</para></listitem>
	  <listitem>
	    <para>les noms des variables sont sensibles à la casse.</para></listitem></itemizedlist></para>

      <para>Contrairement à beaucoup d'autres langages, la déclaration des variables ne se fait pas en PHP. Cette déclaration est implicite au moment de la première affectation. <emphasis>L'affectation</emphasis> est l'instruction qui permet de stocker une valeur dans une variable, elle est définie par le signe <command>=</command>.</para>
<para>C'est donc la première affectation qui détermine le type de la variable. Le type d'une variable représente le type de données qu'elle va pouvoir contenir : numérique, caractère, tableau, ...</para>


<example><title>Affectations et variables</title>
<programlisting>
<![CDATA[
<p>Hello World!
<? $age = 33; 
   $nom = "Ivan"; ?>
<br />Hello <? echo $nom; ?>
<br />Tu as <? echo $age; ?> ans
</p>
]]>
</programlisting>
</example> 


      <note><para>Il est possible de supprimer une variable (et pas seulement sa valeur) en utilsant la fonction <command>unset($var)</command>.</para></note>

      <para>Le type d'une variable peut automatiquement évoluer dans le temps, en fonction des diverses affectations. Une variable de type entier peut donc devenir une variable de type texte.On appelle ce changement de type en cours d'exécution le <emphasis>transtypage</emphasis>. Dans certains calculs, Php tentera également de changer le type de certaines variables de manière à pouvoir évaluer certaines expressions : par exemple, la concaténation d'une chaine et d'un entier provoquera le transtypage de l'entier vers une chaîne, puis la concaténation des deux chaînes. Par contre, l'addition d'une chaîne de caractère et d'un entier ne fonctionne pas (aucune erreur n'est renvoyé, mais seul l'entier est pris en compte dans le calcul).


</para>

</sect2>

<sect2><title>Opérateurs</title>
<para>Nous avons vu comment déclarer des variables et leur affecter des valeurs. Voyons maintenant comment manipuler ces valeurs :</para>
<sect3><title>Opérateurs arithmétiques</title>
<para>
              <table>
                  <title>Opérateurs arithmétiques</title>

                  <tgroup cols="2">
       <colspec colwidth="*" colnum="1" colname="op"/>
        <colspec colwidth="3*"   colnum="2" colname="desc"/>
                    <thead>
                      <row>
                        <entry><emphasis role="bold" >Opérateur</emphasis></entry>
                        <entry><emphasis role="bold">Description</emphasis></entry>
                      </row>
		    </thead>
		    <tbody>
                      <row>
                        <entry>+</entry>
                        <entry>Addition</entry>
                      </row>
                      <row>
                        <entry>-</entry>
                        <entry>Soustraction</entry>
                      </row>
                      <row>
                        <entry>*</entry>
                        <entry>Multiplication</entry>
                      </row>
                      <row>
                        <entry>/</entry>
                        <entry>Division</entry>
                      </row>
                      <row>
                        <entry>%</entry>
                        <entry>Modulo (reste de la division entière)</entry>
                      </row>
                    </tbody>
                  </tgroup>
                </table>
</para>
</sect3>
<sect3><title>Opérateurs de comparaison</title>
<para>Les opérateurs de comparaison permettent d'obtenir une valeur booléenne VRAI ou FAUX selon le résultat de l'expression : 
              <table pgwide="0" >
                  <title>Opérateurs de comparaison</title>

                  <tgroup cols="2">
       <colspec colwidth="*" colnum="1" colname="op"/>
        <colspec colwidth="3*"   colnum="2" colname="desc"/>
                    <thead>
                      <row>
                        <entry><emphasis role="bold" >Opérateur</emphasis></entry>
                        <entry><emphasis role="bold">Description</emphasis></entry>
                      </row>
		    </thead>
		    <tbody>
                      <row>
                        <entry>==</entry>
                        <entry>Egalité</entry>
                      </row>
                      <row>
                        <entry>&gt;</entry>
                        <entry>Strictement supérieur</entry>
                      </row>
                      <row>
                        <entry>&gt;=</entry>
                        <entry>Supérieur ou égal</entry>
                      </row>
                      <row>
                        <entry>&lt;</entry>
                        <entry>Strictement inférieur</entry>
                      </row>
                      <row>
                        <entry>&lt;=</entry>
                        <entry>Inérieur ou égale</entry>
                      </row>
                      <row>
                        <entry>!=</entry>
                        <entry>Non égalité</entry>
                      </row>                      <row>
                        <entry>&lt;&gt;</entry>
                        <entry>Non égalité</entry>
                      </row>
                    </tbody>
                  </tgroup>
                </table>
</para>
</sect3>
<sect3><title>Opérateurs logiques</title>
<para>Les opérateurs logiques permettent par exemple de combiner les résultats de comparaisons. Il renvoient la valeur booléenne VRAI ou FAUX.
              <table>
                  <title>Opérateurs logiques</title>

                  <tgroup cols="2">
       <colspec colwidth="*" colnum="1" colname="op"/>
        <colspec colwidth="3*"   colnum="2" colname="desc"/>
                    <thead>
                      <row>
                        <entry><emphasis role="bold" >Opérateur</emphasis></entry>
                        <entry><emphasis role="bold">Vrai quand ...</emphasis></entry>
                      </row>
		    </thead>
		    <tbody>
                      <row>
                        <entry>OR</entry>
                        <entry>une des deux opérandes est VRAI</entry>
                      </row>
                      <row>
                        <entry>AND</entry>
                        <entry>les deux opérandes sont VRAI</entry>
                      </row>
                      <row>
                        <entry>XOR</entry>
                        <entry>Uniquement lorsqu'un opérande est VRAI, pas les deux</entry>
                      </row>
                    </tbody>
                  </tgroup>
                </table>
</para>
</sect3>
<sect3><title>Opérateurs de transtypage</title>
<para>Bien que Php puisse être considéré comme un langage peu typé, il est possible de forcer le type des variables en utilisant les opérateurs de transtypage : 
 <table>
                  <title>Opérateurs logiques</title>

                  <tgroup cols="2">
       <colspec colwidth="*" colnum="1" colname="op"/>
        <colspec colwidth="3*"   colnum="2" colname="desc"/>
                    <thead>
                      <row>
                        <entry><emphasis role="bold" >Opérateur</emphasis></entry>
                        <entry><emphasis role="bold">Change le type vers : </emphasis></entry>
                      </row>
		    </thead>
		    <tbody>
                      <row>
                        <entry>(int)</entry>
                        <entry>entier</entry>
                      </row>
                      <row>
                        <entry>(float)</entry>
                        <entry>Réel</entry>
                      </row>
                      <row>
                        <entry>(string)</entry>
                        <entry>Chaîne de caractère</entry>
                      </row>                      <row>
                        <entry>(bool)</entry>
                        <entry>booléen</entry>
                      </row>
                      <row>
                        <entry>(array)</entry>
                        <entry>Tableau</entry>
                      </row>
                    </tbody>
                  </tgroup>
                </table>
<informalexample>
<programlisting><![CDATA[
Exemple : 
$a = "5"      //$a est de type chaîne
$a = (int) $a; //$a devient de type entier

]]></programlisting></informalexample>
</para>
</sect3>

</sect2>


<sect2>

      <title>Tableaux</title>
      <para>
Les tableaux sont des structures de données permettant de stocker plusieurs valeurs dans une même variable. Très utilisés en PHP, on dispose de tableaux à une ou plusieurs dimensions.</para>
<sect3>
	<title>Tableau à une dimension</title>
	<para>Un tableau à une dimension permet donc de stocker plusieurs valeurs<emphasis> de même type</emphasis> dans une même variable. L'accès à chaque cellule du tableau se fait en utilisant un indice : une entier commençant à 0 ou une chaîne de caractère identifiant la cellule.</para>
<para>
<informalexample>
<programlisting><![CDATA[
Exemple : 
$prof[0] = "Kurzweg";
$prof[1] = "Picard";
$prof[2] = "Gouraud";
$prenoms_enseignant['Kurzweg'] = "Ivan";
$prenoms_enseignant['Picard'] = "Pascal";
$prenoms_enseignant['Gouraud'] = "Gilles";
]]></programlisting></informalexample>
</para>
	<para>Il est possible de déclarer et d'affecter des valeurs à un tableau en utilisant le constructeur<command> array()</command>. </para>
<para>
<informalexample>
<programlisting><![CDATA[
Exemple : 
$prof = array("Kurzweg", "Picard", "Gouraud");
$prenoms_enseignant = array('kurzweg' => "Ivan",
     'Picard' => "Pascal",
     'Gouraud' => "Gilles");
]]></programlisting></informalexample>
</para>
</sect3>
<sect3>
	<title>Tableau à plusieurs dimension</title>
	<para>Les tableaux à plusieurs dimensions permettent de stocker plusieurs valeurs dans chaque cellule du tableau. Il faut néanmoins respecter l'ordre et le type de chaque valeur.</para>
<para>
<informalexample>
<programlisting><![CDATA[
Exemple : 
$prof[0][0] = "Kurzweg";
$prof[1][0] = "Ivan";
$prof[2][0] = "Picard";
$prof[0][1] = "Pascal";
$prof[1][1] = "Gouraud";
$prof[2][1] = "Gilles";
]]></programlisting></informalexample>
</para>
</sect3>
  
    <sect3>
	<title>Fonctions sur les tableaux</title>
	<para>Il existe un certain nombre de fonctions prédéfinies en Php, dont voici une liste non exhaustive :</para>
<table>
                  <title>Fonctions concernant les tableaux</title>

                  <tgroup cols="3">
        <colspec colnum="1" colname="fonc" colwidth="*"/>
        <colspec colnum="2" colname="desc" colwidth="2*"/>
        <colspec colnum="3" colname="ex" colwidth="3*"/>
                    <thead>
                      <row>
                        <entry><emphasis role="bold">Fonctions</emphasis></entry>
                        <entry><emphasis role="bold">Commentaires</emphasis></entry>
                        <entry><emphasis role="bold">Exemple</emphasis></entry>
                      </row>
		    </thead>
		   <tbody>
                
<!-- ======================= TO DO : ERREUR DBLATEX !!!!!!!!!!!!!!!!!!!-->


  <row>
		    <entry><command><computeroutput><![CDATA[count($var) ]]></computeroutput></command></entry>
                        <entry>compte le nombre d'éléments affectés</entry>
		<entry><computeroutput><programlisting>
<![CDATA[$dept = array ("974","972");
$nb = count($dept); 
 ]]></programlisting></computeroutput></entry>
                      </row> 
                                <row>
		        <entry><command><![CDATA[sort($var) ]]></command></entry>
                        <entry>trie les éléments selon un ordre numérique ou alphabétique et réaffecte les indices du tableau
</entry>
		        <entry><programlisting><![CDATA[$dept=array ("des","dpa","dbe");
sort($dept);
while (list($indice, $val)
=each($dept) )
{ echo ("$indice - $val");
    // "0 - dbe" puis "1 - des"
    // puis "2 - dpa"
}
 ]]></programlisting></entry>
                      </row>
                      <row>
		        <entry><command><![CDATA[asort($var) ]]></command></entry>
                        <entry>trie les éléments mais ne réaffecte pas les indices
</entry>
		        <entry><programlisting><![CDATA[$dept=array ("des","dpa","dbe");
asort($dept);
    // "2 - dbe" puis "0 - des"
    // puis "1 - dpa"
 ]]>
</programlisting></entry>
                      </row>



<!-- -->
	            </tbody>
	          </tgroup>
</table> 
</sect3>

    <sect3>
	<title>Parcours d'un tableau</title>
	<para>Le parcours d'un tableau consiste à récupérer les valeurs stockées afin de les traiter (les afficher par exemple. Il existe de nombreuses manières de parcourir un tableau, mais une des plus courante est l'utilisation de la <emphasis>boucle</emphasis> <command>foreach</command> :  </para>
<para>
<informalexample>
<programlisting><![CDATA[
Exemple : 
#!/usr/bin/php
<?
$prof = array("Kurzweg", "Picard", "Gouraud");
foreach  ($prof as $nom)
{
        echo $nom,"\n";
}
?>

]]></programlisting></informalexample>

<informalexample>
<programlisting><![CDATA[
Exemple : 
#!/usr/bin/php
<?
$enseignant = array('kurzweg' => "Ivan",
     'Picard' => "Pascal",
     'Gouraud' => "Gilles");

foreach  ($enseignant as $nom => $prenom)
{
        echo $nom,"\t",$prenom,"\n";
}
?>

]]></programlisting></informalexample>

</para>

</sect3>
    </sect2>  

    <sect2>
      <title>Garbage collector</title>
      <para>Php utilise deux mécanismes de gestion de la mémoire : <emphasis>copy-on-write</emphasis> et <emphasis>reference counting</emphasis> :
<itemizedlist>
	  <listitem>
	    <para><foreignphrase>copy-on-write</foreignphrase> : lors d'affectation de variable à variable, Php retard la copie de la veleur échangée jusqu'au moment où un modification intervient sur une des variable. Ainsi, seule la référence de la variable est modifiée. On économise ainsi mémoire et et temps dans de nombreuses situation. 
<informalexample>
<programlisting><![CDATA[
Exemple : 
#!/usr/bin/php
<?
$enseignant = array("kurzweg","Ivan","33");

$prof = $enseignant; //on ne copie pas les valeurs du tableau, mais Php met
                     //juste à jour la table des symboles, indiquant que pour
                     //le moment, $prof et $ens pointent sur les mêmes zones mémoires

$prof[2] = "34";     //les valeurs sont modifiées, la variable $prof est écrite en mémoire 
?>

]]></programlisting></informalexample>
 </para>
	  </listitem>
	  <listitem>
	    <para><foreignphrase>reference counting</foreignphrase> : Php maintient à jour le nombre de références pointant sur les zones mémoires, c'est-à-dire le nombre de moyen d'aboutir à chaque valeur utilisée dans le programme. Dès que ce nombre atteint 0, la zone mémoire est libérée. Dans l'exemple précédent, l'entrée de la table des symboles est référencée 1 fois à la création du tableau <varname>$enseignant</varname>, puis référencé 2 fois à l'affectation <varname>$prof = $enseignant</varname>, puis référencé de nouveau 1 seule fois lors de l'écritre des valeurs de <varname>$prof</varname></para>
	  </listitem>
	</itemizedlist>
</para>
    </sect2>

    <sect2>
      <title>Scripts interactifs</title>
      <para>Dans ce cours, nous allons utiliser Php comme langage de scripts systèmes. Pour les besoins des exercices et des exemples, nous aurons besoin de saisir des données entrées par l'utilisateur. Pour efectuer c'est saisie, nous utiliserons des fonctions de Php, permettant de lire dans un fichier (et sous Unix, tout est fichier ... le clavier peut donc être lu comme un fichier !). L'exemple suivant permet de lire un entier, puis une chaîne de caractère. Nous reviendrons dans le chapitre consacré aux fichiers sur ces fonctions ...
<informalexample>
<programlisting><![CDATA[
Exemple :#!/usr/bin/php
<?
echo "\n Entrez votre nom : \t";

//lecture de la chaine de caractères
$nom = trim((string)fgets(STDIN)); //on supprime les espaces et le caractère newline

echo "\n Entrez votre age : \t";

//lecture de l'entier :
$age = (int)fgets(STDIN);

//message d'accueil :
echo "\nBonjour $nom, vous avez $age ans\n";

?>
ikare@ix $ ./saisie.php 

 Entrez votre nom :     Ivan

 Entrez votre age :     34

Bonjour Ivan, vous avez 34 ans

]]></programlisting></informalexample>


  </para>
    </sect2>

    <sect2>
      <title>Exercices d'applications</title>
      <sect3><title>Analyse de code</title>
   <para>Interprétez et corrigez si nécessaires les extraits de code suivants : 

<orderedlist>
	  <listitem>
<programlisting><![CDATA[$string = 'c'est surement un probleme de guillemets';
echo $string]]></programlisting></listitem>
	  <listitem><programlisting><![CDATA[$age = 12;
$result1 = "$age";
$result2 = "$age';
echo $result1;
echo "<br />";
echo $result2;]]></programlisting></listitem>
	  <listitem><programlisting><![CDATA[$nb = 10;
$ch1 = "Il y a '$nb' personnes connectées";
$ch2 = `Il y a "$nb" personnes connectées. ';
echo $ch1,"<br />\n";
echo $ch2;]]></programlisting></listitem>
	  <listitem><programlisting><![CDATA[$string1 = `Hello';
$string2 = `World!';
$stringall = $string1.$string2;
echo $stringall;]]></programlisting></listitem>


	  <listitem><programlisting><![CDATA[$nix = "BSD";
echo "Free$nix, Open$nix, PC$nix sont tous des Unix-like libres ...";]]></programlisting></listitem>

	  <listitem><programlisting><![CDATA[$number = 2;
$string = "Hello";
$combined = $number + $string;
$combined2 = $number.$string;
echo $combined;
echo <br />;
echo $combined2;]]></programlisting></listitem>
	  <listitem>
<programlisting><![CDATA[
$cpt=4;
$cpt+=2;
$cpt-=3;
$cpt*=2;
$cpt/=3;
echo $cpt;]]></programlisting></listitem></orderedlist>

 </para></sect3>
      <sect3><title>Instructions simples</title>
<orderedlist>
	  <listitem>
<para>Ecrivez le code permettant d'inverser le contenu de deux variables $x et $y. (au départ, $x contient 2 et $y contient 4, et c'est l'inverse en fn de programme). Le programme devra afficher le contenu des variables avant et après le traitement.</para>
 </listitem> 
	  <listitem>
	    <para>La surface et la circonférence d'un cercle de 2cm de rayon (PI et le rayon devront être stockés dans des variables)</para>
	  </listitem>
	  <listitem>
	    <para>Le résultat de l'évaluation de l'expression <command>((VRAI et FAUX) OU VRAI) ET FAUX</command></para>
	  </listitem> 
	  <listitem>
	    <para>Le résultat de l'évaluation de l'expression <command>((VRAI et FAUX) OU (VRAI ET FAUX))</command></para>
	  </listitem> 
	  <listitem>
	    <para>La phrase <computeroutput>la date actuelle est :date et il est : heure</computeroutput></para>
	  </listitem> 

	</orderedlist>

</sect3>
    
    </sect2>

  </sect1>






<!--  ================================= Chapitre 2 ============================= -->
<sect1>
    <title>Structures de contrôles</title>

    <sect2>
      <title>Conditionnelles</title>
      <sect3><title><command>if</command></title>
      <para>





Les structures conditionnelles permettent de n'exécuter un bloc d'instructions que si une condition est réalisée. Le synopsys de la conditionnelle est le suivant : 
<informalexample>
<programlisting><computeroutput>
if ( condition1 ...<co id="id1" /> )
{
  <replaceable> Bloc d'instructions 1..</replaceable><co id="id2" />
}
elseif ( condition2 ... ) <co id="id3" />
   {
      <replaceable>Bloc d'instructions 2..</replaceable><co id="id4" />
   }
   else<co id="id5" />
   {
   <replaceable>Bloc d'instructions 3..</replaceable>
   }
<co id="id6" />
</computeroutput></programlisting>
<calloutlist>
   <callout arearefs="id1">
      <para>
      Une <emphasis>expression</emphasis> dont l'évaluation donne VRAI ou FAUX
      </para>
   </callout>
   <callout arearefs="id2">
      <para>
      Si la condition 1 est vrai alors tout le bloc 2 est exécuté et  le programme va en 6
      </para>
   </callout>
   <callout arearefs="id3">
      <para>
      Si la condition 1 est FAUX alors  la valeur de la condition 3 est testée
      </para>
   </callout>
   <callout arearefs="id4">
      <para>
      Si la condition 2 est VRAI alors  le bloc 4  est exécuté et  le programme va en 6
      </para>
   </callout>
   <callout arearefs="id5">
      <para>
      Si la condition 2 est FAUSSE alors le bloc 5  est exécuté et  le programme va en 6
      </para>
   </callout>   <callout arearefs="id6">
      <para>
      Fin de la conditionnelle
      </para>
   </callout>
</calloutlist></informalexample>
     </para>
<para>Voici un exemple d'enchaînement de conditionnelles : 
<example>
<title>Emboitements de condition</title>
<programlisting>
<![CDATA[
if ($country == "Germany" )
{
   $version = "German";
   $message = " Sie sehen unseren Katalog auf Deutsch";
}
elseif ($country == "France" )
  {
     $version = "French";
     $message = " Vous verrez notre catalogue en francais";
   }
   elseif ($country == "Italy" )
      {
         $version = "Italian";
         $message = " Vedrete il nostro catalogo in Italiano";
      }
      else
      {
         $version = "English";
         $message = "You will see our catalog in English";
      }
echo "$message<br>";

]]>
</programlisting>
</example></para>
</sect3>
      <sect3><title>Le <command>Switch</command></title>
	<para>Nous avons vu dans l'exemple précédent la nécessité de renoter plusieurs fois le même test d'égalité. Dans le cas de multiples tests de la valeur d'une variable, l'écriture peut devenir vite fastidieuse. C'est là qu'intervient le <command>switch</command> : 
<informalexample>
<programlisting>switch ( $variable )
{
  case value :
     bloc d'instructions
     break;
  case value :
     bloc d'instructions
     break;
  ...
  default:
     bloc d'instructions
     break;
}
</programlisting></informalexample>
Il faut bien noter ici que l'on ne peut tester que la valeur d'une seule variable !</para>
<para>Un exemple d'utilisation du switch : 

<example>
<title>Selon ...</title>
<programlisting>
<![CDATA[

switch ( $dept )
{
  case 974 :
     $dept_nom = "Réunion";
     break;
  case 972 : 
     $dept_nom = "Guyane";
  default:
     $dept_nom = "France métropolitaine";
     break;
}

]]>
</programlisting>
</example></para>

</sect3>
    </sect2>
   <sect2>
      <title>Répétitives</title>
      <para>
Les structure répétitives (itératives) permettent de répeter un certain nombre de fois un bloc d'instructions. Nous en étudierons deux, la boucle <command>for</command> et la boucle <command>while</command></para>
<sect3>
	<title>La boucle <command>for</command></title>
	<para>L'instruction <command>for</command> permet de répeter un bloc d'instructions pour un nombre de fois défini. Elle doit définir la variable qui sera modifiée à chaque itération, sa valeur de départ, la valeur de fin de boucle, et l'opération à effectuer à chaque itération :
</para><para>

<example>
<title>Affichage des nombres inférieurs à 100</title>
	    <informalexample>
<programlisting><computeroutput>
<![CDATA[
<? 
for ($cpt=1;$cpt<100;$cpt++)
{
	echo "$cpt<br />";
}
?>
]]>
</computeroutput></programlisting></informalexample>
</example>

<example>
<title>Calcul de la somme des nombres pairs inférieurs à 100</title>
<programlisting><computeroutput>
<![CDATA[
<? 
$som=0;
$nb=100;
for ($cpt=1;$cpt<$nb+1;$cpt+=2)
{	
	$som=$som+$nb;
}
echo "La somme des $nb premiers entiers est de $som";
?>
]]>
</computeroutput></programlisting>
</example>


 </para>
</sect3>
<sect3>
	<title>La boucle <command>while</command></title>
	<para>L'instruction <command>while</command> permet de répeter un bloc d'instructions tant qu'une condition n'est pas remplie. Elle suit le synopsys suivant :
<informalexample>
<programlisting><computeroutput>
while (condition<co id="id31" />)
{
    bloc d'instructions ... ;
}
</computeroutput></programlisting>
<calloutlist>
   <callout arearefs="id31">
      <para>
       tant que cette condition est VRAI, on exécute le bloc et on réévalue la condition. 
      </para>
   </callout>
</calloutlist></informalexample></para>
<para>Bien sûr, il est à la charge du programmeur de bien s'assurer que la condition d'exécution de la boucle est modifiée et passe à un moment à FAUX .. sinon, on est dans le cas d'une boucle infinie.</para>
<example>
<title>Affichage des nombres inférieurs à 100</title>
<programlisting><computeroutput>
<![CDATA[
<? 
$cpt=1;
//on affiche tous les nombres jusque 99
while ($cpt<100)
{
	echo "$cpt<br />"; 
	$cpt++;
}
?>
]]>
</computeroutput></programlisting>
</example>
<example>
<title>Une boucle infinie !!</title>
<programlisting><computeroutput>
<![CDATA[
<? 
$cpt=1;
while ($cpt<100)
{
	echo "$cpt<br />";
	//$cpt++; on commente la ligne, la valeur de $pt ne changera plus, 
        //la boucle ne sarrêtera pas
}
?>
]]>
</computeroutput></programlisting>
</example>
</sect3>
<sect3>
	<title>La boucle <command>do ... while</command></title>
	<para>La boucle  <command>do { }while</command> est similaire à la première, à la différence que la condition d'arrêt est examinée à la fin de la boucle et non plus au début : <informalexample>
<programlisting><computeroutput>
do
{
    bloc d'instructions ... ;
}
while (condition<co id="id32" />)

</computeroutput></programlisting>
<calloutlist>
   <callout arearefs="id32">
      <para>
       si cette condition est VRAI, on ré-exécute le bloc et on réévalue la condition.
      </para>
   </callout>
</calloutlist></informalexample></para>
<para>Bien sûr, il est à la charge du programmeur de bien s'assurer que la condition d'exécution de la boucle est modifiée et passe à un moment à FAUX .. sinon, on est dans le cas d'une boucle infinie.</para>
<example>
<title>Affichage des nombres inférieurs OU EGAUX à 100</title>
<programlisting><computeroutput>
<![CDATA[
<? 
$cpt=1;
//on affichera les nombres, 100 y compris 
do
{
	echo "$cpt<br />";
	$cpt++;
}
while ($cpt<100) 
?>
]]>
</computeroutput></programlisting>
</example>

</sect3>

<sect3>
	<title>La boucle <command>foreach</command></title>
	<para>La boucle  <command>foreach</command>, abordée dans le premier chapitre, permet de parcourir un tableau <informalexample>
<programlisting><computeroutput>
foreach ($tableau as $cellule<co id="id33" />) 
{
    bloc d'instructions ... ;
}


</computeroutput></programlisting>
<calloutlist>
   <callout arearefs="id33">
      <para>
        <varname>$cellule</varname> prendra successivement les valeurs de chaque cellule du tableau.
      </para>
   </callout>
</calloutlist></informalexample></para>

	<para>Pour parcourir le tableau en accédant à la fois à la clef et à la valeur, on utilise la syntaxe suivante : 
 <informalexample>
<programlisting><computeroutput>
foreach ($tableau as $clef => $cellule<co id="id35" />) 
{
    bloc d'instructions ... ;
}


</computeroutput></programlisting>
<calloutlist>
   <callout arearefs="id35">
      <para>
        <varname>$clef et $cellule</varname> contiennent respectivement les valeurs de la clef et de la cellule. 
      </para>
   </callout>
</calloutlist></informalexample></para>
<para>Bien sûr, il est à la charge du programmeur de bien s'assurer que la condition d'exécution de la boucle est modifiée et passe à un moment à FAUX .. sinon, on est dans le cas d'une boucle infinie.</para>
<example>
<title>Affichage des nombres inférieurs OU EGAUX à 100</title>
<programlisting><![CDATA[
Exemple : 
#!/usr/bin/php
<?
$prof = array("Kurzweg", "Picard", "Gouraud");
foreach  ($prof as $nom)
{
        echo $nom,"\n";
}

$enseignant = array('kurzweg' => "Ivan",
     'Picard' => "Pascal",
     'Gouraud' => "Gilles");

foreach  ($enseignant as $nom => $prenom)
{
        echo $nom,"\t",$prenom,"\n";
}
?>

]]></programlisting>
</example>
	<para>Une utilisation des tableaux à plusieurs dimensions est également fréquente. Dans ce cas, il peut être intéressant d'imbriquer les parcours de chaque dimensions :  
<informalexample>
<programlisting>
<![CDATA[
//tableau à deux dimesion : catégorie et produits
$prod['vetements']['T-shirt'] = 20.00;
$prod['vetement'][`pantalon'] = 22.50;
$prod['literie']['taie'] = 25.00;
$prod['literie']['drap'] = 50.00;
$prod['fourniture']['lampe'] = 44.00;
$prod['fourniture']['table'] = 75.00;

//récupération du prix d'un T-Shirt
$prix = $prod['vetements']['T-shirt'];

//affichage du prix d'un pantalon
echo $prod['vetement'][`pantalon'];

//affichage d'un texte 
echo "le prix d'une lampe est \${$prod['fourniture']['lampe']}";

echo "<table border=1>";
foreach( $prod as $categorie )
{
   foreach( $categorie as $produit => $prix )
   {
     $ch_prix = sprintf("%01.2f", $prix);
     echo "<tr><td>$produit:</td><td>\$$ch_prix</td></tr>";
   }
}
echo "</table>";]]>
</programlisting></informalexample>
</para>
</sect3>


    <sect3>
	<title>Sortie d'une boucle</title>
	<para>Même si les boucles devraient être écrites pour s'arrêter d'elles mêmes, il peut être intéressant de forcer la sortie, avec l'instruction <command>break</command>. <command>break</command> permet de sortir complètement de la boucle et de reprendre le cours du programme après le bloc d'instructions.
<informalexample>
<programlisting><computeroutput>
<![CDATA[
$cpt = 0;
while ( $cpt < 5 )
{
  $cpt++;
  If ( $cpt == 3 )
  {
      echo "break<br>";
      break;
  }
  echo "Fin de boucle: cpt=$cpt<br>";
}
echo "Sortie de boucle<p>";
]]>

</computeroutput></programlisting></informalexample></para>


</sect3>


    </sect2>   
    <sect2>
      <title>Exercices d'applications</title>
      <sect3><title>Conditionnelles</title>
	<orderedlist>
	  <listitem>
	<para>Ecire un script qui lit l'âge de l'utilisateur et affiche :
             1. Vous êtes un enfant (moins de 18 ans)
             2. Vous êtes un adultes
             3. ou Vous êtes du 3ème age (plus de 60 ans)
</para>
	  </listitem>
	  <listitem>
	<para>Ecrire un script qui lit deux entiers et dit si les deux entiers sont multiples ou non. Le programme doit être capable de détecter si le premier est multiple du second, ou le second du premier.</para></listitem>
	  <listitem>
	<para>Ecrire un script qui simule le fonctionnement d'un calculatrice : l'utilisateur entre un premier nombre, puis un signe ( + - / * ). Le programme donne le résultat.
</para></listitem> 
  <listitem>
	<para>Ecrire un script qui calcule un montant de facture : à partir d'un prix unitaire, du nombre de produits, du taux de TVA, le programme renvoie le montant total (avec une réduction de 10% si le montant dépasse 1000 euros.)</para></listitem>
 <listitem>
	<para>Ecrire un programme qui indique si une année est bissextile ou non. Une année est dite bissextile si elle divisible par 4, sauf si elle est divisible par 100, par contre celles divisibles par 400 sont bissextiles. </para></listitem>
</orderedlist>
</sect3>

 <sect3><title>Boucles</title>
	<orderedlist>
	  <listitem>
	    <para>Affectez une valeur à la variable <varname>nbre</varname> et afficher la somme des entiers de 1 à <varname>nbre</varname>. Donnez les versions du programme en utilisant l'instruction <command>FOR</command> puis avec l'instruction <command>WHILE</command>.
</para></listitem>
	  <listitem>
	    <para>Modifier le script précédent pour calculer la somme des entiers pairs uniquement. 
</para></listitem>
	  <listitem>
	    <para>Ecrire un script qui lit 10 réels, puis donne la somme des entiers, la moyenne, le nombre maximum entré, ainsi que le minimum. 
</para></listitem>
	  <listitem>
	    <para>Modifier le programme précédent pour qu'on saisisse un nombre indéfini de réels. La saisie se termine quand l'utilisateur entre -1. 
</para></listitem>
 <listitem>
	    <para>Afficher la table de multiplication de 10. 
</para></listitem>
 <listitem>
	    <para>Ecrire une script qui affiche un carré d'étoiles, dont la taille est entrée au clavier.  Par exemple, pour une taille de 4, le programme affichera :
<programlisting><computeroutput>
<![CDATA[
****
****
****
****
]]>

</computeroutput></programlisting>
</para></listitem> <listitem>
	    <para>Même exercice, mais cette fois ci avec un triangle, dont la nombre de lignes est entrée au clavier.  Par exemple, pour une taille de 4, le programme affichera :
<programlisting><computeroutput>
<![CDATA[
    *
  ****
 ******
********
]]>

</computeroutput></programlisting>
</para></listitem>
	  <listitem>
	    <para>Un nombre entier est dit premier s'il n'est divisible que par 1 et par lui même (1,2,3,5,7,11,13,17,19,....). Ecrire un script qui lit au clavier un nombre et indique si il est premier ou non. Vérifiez que votre programme marche correctement dans le cas d'une saisie d'un grand nombre pair (100 000 000 000) : la réponse doit être immédiate.
</para></listitem>
	  <listitem>
	    <para>Modifiez le script précédent pour qu'il affiche les nombres premiers inférieurs à 100 000.
</para></listitem>
	  <listitem>
	    <para>Un nombre entier est dit parfait si il est égal à la somme de ses diviseurs. Ecrire un script qui lit au clavier un nombre et indique si il est parfait ou non.
</para></listitem>
 <listitem>
	    <para>Modifiez le script précédent pour qu'il affiche les nombres parfaits inférieurs à 100 000.
</para></listitem>

</orderedlist>

</sect3>

 <sect3><title>Tableaux</title>
	<orderedlist>
	  <listitem>
	    <para>Ecrire un script initialise une liste de 10 élèves (noms et prénoms), les stocke dans un tableau, puis réaffiche la liste.
</para></listitem>
	  <listitem>
	    <para>Modifier le programme précédent pour qu'il lise un réel associé à chaque élève. En fin de saisie, le programme devra afficher la moyenne de la classe, puis le nom du meilleur élève.
</para></listitem>
 <listitem>
	    <para>Modifier le programme de manière à fournir le nombre d'élèves au dessus de 10, et le nombre d'élèves en dessous de la moyenne générale. 
</para></listitem>
	  <listitem>

	    <para>Sur la même base de tableau d'élève, écrivez le programme qui permet de vérifier si un élève est dans la classe. On saisira son nom au clavier, et en cas d'homonymie, on donnera la liste des élèves portant le même nom (par exemple, Olivier Grondin et Pierre Grondin).
</para></listitem>
	 
	  <listitem>Stocker dans un tableau les 10 premiers multiples d'un entier saisi au clavier. 
	    <para>
</para></listitem>

	  
</orderedlist>

</sect3>

      <sect3><title>Carré magique</title>

	<para>Un tableau de nombres entiers est dit <emphasis>magique</emphasis> quand la somme des cases de chaque colonne est égale à la somme des cases de chaque ligne, et à la somme des cases de chaque diagonale.</para>

<para>Vous devez écrire une page PHP qui affiche le tableau suivant, et qui prouve que le carré est magique. Vérfiez en changeant une des valeurs. Toutes les valeurs du carré doivent être stockées dans une seule variable.
 <table>
                  <title>Carré magique</title>

                  <tgroup cols="5">
		    <tbody>
                      <row>
                        <entry>17</entry>
                        <entry>24</entry>
                        <entry>1</entry>
                        <entry>8</entry>
                        <entry>15</entry>
                      </row>
                      <row>
                        <entry>23</entry>
                        <entry>5</entry>
                        <entry>7</entry>
                        <entry>14</entry>
                        <entry>16</entry>
                      </row>
                      <row>
                        <entry>4</entry>
                        <entry>6</entry>
                        <entry>13</entry>
                        <entry>20</entry>
                        <entry>22</entry>
                      </row>
                      <row>
                        <entry>10</entry>
                        <entry>12</entry>
                        <entry>19</entry>
                        <entry>21</entry>
                        <entry>3</entry>
                      </row>
                      <row>
                        <entry>11</entry>
                        <entry>18</entry>
                        <entry>25</entry>
                        <entry>2</entry>
                        <entry>9</entry>
                      </row>

                    </tbody>
                  </tgroup>
                </table>

</para> 

     </sect3>
    </sect2>

  </sect1>


 

<!--  ================================= Chapitre 3 ============================= -->
<sect1>
    <title>Fonctions</title>  
<abstract>
      <para>Une fonction est un bloc d'instructions nommé, pouvant accéder à des valeurs qui lui sont passées en arguments, les <emphasis>paramètres</emphasis> de la fonction. Permettant de réutiliser du code plusieurs fois dans un même programme, voire dans des programmes différents, elles sont essentielles dans la programmation

</para>
</abstract>
    <sect2>
      <title>Appel d'une fonction </title>
   <para>Qu'elles soient des fonctions prédéfinies (primitives du langage) ou définies par l'utilisateur, les fonctions sont appelées dans le code selon la même syntaxe : 
<informalexample>
<programlisting><computeroutput>
<![CDATA[
$var = nom_fonction(parametre1, parametre2, ...)
]]>
</computeroutput></programlisting></informalexample>
Le nombre de paramètres dépend de la définition de la fonction. Dans le cas de fonctions prédéfinies où incluses dans des modules externes, la documentation précise le nombre et le type des paramètres (voir <ulink url="http://www.php.net" >www.php.net)</ulink>. </para>
<para>Les exemples suivants illustrent des appels à des fonctions de Php :
<informalexample>
<programlisting><computeroutput>
<![CDATA[
// strlen( ) est une fonction qui retourne la taille d'une chaîne de caractères
$lg = strlen("PHP"); // $lg contient 3
// unlink permet d'effacer un fichier
$result = unlink("functions.txt") or die("Impossible !");

]]>
</computeroutput></programlisting></informalexample>
Dans le second exemple la fonction <function>unlink()</function> qui demande l'effacement d'un fichier retourne comme valeur <filename>FALSE</filename> si le traitement échoue. De nombreuses fonctions sont implémentées de cette manière en PHP. 
     </para>
    </sect2>

    <sect2>
      <title>Définition d'une fonction</title>
      <para>Une fonction est définie dans un script par la syntaxe suivante : 
<informalexample>
<programlisting><computeroutput>
<![CDATA[
function nom_fonction ( [ parametre [, ... ] ] )
{
  Instructions ...
}

]]>
</computeroutput></programlisting></informalexample>
Le nom de la fonction est soumis aux mêmes règles que le nom des variables, mais il est insensible à la casse. </para>
<para>
Toute fonction doit retourner une valeur. Ce renvoi est effectif à l'exécution de l'instruction <command>return</command>. Cette instruction a pour effet de terminer l'appel de la fonction, et de revenir au code d'où a été effectué cet appel. 
<example>
	  <title>Concaténation de chaînes</title>
	 <programlisting><computeroutput>
<![CDATA[

function concat($gauche, $droite) {
  $chaine = $gauche . $droite;
  return $chaine;
}

]]>
</computeroutput></programlisting> 
	</example>
Dans l'exemple précédent, la fonction concat accepte deux paramètres, effectue la concaténation des chaînes de caractères, stocke cette concaténation dans une variable, et renvoi la valeur de cette variable. Le passage par une variable intermédiaire est inutile : 
<example>
	  <title>Concaténation de chaînes améliorée</title>
	 <programlisting><computeroutput>
<![CDATA[

function concat($gauche, $droite) {
  return $gauche . $droite;
}

]]>
</computeroutput></programlisting> 
	</example>
Un exemple de script complet : 
<example>
	  <title>Concaténation de chaînes</title>
	 <programlisting><computeroutput>
<![CDATA[
<?php
 function concat($gauche, $droite) {
  return $gauche . $droite;
}
 $ch1 = "c'est une ";
 $ch2 = "phrase complète";
 echo concat($ch1, $ch2);
?>
]]>
</computeroutput></programlisting> 
	</example>
</para>
    </sect2>
    <sect2>
      <title>Portée des variables</title>
      <para>Jusque maintenant, sans les fonctions, nous avons toujours considéré qu'une variable pouvait être utilisée dans n'importe quelle instruction d'un script. Mais avec les fonctions, qui peuvent contenir leur propres variables nécessaires à leurs traitements, ce n'est plus le cas. Les variables internes aux fonctions ne sont effectivement plus visible à l'extérieur de la fonction :
<example>
	  <title>Portée d'une variable</title>
	 <programlisting><computeroutput>
<![CDATA[
#!/usr/bin/php
<?
$a = 3;
function foo( ) {
  $a += 2;
}
foo( );
echo "\n",$a,"\n";
?>

ikare@ix $ ./portee.php 

3
]]>
</computeroutput></programlisting> 
	</example>
Dans cet exemple, la valeur de <varname>$a</varname> n'a pas changé dans le programme principal : le <varname>$a</varname> de la fonction est une variable distincte, dont la durée de vie est celle de la fonction. 
 </para>
      <sect3>
	<title>Variables globales</title>
	<para>Dans certains cas, il peut être utile de pouvoir accèder à une variable depuis une fonction. Il faut à ce moment là déclarer la variable comme <emphasis>globale</emphasis> : 
<example>
	  <title>variable globale</title>
	 <programlisting><computeroutput>
<![CDATA[
#!/usr/bin/php
<?
$a = 3;
function foo( ) {
 global $a; 
 $a += 2;
}
foo( );
echo "\n",$a,"\n";
?>

ikare@ix $ ./globale.php 

5
]]>
</computeroutput></programlisting> 
	</example>

</para>
      </sect3>
      <sect3>
	<title>Variables statiques</title>
	<para>Une variable est dite statique quand sa valeur est partagée par tous les appels à la fonction, c'est-à-dire que sa valeur n'est pas réinitialisée à chaque appel : 
<example>
	  <title>Variable statique</title>
	 <programlisting><computeroutput>
<![CDATA[
#!/usr/bin/php
<?
function compteur( ) {
  static $cpt = 0;
  return $cpt++;
}
for ($i = 1; $i <= 5; $i++) {
  echo compteur( );
}

?>
ikare@ix $ ./static.php 
01234
]]>
</computeroutput></programlisting> 
	</example>

</para>
      </sect3>
    </sect2>


    <sect2>
      <title>Paramètres</title>
      <sect3>
	<title>Passage par valeur</title>
	<para>Dans la plupart des cas, le passage des paramètres depuis le programme appelant vers la fonction se fait <emphasis>par valeur</emphasis> : la valeur du paramètres est assignée à la variable correspondante dans la fonction.</para>      </sect3>

      <sect3>
	<title>Passage par adresse</title>
	<para>Le passage des paramètres par adresse (encore appelé passage par référence), permet de contourner la portée d'une variable en la rendant directement accessible depuis le corps de la fonction. Il s'agit en effet de passer non plus la valeur contenue dans la variable, mais l'adresse mémoire de la variable, en utilisant le symbole <![CDATA[&]]>.</para>
<para>
<informalexample>
<programlisting><computeroutput>
<![CDATA[
function doubler(&$value) {
  $value = $value*2;
}
$a = 3;
doubler($a);
echo $a;

]]>
</computeroutput></programlisting></informalexample>
Dans l'exemple précédent, la fonction <function>doubler</function> n'a pas d'instructions <command>return</command>. La variable passée en paramètre est accesible par la fonction via son adresse mémoire, sa référence. A noter l'appel de la fonction, qui s'effectue cette fois ci sans affectation !
</para>
      </sect3>

</sect2>
    <sect2>
      <title>Récursivité</title>
      <para>Une fonction récusrsive est une fonction qui est utilisée dans sa propre définition. Par exemple, on peut définir la fonction factorielle comme suit : 
<informalexample>
<programlisting><computeroutput>
<![CDATA[
0! = 1
n! = n*(n-1)! pour n > 0
]]>
</computeroutput></programlisting></informalexample>
Dans une fonction récursive, il y a toujours deux choses : 
<itemizedlist>
	  <listitem>
	    <para>un cas de base non récursif, la condition d'arrêt</para>
	  </listitem>
	  <listitem>
	    <para>un cas de récursion qui rapproche du cas de base, si bien qu'à chaque appel, on se rapporche de la fin du calcul. </para>

	  </listitem>
	</itemizedlist>
<para>Il est prouvé théoriquement que chaque fonction récursive peut s'ecrire avec des boucles, et inversement, mais dans certains cas, l'une ou l'autre des manières permet une écriture simplifiée des algorithmes. 
<example>
	  <title>Fonctions factorielle itérative et récursive</title>
	 <programlisting><computeroutput>
<![CDATA[
#!/usr/bin/php
<?
function fact_iterative($n) {
  $res=1;
  for ($cpt=1;$cpt<=$n;$cpt++)
        $res=$res*$cpt;
  return $res;
}

function fact_recursive($n) {
  if ($n <= 0)
        return 1;
  else
        return $n*fact_recursive($n-1);
}

echo "\nFactorielle it~rative de 5 = \t",fact_iterative(5);
echo "\nFactorielle r~cursive de 5 = \t",fact_recursive(5);

?>
ikare@ix $ ./fact.php 

Factorielle it~rative de 5 =    120
Factorielle r~cursive de 5 =    120

]]>
</computeroutput></programlisting> 
	</example>
Lors des appels récursifs à la fonction, les paramètres de la fonction sont empilés, en attendant le retour de la condition d'arrêt. A ce moment là, les paramètres sont dépilés, en calculant à chaque fois leur valeur définitive. 
</para>
</para>
    </sect2>
    <sect2>
      <title>Exercices d'applications</title>
      
      <sect3>
	<title>Fonctions</title>
	<orderedlist>
	  <listitem>
	    <para>Ecrire une fonction qui renvoie le maximum de deux entiers. En utilisant cette fonction, ecrire un programme qui saisi 3 entiers au clavier, et qui les réaffiche dans l'ordre croissant.</para>
	  </listitem>
	  <listitem>
	    <para>Ecrire une série de fonctions sur les tableaux d'entiers, avec les scripts qui permettent de les tester : 
<itemizedlist>
		<listitem>
		  <para>une fonction qui détermine si un nombre est présent dans un tableau</para>
		</listitem>
	        <listitem>
		  <para>une fonction qui donné l'indice de la première occurence d'un nombre dans un tableau. Si ce nombre n'apparît pas, la fonction retourne -10</para>
		</listitem>
	        <listitem>
		  <para>une fonction qui retourne le nombre d'occurence d'un nombre dans un tableau.</para>
		</listitem>
<listitem>
		  <para>une fonction qui retourne un tableau contenant les 10 premiers multiples d'un nombre n donné en paramètre.</para>
		</listitem>
	      </itemizedlist>
</para>
	  </listitem>
	  <listitem>
	    <para>Une permutation est un arrangement d'éléments pris dans un ensemble fini. La fonction de permutation P(n,k) donne le nombre de permutations différentes de k éléments pris dans un ensemble de n. On peut calculer cette fonction en utilisant la formule : P(n,k) = n! / (n-k)!. Coder la fonction en Php. 
</para>
	  </listitem>
	</orderedlist>
      </sect3>


      <sect3>
	<title>Récursivité</title>
	<orderedlist>
	  <listitem>
	    <para>Ecrire une fonction récursive qui calcule la somme des n premiers carrés (1+4+9+...)</para>
	  </listitem>
	  <listitem>
	    <para>Ecrire une fonction récursive puissance qui prend en paramètre deux entiers : le nombre à élever à la puissance, et la puissance.</para>
	  </listitem>
	  <listitem>
	    <para>Ecrire une fonction exponentielle Exp, qui calcule xy sans utiliser l'opérateur ** mais en exploitant la définition récursive :
<programlisting><computeroutput>
<![CDATA[
                xy = 1, si y=0,
                xy = (x*x)y/2, si y est pair,
                xy = (x*x)y/2*x, si y est impair.
]]>
</computeroutput></programlisting>
</para>
	  </listitem>
	  <listitem>
	    <para>Ecrire une fonction recursive Palindrome qui teste si un mot est un palindrome.</para>
	  </listitem>
	  <listitem>
	    <para>Ecrire une fonction Paire_E qui teste si un mot contient un nombre pair de 'E'.</para>
	  </listitem>
	</orderedlist>
      </sect3>
    </sect2>
  </sect1>


  <!-- =========================== CHAPITRE 4 ======================================== -->
  <sect1>
    <title>Fichiers</title>
    <para></para>
  </sect1>

  <!-- =========================== CHAPITRE 4 ======================================== -->
  <sect1>
    <title>Objets</title>
    <para></para>
  </sect1>

  <!-- =========================== CHAPITRE 4 ======================================== -->
  <sect1>
    <title>Bases de données</title>
    <para></para>
  </sect1>
  <!-- =================================================================== -->
  <bibliography> 
    <title>Références</title> 

    <bibliodiv> 
      <biblioentry> 
 	<abbrev>1</abbrev> 
	<authorgroup>
	  <author>	   
	    <personname>
	    <firstname>Welling</firstname>
	    <surname>Luke</surname>
	  </personname>	 
 </author> <author>
	    <personname>
	    <firstname>Thomson</firstname>
	    <surname>Laura</surname>
	  </personname>	  
 	</author>
	</authorgroup>
 	<title>PHP and MySQL - Web Development</title> 
 	<edition> 
SAMS Edition
         </edition> 
      </biblioentry> 

      <biblioentry> 
 	<abbrev>2</abbrev> 
	<authorgroup>
	  <author>	   
	    <personname>
	    <firstname>Ratschiller</firstname>
	    <surname>Tobias</surname>
	  </personname>	 
   </author> <author>
	    <personname>
	    <firstname>Gerken</firstname>
	    <surname>Till</surname>
	  </personname>	  
 	</author>
	</authorgroup>
 	<title>Web Application Development with Php 4.0</title> 
 	<edition> 
New Riders
         </edition> 
      </biblioentry> 

      <biblioentry> 
 	<abbrev>3</abbrev> 
	<authorgroup>
	  <author>	   
	    <personname>
	    <firstname>Valade</firstname>
	    <surname>Janet</surname>
	  </personname>	 
  
 	</author>
	</authorgroup>
 	<title>PHP and MySQL for Dummies</title> 
 	<edition> 
Wiley Publishing, Inc
         </edition> 
  </biblioentry> 
      <biblioentry> 
 	<abbrev>4</abbrev> 
	<authorgroup>
	  <author>	   
	    <personname>
	    <firstname>Lane</firstname>
	    <surname>David</surname>
	  </personname>	 
  
 	</author>
	</authorgroup>
 	<title>Web database applications</title> 
 	<edition> 
O'Reilly
         </edition> 
      </biblioentry>     
 

      <biblioentry> 
 	<abbrev>5</abbrev> 
	<authorgroup>
	  <author>	   
	    <personname>
	    <firstname>Rasmus</firstname>
	    <surname>Lerdorf</surname>
	  </personname>	 

 	</author>
	</authorgroup>
 	<title>Programming PHP</title> 
 	<edition> 
O'Reilly
         </edition> 
      </biblioentry>     

    </bibliodiv> 
  </bibliography> 
</article>
