Développement de Noalyss

Intro

Au début, les développeurs développent la totalité d'un produit et regroupent de fonction dans des librairies puis en adoptant une méthode de développement afin d'avoir un code homogène; ensuite pour éviter cette étape et gagner du temps, ils mettent en place leur propre framework (= cadre de travail).

Connaissant PHP depuis 1998, c'est un langage que je pense maîtriser, j'ai développé dans chaque version de PHP depuis la 1.0. Ayant commencé avant l'arrivée des premiers frameworks, j'ai mis au point une méthode de travail, qui en définitive est devenu un framework maison. Pour le javascript, j'ai utilisé prototype.js, malgré que ce framework est excellent, je l'emploie plus comme une librairie de fonctions.

Organisation des fichiers

  • html= ce qui est appelable directement (modèle mvc)
  • include/ fichier inclu par html (*.inc.php)
  • include/ajax traitement pour les réponse ajax
  • include/template : template , écran & code html
  • include/lib : les classes librairies
  • include/class : class métiers
  • include/database : paradigme orm
  • include/export : fichier pour confection de documents qu'on envoie ( zip , csv, pdf …)
  • include/ext : plugin
  • include/sql : répertoire avec les scripts SQL pour les mises à niveau du programme

Développement en MVC

Le développement en MVC est un développement qui suit les concepts Modèle Vue Contrôle. Il en existe 2 versions. Ici, je ne parlerai que de la première.

En pratique, je crée 3 répertoires de base /html et /include et /include/template, le premier contient les « contrôles » le second les «vues» et le troisième les « modèles ».

Contrôle

Un contrôle est une page php, qui en fonction de l'action demandé va inclure la page «modèle» qu'il faut.

Dans noalyss, cette page est :

do.php pour toutes les demandes de pages

export.php pour toutes les impressions (PDF, CSV, …)

ajax_misc.php pour l'ajax1)

Exemple

la page contrôle contient

<?php
 
if ( !isset ($_REQUEST['do'])) 	exit();
 
$do=$_REQUEST['do'];
 
if ( $do == 'auteur' ) {
 
	require_once('include/auteur.inc.php');
 
}
 
?>

L'explication est assez simple, si la page n'est pas appelé avec une variable do, donné par un POST ou GET alors, le traitement s'arrête. Sinon en fonction de la valeur de la variable, il va inclure le fichier « vue ». Par habitude, mes fichiers vues ont toujours l'extension .inc.php.

Dans noalyss, le fichier do.php va chercher la vue à intégrer dans la base de données, ce qui améliore la sécurité mais aussi une grande souplesse pour les menus. Facile d'en ajouter, d'en retirer, de les renommer…

Vue

Grâce à l'exemple vu dans Contrôle, vous avez compris ce qu'est le concept vue: c'est la présentation de votre action. Donc pour continuer l'exemple, dans le document include/auteur.inc.php, on aurait

<?php
 
require_once ('include/class_auteur.php');
 
if ( ! isset($_REQUEST['sdo']) ) exit();
 
 
 
$sdo=$_REQUEST['sdo'];
 
 
 
if ( $sdo == 'add' ) {
 
	$auteur=**new** Auteur();
 
	$auteur->display_form();
 
}
 
?>

Ici, comme dans contrôle, on vérifie qu'une action est bien demandée, si c'est la cas, on appelle un objet et on lui demande d'afficher quelque chose. Cet objet est ce qui est dans le concept MVC, un modèle. En fait, on dirait une espèce de sous-contrôle

Modèle

Eh oui, le dernier est donc le modèle. Ici ce sont deux classes, l'une va se charger de sauver, afficher, effacer les données et gère donc les relations avec la base de données et l'autre l'objet métier.

Maintenant que vous avez compris MVC, je vais développer un peu les modèles.

Cette partie est un peu plus complexe. Tout d'abord, personnellement, je la divise en deux parties, la première doit gérer les données de la base de données et l'autre les traiter. Comment y arriver ?

Il est vraiment mais vraiment fastidieux de construire une chaîne de caractère contenant tout le code html, surtout quand on emploie aussi du javascript et des tableaux. La solution que j'ai trouvé, je l'ai trouvé en m'inspirant de l'idée de smarty. En fait, je crée un sous-répertoire dans include que j'appelle template, et dedans je met le code HTML de ce qui doit être affiché

function display_form() {
 
ob_start();
 
include  'template/auteur_display_form.php';
 
$r=ob_get_contents();
 
$ob_clean();
 
return $r;
 
 
 
}

exemple Ici on inclus le fichier, comme il est en php, il sera interprété par PHP, il contient surtout du code HTML et des balises PHP, on peut aussi manipuler la chaîne retournée avec les fonctions de chaînes comme str_replace, strcmp,… Ce qui donne à cette méthode encore plus de souplesse.

Il est important de respecter la règle suivante: un minimum d'HTML dans le php et un minimum de PHP dans l'HTML. Il faudra alors utiliser beaucoup de variables avant d'utiliser les templates, il faudra aussi résister à la tentation de mettre de l'html dans la variable, ce qui n'est pas toujours possible.

La documentation

J'utilise Doxygen afin de générer le code ce sont les TAGS brief, param… Cela me permet de générer une documentation; cette documentation me permet de développer plus vite et de mieux vérifier la qualité du code.

Voir le résultat ici http://wiki.noalyss.eu/doc/

Noalyss

Noalyss utilise le MVC, toutes les actions sont controlées par do.php pour les pages web, export.php pour tous les exports (PDF, ODT ou CSV). Ce sont les contrôleurs.

Fichiers importants

Les fichiers à inclure sont dans la table menu_ref, cette table est accèdée à travers la table profile_menu qui décrit l'interface de l'utilisateur, ce qui automatiquement empêche un utilisateur d'accèder à un menu auquel il n'a pas accès.

Le répertoire include contient les fichiers à inclure, les noms de fichiers suivent la logique suivant :

  • Action ajax, le nom de fichier commence par ajax,
  • fichier à inclure le nom de fichier termine par inc.php,
  • fichier objet correspondant à une table NOM_TABLE dans la base de données:class_NOM_TABLE_sql.php,
  • fichier d'object le nom commençent par class

Dans le répertoire template, vous avez les modèles, ce sont des fichiers contenant surtout du code HTML.

En résumé :

Les contrôleurs sont do.php, export.php

Les modèles sont dans include/template

et les vues sont dans le répertore include

La partie base de données

Les mises à jour

Depuis 2005, dans phpcompta, il y a une table VERSION qui contient le numéro du dernier patch appliqué. Quand le fichier do.php est exécuté, il vérifie si le nombre DBVERSION contenu dans constant.php correspond à la version actuelle

/* Ficher do.php */
if (DBVERSION < dossier::get_version($cn))
{
    echo '<h2 class="error" style="font-size:12px">' .
     _("Attention: la version de base de donnée est supérieure à la version du programme, vous devriez
 mettre à jour") . '</h2>';
}
if (DBVERSION > dossier::get_version($cn))
{
    echo '<h2 class="error" style="font-size:12px">' . _("Votre base de données n'est pas à jour") . '   ';
    $a = _("cliquez ici pour appliquer le patch");
    $base = dirname($_SERVER['REQUEST_URI']) . '/admin/setup.php';
    echo '<a hreF="' . $base . '">' . $a . '</a></h2>';
}

Dans le cas où DBVERSION n'est pas la valeur contenue dans la base de donnée, do.php vous propose d'appliquer le patch sur vos bases de données. Voici la fonction qui applique les patch SQL pour la base de données

/* fichier setup.php */
//----------------------------------------------------------------------
// Upgrade the folders
//----------------------------------------------------------------------
 
for ($e=0;$e < $MaxDossier;$e++) {
   $db_row=Database::fetch_array($Resdossier,$e);
  echo "<h3>Patching ".$db_row['dos_name'].'</h3>';
 
  $name=$cn->format_name($db_row['dos_id'],'dos');
 
  if ( $cn->exist_database($name)> 0 )
  {
    $db=new Database($db_row['dos_id'],'dos');
    $db->apply_patch($db_row['dos_name']);
    Dossier::synchro_admin($db_row['dos_id']);
 
  } else
  {
      echo_warning(_("Dossier inexistant")." $name");
  }
 }

La fonction qui applique le patch est Database::apply_patch voir la documentation en ligne

Tous les patchs pour la base de données se trouve dans /noalyss/include/sql/patch/ et sont numérotés dans l'ordre d’exécution. Chaque patch commence par

BEGIN;

et termine par

UPDATE version SET val=13;
 
commit;

Ainsi, si le script échoue, la mise à jour s'arrête et annule toute ce qui a été fait dans le script contenant l'erreur, la base de données reste ainsi dans un état cohérent. Une fois l'erreur corrigée dans votre base de données, ce script ainsi que ceux qui suivent seront appliqués quand vous appelerez à nouveau phpcompta/admin/setup.php

Accèder aux données : DAO

Nous avons créér une classe qui va hériter de Noalyss__SQL et qui va nous permettre de faire la même chose en très peu de ligne de code.

Cette classe fournit les fonctions suivantes

  • insert pour insérer une ligne dans la base de données
  • delete pour insérer une ligne dans la base de données
  • update pour mettre à jour une ligne dans la base de données
  • verify à surcharger, vérifie que les données sont conformes
  • setp setter
  • getp getter
  • get_info affiche le contenu de l'objet
  • from_array transforme un tableau en un objet
  • seek recherche dans la table sur base d'une condition
  • next retourne l'objet suivant (après seek)

Voici tout le code à taper par table, exemple pour la table stock_change

class Stock_Change_Sql extends Noalyss_SQL
{
	// Le contructeur obligatoire
	function __construct($p_id = -1)
	{
		// Façon dont les dates sont utilisées
		$this->date_format="DD.MM.YYYY";
		// Nom de la table 
		$this->table = "public.stock_change";
		// nom de la clef primaire
		$this->primary_key = "c_id";
 
		// Structure de la table, à gauche le nom logique utilisable
		// avec les getters/setters (setp/getp) et à droite le nom de la
		// colonne
		$this->name = array(
			"id" => "c_id",
			"c_comment" => "c_comment",
			"c_date" => "c_date",
			"tech_date"=>"tech_date",
			"tech_user"=>"tech_user",
			"r_id"=>"r_id"
		);
		// Type de données
		$this->type = array(
			"c_id" => "numeric",
			"c_comment" => "text",
			"c_date" => "date",
			"tech_date"=>"date",
			"tech_user"=>"text",
			"r_id"=>"numeric"
		);
		// Les colonnes qui ne peuvent pas être changée ni par insert ni par 
		// update parce leurs valeurs sont données automatiquement 
		// exemple : la clef primaire qui est un numéro de séquence 
		//automatiquement donné
		$this->default = array(
			"c_id" => "auto",
			"tech_date" => "auto"
		);
		global $cn;
 
		parent::__construct($cn, $p_id);
	}
}

Si on change la structure d'une table, il ne faut presque rien changer : seulement quelques lignes.

Les tests unitaires

Avant on utilisait dans chaque class , une fonction nommée test_me qui pouvait être appelée depuis le fichier test.php.

A partir de NOALYSS (version 6.7.2.0), et pour les plugins nous utiliserons PHPUnit.Ces tests sont heureusement appelables directement depuis NetBeans (version 7.4 et supérieure).

Il faut tout d'abord un fichier bootstrap qui contient le path correct pour php ainsi que les variables comme $g_user ou $cn, l'inclusion de config.inc.php et de constant.php

1) Pour l'ajax, il existe plusieurs fichiers, ajax_misc.php est en général utilisé
/srv/web/wiki.noalyss.eu/www/data/pages/developpement/noalyss.txt · Dernière modification: 2018/05/30 16:17 par dany
 
Sauf mention contraire, le contenu de ce wiki est placé sous les termes de la licence suivante : GNU Free Documentation License 1.3
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki