Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Dernière révision Les deux révisions suivantes
developpement_de_plugin [2014/06/12 15:47]
yann [Plugin plus avancé]
developpement_de_plugin [2014/12/20 17:58]
dany
Ligne 1: Ligne 1:
- +[[developpement:developpement_de_plugin|Développement ​de plugin]]
-====== L'​API ​ ====== +
- +
-Toute la documentation se trouve sur www.phpcompta.eu/​doc;​ seules les classes nous intéressent. La documentation est générée à partir du code avec Doxygen. Le but de cet article n'est pas de revisiter la documentation technique mais de la mettre en oeuvre afin d'​écrire une extension ou plugin. +
- +
-====== Installation de l'​extension ====== +
- +
-[[Installation de plugin]] +
-  +
-===== Connection à la base de données ===== +
- +
-  +
- ​Certaines valeurs doivent ​ toujours être passées à chaque page, par exemple gDossier qui est l'​identifiant du dossier. +
- Pour se connecter c'est assez facile, il faut utiliser la classe Database et la classe Dossier. +
-  +
-  +
- Donc on écrit dans dummy.php +
-  +
-<code php> +
-  echo "​L'​ identifiant de mon dossier est "​.dossier::​id()."<​br>";​ +
-  echo "Son nom réel est "​.DOMAIN."​dossier"​.dossier::​id()."<​br>";​ +
-  echo "Son nom est "​.dossier::​name()."<​br>";​ +
- // Je me connecte à présent à ce dossier +
-  $cn_db=new Database(dossier::​id());​ +
- +
-  +
-</​code>​ +
- +
-   +
- +
-  +
- Je veux afficher toutes les fiches qui concernent le matériel à amortir, donc j'ai +
- ​besoin ​de savoir ce que vaut son FICHE_DEF_REF:​FRD_ID dans constant.php;​ la FICHE_TYPE_XX n'​existe pas, +
- je vois dans la table fiche_def_ref qu'il s'agit de "7 Matériel à amortir"​ +
-  +
- Pour avoir toutes les fiches, +
-  +
-<code php> +
-  $fiche= new Fiche($cn_db);​ +
-  $aFicheMateriel=$fiche->​getByDef(7);​  +
- +
-</​code>​ +
- +
- Pour chaque fiche, je veux afficher son nom, son prix, le nombre d'​années à amortir et la date d'​achat. Je peux en trouver les valeurs dans la table attr_def ou le fichier constant.php,​ +
-  +
- Donc cela devient +
-<code php> +
-  for ($i=0; $i < count($aFicheMateriel);​$i++) { +
-    echo "<​ul>​ +
-     echo "<​li>​ "; +
-     echo "​Nom";​ +
-     echo $aFicheMateriel[$i]->​strAttribut(ATTR_DEF_NAME);​ +
-     echo "</​li>";​ +
-     echo "<​li>​ "; +
-     echo "Prix achat";​ +
-     echo $aFicheMateriel[$i]->​strAttribut(ATTR_DEF_PRIX_ACHAT);​ +
-     echo "</​li>";​ +
-     echo "<​li>​ "; +
-     echo "​Durée amortissement";​ +
-     echo $aFicheMateriel[$i]->​strAttribut(8);​ +
-     echo "</​li>";​ +
-     echo "<​li>​ "; +
-     echo "Date de début";​ +
-     echo $aFicheMateriel[$i]->​strAttribut(10);​ +
-     echo "</​li>";​ +
-     echo "</​ul>​ +
-  } +
-</​code>​ +
-   +
- +
-===== Soumettre des requêtes ===== +
- +
-  +
- ​Uniquement pour l'​exercice,​ nous allons ajouter un FORM. +
- Les données nécessaires dans le FORM sont toujours au minimum: l'id du dossier, le code du plugin+
-  +
- Dans le FORM, on demandera juste à afficher le solde de chaque élément. +
- On aura alors le code suivant, on utilisera la technique des templates +
-  +
-<code php> +
-  $year=new IText('​year'​);​ +
- +
-  $str_year=$year->​input();​ +
- +
-  $str_submit=HtmlInput::​submit('​year_left','​Appliquer'​);​ +
- +
-  require_once('​template1.php'​);​ +
-</​code>​ +
-   +
- +
-   +
- +
-  template1.php +
-<code php> +
-  <FORM METHOD="​GET"​ ACTION="​extension.php">​ +
- +
-  <?​=dossier::​hidden()?>​ +
- +
-  <?​=HtmlInput::​extension()?>​ +
- +
-  Solde pour l'​année : <?​=$str_year?>​ +
- +
-  <?​=$str_submit?>​ +
- +
-  </​form>​ +
-</​code>​ +
-  +
-Puis dans le début du fichier phpcompta/​include/​ext/​dummy/​dummy.php,​ on ajoutera un test pour savoir un FORM a été soumis et on affichera +
-une boîte de dialogue. +
- +
-<code php> +
- if (isset($_GET['​year_left'​])){ +
- +
-    alert('​Vous avez demandé le nombre d\'​années restantes'​);​ +
- +
- } +
- +
-</​code>​ +
-====== Plugin plus avancé ====== +
- +
- +
- +
-Ma première extension, intégrer un fichier de client dans une catégorie +
-de fiche, ce fichier est en CSV. Le code est simple et compréhensible,​ normalement on +
-devrait avoir une meilleure gestion des erreurs, vérifier les attaques SQL Inject,​... +
-Ce code n'est là QUE pour expliquer le concept. On n'a pas utilisé plusieurs pages, ni de templates +
- +
-Tout d'​abord,​ il faut se connecter à la base de données +
- +
-<code php> +
- // se connecter au dossier courant +
- +
- ​$cn=new Database(dossier::​id());​ +
-</​code>​ +
- +
-Dans extension.php on vérifie la sécurité, en ajoutez une dans l'​extension n'est en général pas nécessaire mais vous pourriez avoir votre propre système de sécurité si votre extension est fort complexe +
- +
-En premier lieu, il est nécessaire ​ de choisir dans quelle catégorie de fiche je veux intégrer les +
-enregistrements. Donc on utilise un petit form +
-<code php> +
- +
- echo '<​form METHOD="​get"​ action="​extension.php">';​ +
- +
- echo dossier::​hidden();​ +
- +
- // Ceci vous permet de revenir ici (voir extension.php). Cet élément caché permet d'​include cette page-ci +
- +
- // Donc si votre plugin contient plusieurs pages, vous allez devoir ajouter une seconde variable pour +
- +
- // inclure la page que vous voulez (voir méthode de développement de PhpCompta ) +
- +
- echo HtmlInput::​extension();​ +
- +
- +
- echo "Choix de la catégorie de fiche";​ +
- +
- ​$select_cat=new ISelect('​fd_id'​);​ +
- +
- ​$select_cat->​value=$cn->​make_array('​select fd_id,​fd_label from fiche_def where frd_id='​. +
- +
-     ​FICHE_TYPE_CLIENT);​ +
- +
- echo $select_cat->​input();​ +
- +
- echo HtmlInput::​submit('​display_prop','​Afficher les propriétés'​);​ +
- +
- +
- echo '</​FORM>';​ +
-</​code>​ +
- +
-Il faut remarquer 2 choses dans ce FORM, primo, on utilise les objets HtmlInput et ISelect, secundo on doit avoir absolument en variables cachées, le n° de dossier sur  lequel on est connecté, le code de l'​extension,​ qui permettra à extension.php d'​include le bon fichier. On utilise ici le protocole GET puisqu'​on interroge, le protocole POST est réservé aux sauvegardes,​ c'est une convention assez répandue. La différence,​ est que les requêtes GET se voient dans l'URL, les requêtes POST ne sont jamais dans l'​url. +
- +
- +
-L'​utilisateur soumet le FORM, donc la feuille se recharge et on arrive à cette partie du code +
- +
-On choisit d'​afficher les propriétés avant de confirmer l'​import +
-<code php> +
- if ( isset($_GET['​display_prop'​])){ +
- +
-     ​$a=new Fiche($cn);​ +
- +
-     ​$prop=$a->​toArray($_GET['​fd_id'​]);​ +
- +
-     ​foreach ($prop as $key=>​$value) ​    echo "Index : $key valeur $value <​br/>";​ +
- +
-      +
- +
-     echo '<​form method="​POST"​ action="​extension.php" ​ enctype="​multipart/​form-data">';​ +
- +
-     echo dossier::​hidden();​ +
- +
-     echo HtmlInput::​extension();​ +
- +
-     echo HtmlInput::​hidden('​fd_id',​$_GET['​fd_id'​]);​ +
- +
-     ​$file=new IFile('​fichier_csv'​);​ +
- +
-     echo $file->​input();​ +
- +
-     echo HtmlInput::​submit('​start_import','​Démarrez importation'​);​ +
- +
-     echo '</​form>';​ +
- +
-     ​exit;​ +
- +
- } +
-</​code>​ +
-Voilà, si l'​utilisateur clique sur le bouton SUBMIT, ​ l'​importation va  démarrer. Dans notre exemple, on imaginera que le fichier CSV n'a que 4 champs "nom client","​prenom client",​ "​numero client","​adresse client"​ +
- +
-Le code qui suit est très simplifié, il n'y a peu voire aucun contrôle ni de gestion d'​erreur. +
-<code php> +
- if ( isset($_POST['​start_import'​])){ +
- +
-     ​$fd_id=$_POST['​fd_id'​];​ +
- +
-     ​$tmp_file=$_FILE['​fichier_csv'​]['​tmp_name'​];​ +
- +
-     if ( ! is_uploaded_file($tmp_file))  +
- +
-         die 'Je ne peux charger ce fichier';​ +
- +
-     // on ouvre le fichier  +
- +
-     ​$f=fopen($tmp_file,'​r'​);​ +
- +
-     // On récupère les propriétés de cette catégorie de fiche +
- +
-     ​$client=new Fiche($cn);​ +
- +
-     // $array contient toutes les valeurs nécessaires à Fiche::​insert,​ +
- +
-     ​$array=$client->​toArray($_POST['​fd_id'​]);​ +
- +
-          +
- +
-     while ( $data=fgetcsv($f)) { +
- +
-         // remarque : on a éliminé les traitements d'​erreur +
- +
-          +
- +
-         // On  remet tous les attributs (propriétés) à vide +
- +
-         ​foreach(array_keys($array) as $key) $array[$key]="";​ +
- +
-          +
- +
-         // Nom et prénom +
- +
-         ​$array['​av_text1'​]=$data[0].'​ '​.$data[1];​ +
- +
-         // Numéro de client +
- +
-         ​$array['​av_text30'​]=$data[2];​ +
- +
-         // Adresse +
- +
-         ​$array['​av_text14'​]=$data[3];​ +
- +
-         // Quickcode +
- +
-         ​$array['​av_text23'​]="​CLI"​.$data[2];​ +
- +
-         ​$client->​insert($fd_id,​$array);​ +
- +
-     } +
- +
-     ​exit;​ +
- +
- } +
-</​code>​ +
- +
- +
- +
-Voici le fichier client.txt +
- +
-<​code>​ +
- "​Nom client1","​Prénom","​C1","​Rue de la boite,​55"​ +
- +
- "​Nom client2","​Prénom","​C2","​Rue du couvercle,​55"​ +
- +
- "​Nom client3","​Prénom","​C3","​Rue de la chaussure,​55"​ +
- +
- "​Nom client4","​Prénom","​C4","​Rue de la couleur,​55"​ +
- +
-</​code>​ +
-Si vous vérifiez dans VW_CLIENT, vous verrez que toutes vos fiches ont été ajoutées. Dans l'​exemple,​ il fatraitement d'​erreur plus élaboré; le fait que si une fiche echoue , l'​opération est annulée (Database::​rollback) ou alors création d'un fichier avec les enregistrements "​ratés"​... +
- +
-  +
-====== Ajax ====== +
- +
- +
-  +
- +
-Afin d'​utiliser des fonctions avec ajax, prototype.js devrait être utilisé.Vous devez appeler le fichier ajax.php, ce fichier dans html va simplement vérfier la sécurité et appeler le fichier ajax.php du répertoire où se trouve le plugin avec tous les arguments donnés. +
- +
-  +
- +
-Exemple +
- +
-  +
- +
-dans +
- +
-  +
- +
-dummy/​javascript.js,​ vous avez  +
-<code javascript>​ +
-function show_detail(pop_id){ +
-    $('​detail_invoice_content'​).innerHTML=loading();​ +
-    showIPopup('​detail_invoice'​);​ +
-    try { +
-    var gDossier=$('​gDossier'​).value;​ +
-    var phpsessid=$('​phpsessid'​).value;​ +
-    var code=$('​code'​).value;​ +
-    var obj={"​op_id":​pop_id,"​gDossier":​gDossier,"​phpsessid":​phpsessid,"​code":​code,'​act':'​detail_invoice'​};​ +
-    var queryString=encodeJSON(obj);​ +
-    var action=new Ajax.Request ( '​ajax.php',​ +
-              { +
-                 ​method:'​get',​ +
-                 ​parameters:​queryString,​ +
-                 ​onFailure:​show_detail_error,​ +
-                 ​onSuccess:​show_detail_success +
-               } +
-               ); +
-    } catch (e){alert('​show_detail'​+e.message);​} +
-     +
- +
- } +
-</​code>​ +
-  +
- +
-et dans dummy/​ajax.php +
- +
-  +
-<code php> +
-<?php +
-// Met correctement la langue +
- +
-set_language();​ +
-//retrouve le dossier courant et s y connecte +
- +
-$gDossier=dossier::​id();​ +
-$cn=new Database($gDossier);​ +
- +
-// action +
- +
-$action=(isset($_REQUEST['​act'​]))?​$_REQUEST['​act'​]:'​sh';​ +
- +
- +
-// Véridfie la sécurité +
- +
-require_once ('​class_user.php'​);​ +
-$User=new User(new Database());​ +
-$User->​Check();​ +
- +
-/* Suivant l action demandé, on executera tel ou tel partie de code +
- +
-/* Show the document */ +
-if ( $action == '​sh'​) { +
-/* +
- +
-* Votre code +
- +
-*/} +
-/* remove the document */ +
-if ( $action == '​rm'​ ) { +
-/*votre code et la réponse +
- +
-*/ +
- +
-    header('​Content-type:​ text/xml; charset=UTF-8'​);​ +
-    header ('<?​xml version="​1.0"​ encoding="​UTF-8"?>'​);​ +
-    echo '<​answer>';​ +
-    echo '<​ctl>​detail_invoice</​ctl>';​ +
-    echo '<​html>'​.escape_xml($html).'</​html>';​ +
-    echo '</​answer>';​ +
-+
-?> +
-</​code>​ +
-  +
-====== Les données ====== +
- +
- +
-Si votre extension nécessite de sauver ses propres données, il faut impérativement les mettres dans un schéma séparé. Prévoyez une table version, afin d'​appliquer des mises à jour si nécessaire et un fichier install.php afin de créer les schémas nécessaire +
- +
-exemple +
- +
-create schema plugin_tva;​ +
- +
-create table version (val integer); +
- +
-.... +
- +
-  +
- +
-  +
- +
- +
  • developpement_de_plugin.txt
  • Dernière modification: 2015/01/26 00:58
  • par dany