Process Explorer de Sysinternals

Pour le développement et même pour avoir une meilleur connaissance du fonctionnement de son PC sous Windows, un outil qui doit être installé à mon avis par défaut est Process Explorer.

Pour information, l’entreprise Sysinternals a été racheté par Microsoft en 2006, on trouve donc maintenant la suite d’outil sur le site web technet de Microsoft.

Parmi la suite d’outils, le plus utilisé et le plus intéressant est procexp64.exe ou en version 32bits procexp.exe. Pour obtenir la dernière version de ce logiciel, il suffit de télécharger le fichier zip et le dézipper dans un dossier autre que « Programmes » ou « Program Files (x86) ».

Nota: j’utilise un dossier c:\Developpement\ pour installer tous les outils de développements/systèmes/library/scripts car j’ai remarqué que les programmes installés dans les dossiers « Programmes », « Program Files (x86) », « Windows », « Utilisateurs » ou tout autre dossier directement à la racine du disque sont particulièrement surveillé par Windows. Ce qui les rendaient très lent et parfois déclenche des erreurs. Ce n’est qu’une réflexion empirique, après vous faites comme vous voulez.

 

Vous vous retrouvez alors avec 4 fichiers:

  • Eula.txt est la licence
  • procexp.chm est le fichier d’aide
  • procexp.exe est le process explorer version 32bits
  • proxecp64.exe est le process explorer version 64bits

Lancer le process explorer selon la version de votre système d’exploitation:

L’affichage que je vous présente est en version « Show Process Tree », accessible via la barre de menu

Elle montre la liste des processus avec l’imbrication des appels des applications.

C’est la visualisation la plus utile je trouve car elle me permet d’identifier rapidement les liens entre les différents processus. Vous noterez que la colonne « Command Line » que j’ai affiché est très large car l’information qu’il me manque souvent est « quel est cet exe qui fonctionne sur mon PC » et rapidement avec le chemin complet de l’application je retrouve à qui est ce programme.

Par exemple, le « QLBController.exe » est en fait démarré par cette ligne de commande:

"C:\Program Files (x86)\Hewlett-Packard\HP Hotkey Support\QLBController.exe" /start

Je peux donc voir que c’est un outil installé par HP sur mon PC pour gérer les touches additionnelles du clavier.

Je peux en double cliquant ouvrir des informations beaucoup plus détaillés sur ce processus:

J’ai indiqué en rouge quelques zones intéressantes:

  • la ligne de commande complète pour le démarrage du programme
  • La clef de registre démarrant le processus si je veux par exemple la désactiver
  • Une nouveauté dans cette version avec une évaluation par le site VirusTotal de ce processus.
  • Un bouton « explorer » pour ouvrir le dossier ou la clef de registre directement
  • Un onglet TCP/IP qui permet de comprendre les connexions réseaux de ce processus

Cet outil est livré avec énormément d’options, je peux rajouter le « Find Window’s process » qui permet de lier une fenêtre graphique d’une application avec le processus qui a ouverte cette fenêtre. Cela permet si une fenêtre est figée de connaitre le nom du processus.

Il y a aussi la fonction de recherche qui permet de trouver par exemple le nom de l’application qui a toujours la main sur un fichier que vous n’arrivez pas à effacer.

Le dernier point est que l’on peut indiquer via le menu « Options » que l’on souhaite remplacer le gestionnaire de tâches par défaut de Windows par le « process explorer »:

Inutile de vous dire que vu le nombre de fois que je l’utilise il est mon gestionnaire de tâche par défaut.

Publié dans Développement | Laisser un commentaire

Premier développement Seafile

Suite à l’utilisation de Seafile alternative open-source à Dropbox, je me suis posé la question du rajout de fonctionnalité dans cette solution.

1/ Installation de Seafile Community Edition 5.1.3

Pour tester le développement, j’ai utiliser un serveur seafile version 5.1.3 plus petite et plus simple pour commencer à étudier les APIs. Je souhaite intervenir uniquement sur la partie Web appelée Seahub (en rouge sur le diagramme ci-dessous), donc je ne réalise pas une installation « build » comme expliquer par seafile mais une installation classique.

Diagramme des différents software de la solution Seafile

 

Editer le fichier  « .\seafile-server-5.1.3\seahub\seahub\settings.py » pour mettre les variables facilitant le développement:

# DEBUG = False
DEBUG = True
TEMPLATE_DEBUG = DEBUG

 

Démarrer ensuite et utiliser Seafile de manière classique pour vérifier que tout est opérationnel.

Après l’installation classique du serveur car je ne souhaite intervenir que sur la partie site web développé en Django et en python, il suffit d’activer les réglages de débogage.

 

2/ Localisation de la zone d’intervention

La problématique que je rencontre avec Seafile est de comprendre l’organisation du code; où intervenir pour ajouter une fonctionnalité.

En premier lieu, de manière classique en développement web, je cherche avec l’inspecteur de Chrome Developer Tools, la zone HTML qui m’intéresse:

On peut voir que le <div class= »op-containter »> gère la zone où on pourrait rajouter une fonctionnalité sur un fichier stocké dans le Seafile.

Une petite recherche via la console cygwin avec un grep pour trouver le fichier intéressant dans seahub/seahub/templates/js/templates.html

Il y a trois fois le tag que l’on cherche, une fois pour une bibliothèque, une fois pour un dossier et enfin la dernière fois pour un fichier.

Ajoutons donc une nouveau élément à la liste juste après le choix « Ouvrir avec le client »

<li><a class="op open-via-client" href="seafile://openfile?repo_id=<%- repo_id %>&path=<% print(encodeURIComponent(dirent_path)); %>">{% trans "Open via Client" %}</a></li>
<!-- PJE -->
<li>
   <a class="op open-diff" href="<% print("http://URL/"); %>">{% trans "Diff" %}</a>
</li>
<!-- /PJE -->

L’entrée du menu est visible dans l’interface web mais pour l’instant ne renvoie sur aucun site. L’URL que l’on souhaite fabriquer est recopiable depuis la page « Historique » du fichier.

L’URL est de la forme suivante:

http://<Nom_du_serveur:port>/repo/text_diff/<id_de_l_objet>/?p=<chemin_nom_fichier>&commit=<id_commit>

Cela permet de présenter l’interface qui montre les différences entre la dernière version du  fichier et l’avant dernière version.

3/ Comment fabriquer cette URL dans le menu associé avec le fichier

Pour repérer le fichier python qui envoie les données, en premier lieu, j’ai remarqué que l’affichage de la liste des fichiers est réalisé en arrière plan du chargement de la page via un appel ajax comme visible dans le Chrome Developer Tools:

en affichant les données envoyé par le serveur django, on peut voir que la liste des données envoyé est réduite:

{ "encrypted": false,
  "is_virtual": false,
  "user_perm": "rw",
  "dirent_list": 
     [
     {"obj_id": "79d2a1ab64773b325d2b19fb80a4781af5bd1dd2",
     "file_icon": "txt.png",
     "perm": "rw",
     "last_update": "<time datetime=\"2017-05-24T16:42:46\" is=\"relative-time\" title=\"mer, 24 Mai 2017 16:42:46 +0800\" >Il y a 7 jours</time>",
     "last_modified": 1495640566,
     "file_size": "184\u00a0bytes",
     "is_file": true,
     "obj_name": "matlab1.txt",
     "starred": false},
  
    {"obj_id": "b88ab96740ef53249b9d21fb3fa28050842266ba",
     "file_icon": "word.png",
     "perm": "rw",
     "last_update": "<time datetime=\"2016-09-14T12:19:06\" is=\"relative-time\" title=\"mer,
     14 Sep 2016 12:19:06 +0800\" >2016-09-14</time>",
     "last_modified": 1473851946,
     "file_size": "293,5\u00a0KO",
     "is_file": true,
     "obj_name": "seafile-tutorial.doc",
     "starred": false}],
     "is_repo_owner": true,
  "repo_name": "Ma biblioth\u00e8que"
}

On peut voir que l’id de commit n’est pas indiqué dans aucun des deux fichiers. Pour fabriquer notre URL cet identifiant ce qui est necéssaire pour construire l’URL.

En localisant avec encore un grep d’où provient la requête Ajax, j’ai ouvert le fichier dans PyCharm Community Edition pour trouver la boucle qui fabrique le fichier Json.

 Le fichier ajax.py dans le dossier seahub/views/ajax.py

Et plus particulièrement c’est la fonction list_lib_dir dans ce fichier qui fabrique le fichier JSON. Voici spécifiquement l’endroit qui gère la boucle sur les fichiers:

for f in file_list:
    f_ = {}
    f_['is_file'] = True
    f_['file_icon'] = file_icon_filter(f.obj_name)
    f_['obj_name'] = f.obj_name
    f_['last_modified'] = f.last_modified
    f_['last_update'] = translate_seahub_time(f.last_modified)
    f_['starred'] = f.starred
    f_['file_size'] = filesizeformat(f.file_size)
    f_['obj_id'] = f.obj_id
    f_['perm'] = f.permission # perm for file in current dir

Nous allons rajouté une propriété à la liste f_ qui s’appellera [‘diff’].
Voici l’instruction qui fabrique une valeur URL pour tester que côté navigateur la récupération s’effectue correctement:

f_['diff'] = 'http://URL/'

Donc côté page html je peux remodifier le fichier template.html pour intégrer la propriété [‘diff’]

<li><a class="op open-diff" href="<% print(dirent.diff); %>">{% trans "Diff" %}</a></li>

Cela doit permettre d’afficher dans le navigateur le choix Diff dans le menu avec une valeur qui provient du programme python.

 4/ Code final

Voici le code final pour fabriquer les variables path, obtenir la liste des versions d’un fichier (commits) et ainsi fabriquer l’URL valide:

# PJE
path = path + f.obj_name
commits = seafile_api.get_file_revisions(repo_id, path, -1, -1)

if len(commits) > 1:
    # http://127.0.0.1:8000/repo/text_diff/b8f97076-d57f-4f49-aaa8-d0531de51f12/?p=/matlab1.txt&commit=c65591a759910cfe4fb76ff18e1047f202424b31
    f_['diff'] = SERVICE_URL + "/repo/text_diff/" + repo_id + "/?obj_id=" + f.obj_id \
                 + "&commit=" + str(commits[0].__getattr__("id") ) + "&p=" + str(path)
else:
    f_['diff'] = ''

# /PJE

On peut noter que s’il n’y a pas de versions alors la valeur f_[‘diff’] est créé vide. Cela nous oblige à reprendre la page html pour ne pas afficher l’option Diff dans le menu dans ce cas là:

<li><a class="op open-via-client" href="seafile://openfile?repo_id=<%- repo_id %>&path=<% print(encodeURIComponent(dirent_path)); %>">{% trans "Open via Client" %}</a></li>
<!-- PJE -->
<% if (dirent.diff != '' ) { %>
    <li><a class="op open-diff" href="<% print(dirent.diff); %>">{% trans "Diff" %}</a></li>
<% } %>
<!-- /PJE -->

Voici l’affichage de menu sans l’item Diff :

Version sans l’item de menu Diff

Il est inutile de présenter une option si elle n’est pas disponible. Une autre solution que je n’ai pas exploré est de présenter l’option dans le menu mais grisée et désactivée.

 5/ Debug

J’ai découvert de manière plus ou moins fortuite comment debogger dans PyCharm Community Edition avec Seafile. Après avoir démarré le serveur Seafile avec l’option Debug=True et mis un point d’arrêt dans le code fichier ajax.py, il suffit d’attacher le debogger de Pycharm au programme python qui démarre seahub:

Ensuite en consultant la page web on a le deboggeur qui s’enclenche sur le point d’arrêt. La seule partie du code pour l’instant que je n’arrive pas à tracer se trouve dans le code des pages html écrit dans le langage de template de python. Par contre, j’arrive très bien à activer le deboggage dans le navigateur pour comprendre comme avec les autres langages  PHP/Java/Perl/etc.  ce qui se passe côté Javascript du navigateur.

 6/ Conclusion

Ce le menu fonctionne correctement, il me parait encore un peu complexe de comprendre où intervenir pour que cette « nouvelle fonctionnalité » (elle se trouve ailleurs dans Seahub en fait), soit résistante quelque soit la situation (fichier privé, navigateur peu récent, etc.)

C’est le premier développement que je fais en python avec Seafile, cela me motive pour continuer mai

Publié dans Développement | Laisser un commentaire

Tp3 Ema EMACS Développement Web

1/ Utilisation de javascript avec jquery

Avec le javascript et la bibliothèque jquery, nous pouvons mettre en barré le texte associé à une case cochée par l’internaute.

Supposons que nous disposons du code HTML suivant fabriqué à l’origine par la JSP:

<p>
<input type="checkbox" name="checkbox_eau" > Eau
</p>

Nous devons en premier lieu pouvoir manipuler le texte du à côté de la case à cochée, en ajoutant un tag span nous indiquons que ce texte n’est pas simplement un texte sans modifier la mise en forme.

<p>
<input type="checkbox" name="checkbox_eau" >
<span id="checkbox_eau"> Eau </span>
</p>

Nous aimerions ensuite pouvoir lier le click sur la case de la checkbox à la modification du HTML par le javascript en ajoutant la classe barre au tag <span>:

<p>
<input type="checkbox" name="checkbox_eau" >
<span id="checkbox_eau" class="barre"> Eau </span>
</p>

Nous allons appeler jquery directement depuis le serveur hébergent ce projet (CDN) via l’ajout de ce code dans la JSP:

 <script
 src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>

ou en téléchargeant le code javascript pour garder notre version en local et ne pas subir les évolutions de la version jquery:

 <script src="js/jquery-latest.min.js"></script>

Nous pouvons maintenant coder directement en javascript dans la page HTML pour les premiers tests puis ce code ira dans un fichier javascript dans le dossier js:

 <script language="javascript">

 $(document).ready(function() {
    $("input[type=checkbox]").click(
         function(event) { 
            var name = $(this).attr("name");
            var checked = $(this).prop('checked');;
            console.log( $(this).attr("name") );
           // ... continuer en javascript
         });
   
 });
// 
</script>

en décomposant ce code nous avons un premier appel à une fonction anonyme dans la méthode ready.

$(document).ready(function() {
    // ce code javascript est déclenché quand la page est chargée
});

Jquery exploite une fonction qui s’appelle $ pour chercher soit dans le DOM de la page HTML un ou plusieurs éléments/tags, par exemple :

$("h1") // cherche des tags h1
$("#header") // cherche des tags avec id="header"

$("input[type=checkbox]") // cherche des tags input avec un attribut input qui vaut checkbox

la dernière instruction permet donc de trouver nos checkbox et nous allons leur ajouter un événement click dessus.

$("input[type=checkbox]").click(  );

Pour ajouter ce qui doit être fait par le click nous indiquons ainsi une fonction javascript anonyme qui va être appelée par cet événement click :

         function(event) { 
            var name = $(this).attr("name");
            var checked = $(this).prop('checked');;
            console.log( $(this).attr("name") );
           // ... continuer en javascript
         });

console.log appelle la console Javascript embarquée dans les navigateurs (voir plus bas).

En exploitant la fonction de recherche d’un tag à partir de son id et en utilisant la méthode addClass(« barre ») vous pouvez ajouter une classe au bon texte.

$("span#checkbox_eau").addClass("barre");

 

Nous pouvons exploiter le débugger et la console javascript embarqués dans nos navigateurs. Voici l’exemple avec Firebug (pour Chrome faire CTRL+ALT+I) :

Animation de l'activation des onglets: Console, Script et Réseau

Animation de l’activation des onglets: Console, Script et Réseau

Nous pouvons afficher le code Javascript et poser des points d’arrêt dans notre code.

Avec firebug, affichage du code javascript et point d'arrêt ajouté

Avec firebug, affichage du code javascript et point d’arrêt ajouté

Pour Firefox:

Pour Chrome: 

Nota: la fonction $ peut parfois être utilisé par d’autres frameworks Javascript. on peut alors remplacer les appels via jQuery:

jQuery(document).ready(function(jQuery){
            // ne pas utiliser la fonction $ mais jQuery
        });

2/ Injection de javascript avec AngularJS 1.x

AngularJS est actuellement en version 2.x mais cette version s’appuie sur une sur-implémentation de Javascript appelé TypeScript. Le développeur code en langage TypeScript qui passe dans un compilateur TypeScript pour générer du Javascript spécialisé.

AngularJS 2 est plus performant et plus léger que la version 1.x mais nous allons utiliser la version AngularJS 1.x car elle est plus simple en évitant cette compilation additionnelle.

Nous injection dans le tag <header> le chargement d’AngularJS 1.6.1  et d’un fichier Javascript qui va gérer en MVC la manipulation du HTML dans la page Web:

<script
 src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<script src="js/todo.js"></script>

Nous appelons dans une DIV une application todoApp :

<div ng-app="todoApp">

Puis dans un autre DIV incluse dans la précédente nous appelons la gestion de la liste des todo via un controller avec une fabrication du tag de début de liste <ul>:

<div ng-controller="TodoListController as todoList">
 <ul>

 

Nous avons ensuite une boucle qui va charger successivement les todos :
<li ng-repeat= »todo in todoList.todos »>

Nous pouvons ensuite appelé un champ de type checkbox qui va être lié à la partie modèle de notre application AngularJS:

<input type="checkbox" ng-model="todo.actif"> 

Nous pouvons indiquer à AngularJS que nous voulons un affichage du contenu des objects Javascript avec ce genre de code:

{{todo.texte}}
Maintenant pour la partie formulaire nous allons coder l'appel via le bouton Submit à la fonction addTodo qui se trouve dans AngularJs et qui fera ensuite appel au travers du réseau à la Servlet Controlleur: 

 <form ng-submit="todoList.addTodo()">
 <input type="text"  ng-model="todoList.todoText"  placeholder="add new todo here"> 
 
 <input type="submit" value="add">
 </form>

Voici le code todo.js pour déclencher l’affichage de quelques todos pour tester votre application AngularJS:

// Création de l'application todoApp et déclaration du controleur avec le module http activé
angular.module('todoApp', []).controller('TodoListController', function( $http ) {

var todoList = this;
 
todoList.todos = [
{ texte: 'chocolat' , actif:false},
{ texte: 'gateaux' , actif:true}
];
 
// Fonction pour ajouter un  todo depuis l'interface HTML
todoList.addTodo = function() {
      todoList.todos.push( {texte:todoList.todoText, actif:false});
      todoList.todoText = '';
};

}); // Fin application

Pour l’instant tout ce code ne permet qu’une manipulation en local dans le navigateur de la liste des Todos. Il faut via une commande Ajax faire une requête vers le serveur pour que la mise à jours soit effective dans la base de données.

Nota: le paramètre action dans la liste des paramètres permet à la notre Servlet Controlleur de savoir que la demande via pour de l’ajax et qu’il faut faire un ajout du Todo dans la base de données et d’ensuite répondre en  json par exemple:

// Création de la liste des paramètres de la requête GET avec le paramètre action 
var parametres = {action: "ajax.add_todo" };

$http({
  method : "GET",
  url : "./Controleur",
  params: parametres,
})
   .then(function successCallback(response) {
        console.log( response.data );
        // Rafraichir la liste avec la reponse en Json reçue
}, function errorCallback(response) {
        // En cas d'erreur par exemple 404 pour la requête GET sur le controleur
        console.log( response );
});

 

Publié dans Emacs | Laisser un commentaire

TP4 – Technologies Web

1. Généralité sur la base de données

 1.1 Mysql vs phpMyAdmin

Pour manipuler une base de données stockée dans un logiciel de gestion de base de données (SGBD), on peut utiliser plusieurs outils d’administration pour créer, effacer, modifier les tables et les données qu’il stocke.

Mysql est un SGBD très populaire mais ses outils d’administrations sont souvent complexe. Une équipe de développeur à conçu un outil écrit en PHP pour l’administration de Mysql, cet outil est phpMyAdmin.

Pour EasyPhp, cet outil est accessible  via l’adresse suivante pour les machines de la salle de TP:http://127.0.0.1:8887/modules/ ou http://127.0.0.1:8887/home/mysql/ ou

Pour les installations de Mamp/Wamp, l’adresse classique est souvent: http://127.0.0.1/phpmyadmin/

 1.1 Vocabulaire de la base de données

Une base de données regroupe un ensemble de tables de données (équivalent au classeur Excel).

Une table de données regroupe et structure un type d’information (équivalent à une feuille Excel)

Cas pratique, une liste d’élève du Master CTN qui dispose de plusieurs adresses emails : Première table listant les élèves: (nom de la table eleve): avec les champs id, nom, prenom, promotion :

id   nom     prenom    promotion
1    Dupond  Alfonse   2008
2    Duval   Joseph    2008
3    Smith   John      2009

Nota : id est le champ clé de la table, il permet d’identifier de manière unique chaque enregistrement (VF : chaque ligne). Si on utiliser le champs nom comme clef, on ne pourrait avoir 2 personnes ayant le même nom.

Seconde table listant leurs adresses emails: (nom de la table email) avec les champs id, mail, id_eleve

id     mail                id_eleve 
1      a.dupond@ema.fr     1 
2      dupond@yahoo.fr     1 
3      j.smith@ema.fr      3

Nota : id_eleve et le champ clé étrangère car ce champs symbolise la liaison avec le champ id de la table eleve

Nota 2 : Dans notre exemple les champs (les colonnes) id de la table élève et de la table email sont prévues pour être automatiquement incrémenté, identifiant chaque ligne de manière unique.

2. Création du schéma de la base de données.

Dans l’outil phpMyAdmin :

Créer une nouvelle base de données appelé base_contact

  • Onglet « Bases de données » > Créer une base de données
  • Dans la partie gauche de l’interface de phpMyAdmin, choisir cette base de données

 

Créer une nouvelle table appelée eleve (sans accent) avec 4 colonnes (4 champs)

  •  id est un IDentifiant de type INT indiquant que l’on va stocker des nombres entiers, il faut par contre utiliser la barre de défilement horizontal pour trouver l’information A_I (auto incrémentation) pour que ce champ soit automatiquement incrémenté. Ce champ est appelé une clé car il est unique pour chaque enregistrement (ligne) de la table.
  • nom et prenom sont des champs pouvant recevoir tout type de texte (nombre, symbole, lettres, etc.) sur une seule ligne en quantité VARiable de 0 à 50 CARactère (en anglais Character) VARCHAR
  • promotion va être indiqué en tant que CHAR (caractère) de taille fixe 4, il faudra forcément avoir 4 symboles 2004, 2005, 2006, 2007. Impossible d’avoir 98,99,00,01,02
  • Appuyer sur le bouton « Sauvegarder » pour créer la table, noter que l’on n’utilise aucun symboles ou accents pour les noms des champs de la base de données

Insérer des données dans cette table via le bouton « Insérer » en s’inspirant du cas pratique indiqué au dessus :

Faite une dizaine d’enregistrement dans la table eleve.

Créer une nouvelle table appelée email (sans accent) avec 3 colonnes

  •  id est un IDentifiant de type INT indiquant que l’on va stocker des nombres entiers, il faut par contre utiliser la barre de défilement horizontal pour trouver l’information A_I (auto incrémentation) pour que ce champ soit automatiquement incrémenté. Ce champ est appelé une clé car il est unique pour chaque enregistrement (ligne) de la table.
  • mail est un champs pouvant recevoir tout type de texte (nombre, symbole, lettres, etc.) sur une seule ligne en quantité VARiable de 0 à 100 CARactère (en anglais Character) VARCHAR
  • id_eleve est de type INT mais pas avec l’option A_I car il fait référence à la clé de la table eleve. id_eleve est une clé étrangère liant la table eleve à la table email.
  • Insérer des données dans cette table via le bouton « Insérer » en s’inspirant du cas pratique indiqué au dessus
  • Il faudrait disposer au final d’un élève avec plusieurs adresses email, un élève avec une seule adresse email et un élève sans aucune adresse email.

2. Interroger Mysql en SQL

Ouvrer l’onglet SQL en choisissant la base de données base_contact :

Essayez la requête suivante et expliquez son effet:
SELECT prenom,nom FROM eleve ;

Essayez la requête suivante et expliquez son effet :
SELECT * FROM eleve ;

Essayez la requête suivante et expliquez son effet:
SELECT id, nom FROM eleve limit 3,2;

Essayez la requête suivante et expliquez son effet:
SELECT id, nom FROM eleve limit 1,2;

Essayez la requête suivante et expliquez son effet:
SELECT * FROM eleve WHERE Nom = ‘Dupond’ ;

Essayez la requête suivante et expliquez son effet:
SELECT * FROM eleve WHERE Promotion = ‘2008’ ;

Essayez la requête suivante et expliquez son effet:
SELECT * FROM eleve WHERE Promotion = ‘2008’ AND Nom =’Dupond’ ;

COUNT permet de compter le nombre de lignes incluses dans une table, essayer l’exemple:
select count(*) FROM eleve;

Afficher le nombre d’élèves dont le nom commence par D :
select count(*) FROM eleve WHERE nom LIKE ‘D%’;

Afficher (que) les élèves qui ont des emails
SELECT nom,prenom,mail FROM eleve, email WHERE eleve.id=email.id_eleve;

Insérer un nouvel élève
INSERT INTO eleve VALUES(NULL, ‘Gineau’, ‘Nicolas’, ‘2010’);

Supprimer un élève
DELETE FROM eleve WHERE nom=’Gineau’;

Modifier (mettre à jour) le nom d’un élève
UPDATE eleve SET nom=’Dupont’ WHERE nom= ‘Dupond’

Afficher le nombre d’emails par élève
SELECT id_eleve, mail, count(mail) FROM email GROUP BY id_eleve

Faire et expliquer
SELECT * FROM eleve, email WHERE eleve.id = email.id_eleve

Faire et expliquer
SELECT * FROM eleve LEFT JOIN email ON eleve.id = email.id_eleve

Faire une requête SQL qui affiche le nom de l’élève et une de ses adresses emails sans
aucune autre information technique

Faire une requête SQL qui affiche le nom de l’élève et le nombre de ses adresses emails sans aucune autre information technique

3. Création d’un utilisateur de Mysql

Pour accéder à une base de données, il faut disposer d’un compte utilisateur qui dispose de droit sur cette base de données. La création d’un nouvel utilisateur se fait via l’onglet Privilèges ; parfois renommé Utilisateur dans les dernières versions de phpMyAdmin.

Utiliser le bouton « Ajouter un utilisateur » Dans la nouvelle page, il faut indiquer un nom d’utilisateur par exemple user_contact, le client est localhost (ou 127.0.0.1), le mot de passe peut être fabriqué avec le bouton « générer » ou entrer deux fois pour vérification (dans l’exemple ci-après j’utilise VqQEK98bBSGCQ5b2 comme mot de passe).

Cochez la case « Donner les privilèges passepartout (utilisateur\_%) » mais habituellement, l’option « Créer une base portant son nom et donner à cet utilisateur tous les privilèges sur cette base » est utilisée pour fabriquer un utilisateur et une base de données, l’utilisateur ayant tout les droits sur cette base de donnée.

La création de l’utilisateur se fait avec le bouton « Exécuter » qui se trouve tout en base de la page.

4. Interroger Mysql depuis une page PHP

Le programme ci-dessous va fabriquer 3 variables contenant le nom de l’utilisateur de base de données, le mot de passe associé et la base de données que l’on souhaite accéder:

<html>
<body>
<?php
$username = "user_contact";
$password = "VqQEK98bBSGCQ5b2";
$database = "base_contact";

// Connexion à Mysql
$link = mysqli_connect( "localhost" ,$username,$password);

// Sélection de la base de données
mysqli_select_db( $link , $database );

// Création d'une variable pour interroger Mysql
$query = "select nom,prenom from eleve";

// Obtention du résultat dans la variable $result
$result = mysqli_query( $link , $query);

// Boucle pour extraire chaque enregistrement du résultat
while ($row = mysqli_fetch_array( $result , MYSQLI_ASSOC )) {
?>
    <p>
    <?php
         echo( $row["nom"] );
    ?>
    </p>
<?php
}

// Fermeture de la connexion à Mysql 
mysqli_close( $link );
?>
</body>
</html>

 

4 fonctions sont utilisées pour accede à mysql

  • mysql_connect ouvre une connexion avec le logiciel de base de donnés (le SGBD)
  • mysql_select_db permet de choisir une base de données parmi plusieurs
  • mysql_query permet de poser une question en SQL à la base de données
  • mysql_close permet de fermer la connexion avec le logiciel de base de données

Pourquoi le nom est le seul affiché ? Comment corriger cette page pour afficher le prénom et la promotion de chaque élève ?

Sachant que la requête SQL suivante permet de créer un nouvel enregistrement (une nouvelle ligne) dans la table de la base de données, comment faire pour créer un nouvel élève depuis un formulaire:

$query = "insert into eleve( nom, prenom, promotion) values ('Doe' , 'John' , '2014' ) ";
$result = mysqli_query( $link , $query);

Nota: L’explication sur la concaténation ci-dessous peut être utile.

5. Création d’une variable par concaténation

Régulièrement, en PHP, on doit pouvoir fabriquer une variable en « ajoutant » le contenu d’une variable dans une autre variable. Cette opération s’appelle la concaténation.

Il y a plusieurs solutions pour réaliser la concaténation.

L’opérateur de concaténation « . » :

$nom = "Doe";
$prenom = "John";
$nom_prenom = $nom . $prenom;
echo ( $nom_prenom ); // affiche: DoeJohn

Inclusion dans double quote version simple:

$nom = "Doe";
$prenom = "John";
$nom_prenom = "$nom $prenom";
echo ( $nom_prenom ); // affiche: Doe John

Inclusion dans double quote version avancée:

$nom = "Doe";
$prenom = "John";
$nom_prenom = "${nom} ${prenom}";
echo ( $nom_prenom ); // affiche: Doe John

Concaténation avec plusieurs chaines:

$nom = "Doe";
$prenom = "John";
$nom_prenom = $nom . "-". $prenom;
echo ( $nom_prenom ); // affiche: Doe-John

Opération de cherche et remplace successif:

$nom = "Doe";
$prenom = "John";
$nom_prenom = sprintf( "Votre nom: %s ,votre prenom: %s" , $nom , $prenom );
echo ( $nom_prenom ); // affiche: Votre nom:Doe , votre prenom: John

6. Sauvegarder vos tweets dans la base de données

Créer une nouvelle table tweet avec un champ ID de type INT auto incrémenté, un champ pour stocker la date et l’heure de création d’un tweet par exemple create_at avec comme type DATETIME, un champ pour stocker un nombre par exemple nbr_critere de type INT, un champ critere de type VARCHAR 150 caractères.

Modifier votre programme PHP qui accède à l’API twitter, compte le nombre de tweets sur un critère et stocke le nombre de tweets ayant le critère, le critère et la date de création dans Mysql.

Voici un morceau de code pour vous aider :

$query = sprintf("insert into tweet(create_at, nbr_critere, critere) values ( NOW() , %s , '%s' )"
         , $nbr , $critere ) ;
$result = mysqli_query( $link , $query);

 

Publié dans CTN | Laisser un commentaire

Debug WordPress avec Eclipse PDT

Objectif: configuration de wordpress opérationnelle avec un debug dans Eclipse PDT

Etape 1 : Configuration d’EasyPhp/Wamp/Mamp

Pour activer le debuggeur xdebug dans les outils de développement, la toute première étape est de localiser le « bon » fichier php.ini. En effet, votre ordinateur peut contenir plusieurs fichiers pour gérer la version de test et la version de production, un fichier en sauvegarde ou un fichier php.ini si vous écrivez du PHP en utilisation en mode CLI (CLI=client).

Etape 1.1: Localiser et Ouvrir le fichier php.ini

Créer un fichier phpinfo.php à la racine du DocumentRoot d’apache contenant le code suivant:

<?php phpinfo();

Ouvrir la page correspondante dans le navigateur via par exemple l’URL: http://127.0.0.1/phpinfo.php

Vous obtenez l’ensemble des réglages du PHP dans Apache et surtout le « bon » fichier php.ini:

Il faut ouvrir ce fichier pour vérifier/modifier/ajouter les lignes suivantes:

  • activer la ligne qui indique le xdebug, cette ligne ne doit pas commencer par un ; (qui indique un commentaire) mais par zend_extension
  • la ligne  zend_extension doit indiquer un fichier valide de xdebug par exemple:
    zend_extension= »c:/wamp/bin/php/php5.6.2/zend_ext/php_xdebug-2-5.6-vc11-x86_64.dll »
  • xdebug.remote_enable = on

La modification des lignes ci-dessus dans le fichier php.ini sauvegardé et le redémarrage d’Apache doit permettre d’activer le xdebug. Pour le vérifier, ouvrez de nouveau l’URL vers le fichier phpinfo.php. Vous trouverez normalement une indication que le xdebug est bien activité et que le mode remote debug est aussi actif :

Etape 1.2:Réglages d’Eclipse PDT pour xdebug

Il y a plusieurs moyens de modifier les réglages d’Eclipse PDT pour que l’IDE prenne en compte le xdebug comme débuggeur par défaut. Dans certaines versions d’Eclipse PDT, le débuggeur configuré est la version payant de Zend Debugger. Il suffit souvent de désactiver ce dernier au profit de xdebug pour que cela fonctionne correctement.

Faire Menu Windows > Preferences puis ouvrir PHP > Debug dans la fenêtre des préférences puis « l’hyperlien » PHP servers… pour éditer le serveur par défaut « Default PHP Web Server ». Dans la fenêtre « Edit Server », sélectionnez l’onglet « Debugger » pour enfin choisir comme Debugger: XDebug. Finish et OK pour valider les modifications.

Nota: il est possible de trouver la liste des serveurs via Menu Windows > Preferences puis ouvrir PHP > Servers mais je trouve pratique de consulter les réglages du débugger dans PHP > Debug.

Par défaut, le réglage du serveur web par défaut est d’utiliser xdebug.

Etape 2: Création d’un projet PHP pour WordPress dans Eclipse PDT

Après installation de WordPress dans le DocumentRoot d’Apache dans le sous dossier WordPress, nous allons créer un projet PHP portant le même nom pour récupérer les fichiers PHP de WordPress dans Eclipse:

Faire Menu File > New > PHP Project:

File-New-Php Project

Dans la fenêtre de création d’un nouveau projet « New PHP Project » indiquer le nom du projet WordPress et l’option « Create new project in workspace », on peut vérifier que le dossier indiquer par l’interface correspond bien au dossier de l’installation de WordPress:

New-Project

L’importation d’un grand nombres de fichiers de WordPress dasn Eclipse PDT peut prendre jusqu’à quelques dizaines de minutes selon la taille du WordPress et la puissance de votre ordinateur.

WordPress contient quelques pseudo « erreurs » mal détectées par Eclipse, même si le projet est indiqué avec une petite croix rouge, il peut parfaitement fonctionner.

Etape 3: Debug d’un projet PHP dans Eclipse PDT

Etape 3.1: Création d’une configuration de Debug

Pour débugger un projet PHP, il faut en premier lieu créer une configuration de Debug, via le Menu Run > Debug Configuration …

Ou via click droit sur un programme PHP > Debug As > Debug Configurations …

Dans la nouvelle fenêtre « Debug Configurations », on peut créer une nouvelle configuration de Debug via le bouton « New Debug Configuration », indiquer un nom (un label) à cette configuration et surtout le fichier à débugger:

PS : on peut noter l’URL qui est affichée dans le bas de l’interface avec l’option « Auto Generate », si on décoche cette option, on peut ainsi modifier une partie de l’URL.

On peut vérifier que le débugger par défaut pour cette configuration est bien indiqué dans l’onglet Debugger : 

On peut laisser un point d’arrêt automatique via l’option « Break at First Line » ou au contraire vouloir laisser l’option décoché pour utiliser d’autres points d’arrêt (voir plus bas).

Etape 3.2: Lancer le Debugger

Maintenant on peut lancer le « Debugger » avec le bouton « Debug » en bas à droite.
Ce qui devrait ouvrir l’URL dans un navigateur intégré à Eclipse PDT et nous proposer de basculer dans la perspective « Debug » d’Eclipse. Il faut confirmer en indiquant que l’on souhaite qu’Eclipse PDT se souvienne de cette réponse pour éviter d’avoir cette fenêtre à chaque fois.

Cela va ouvrir la perspective « Debug » pour Eclipse PDT. Une perspective est un nouvel agencement des différentes fenêtres d’Eclipse PDT. Cette nouvelle organisation doit mettre en avant ce qui est utile au Debug: les variables, quelques dizaines de lignes de codes, si le serveur Apache est en pause sur un fichier et à quel ligne et dans un coin le navigateur intégré d’Eclipse PDT:

Dans l’exemple ci-dessus, le debugger s’est automatiquement mis en pause sur la première ligne de PHP (cf le choix « Break at First Line » est actif dans la Configuration de Debug plus haut).

Pour contrôler l’exécution du programme PHP en mode debug, soit d’exécuter ligne par ligne le programme PHP, on peut utiliser la barre de menu suivante:

  1. Le bouton 1 permet d’activer/désactiver tous les points d’arrêts
  2. Le bouton 2 permet de faire exécuter toutes les lignes de PHP jusqu’au prochain point d’arrêt, si il n’y a plus de point d’arrêt exécute jusqu’à la fin le programme
  3. Le bouton 3 permet d’arrêt la session de debug sans obtenir de résultat
  4. Le bouton 4 permet de débugger en entrant dans les fonctions PHP
  5. Le bouton 5 permet de débugger en exécutant les fonctions PHP sans entrer dedans

Etape 3.3: Les points d’arrêts

Quand on debugger, ce qui est souvent utile  de faire exécuter le programme PHP depuis le début, autrement-dit depuis le lancement du programme PHP, jusqu’à un endroit critique du programme PHP.

On place donc habituellement un point d’arrêt sur une ligne de code juste avant l’ensemble des lignes qui sont à débugger.

La session de Débug démarre, puis on utilise le bouton 2 (Resume ou touche F8) qui déclenche l’exécution du programme PHP jusqu’au premier point d’arrêt. Puis arrivé sur les lignes de code problématiques, on utilise les boutons 4 (Step Into ou touche F5) et 5 (Step Over F6) pour exécuter ligne à ligne, un peu à la manière d’un ralenti.

Une fois les lignes problématiques passées, nous exécutons le reste du programme avec le bouton 2 (Resume ou touche F8) pour obtenir l’affichage de la page dans le navigateur.

Etape 3.4: Relancer le Debug

Une fois la session de debug terminée, on peut relancer le Debug via clic droit > Run As > PHP Web Application

Attention, Eclipse PDT n’accepte d’avoir qu’une seule session de debug, si votre session n’est pas terminée, vous pouvez l’arrêter via le bouton 3 (Terminate ou touche CTRL+F2).

On peut par contre debugger plusieurs pages dans la session de débug, en appelant de nouvelles pages sur le même projet PHP. On peut aussi utiliser un navigateur extérieur pour voir la session de Debug dans Firefox/Chrome ou tout autre navigateur.

Publié dans CTN | Laisser un commentaire

Tp2 Ema EMACS Développement Web

1/ Ajout d’une feuille de style

L’ajout d’une feuille de style permet de proposer une nouvelle mise en forme. Ajouter le fichier style.css contenant le code suivant dans le dossier css du dossier WebContent:

div#central{
  position:absolute;
  left: 50%;
  top: 10%;
  width: 800px;
  height: 800px;
  margin-top: -50px;
  margin-left: -400px;
  color: black;
  background-color:rgb(200,220,200);
  padding: 20px;
}
ul {
  list-style: none;
  margin: 0;
  padding: 4px 4px 4px 4px;
}
ul > li{
   display: inline;
}
div#menu{
  position:relative;
  left:10%;
  width:80%;
  background-color:rgb(200,240,220);
}

Il faut ajouter deux div dans la JSP avec comme « id » central et menu, le div « menu » doit être inclus dans central et appeler le fichier style.css dans le tag <head> :

<link rel="stylesheet" type="text/css" href="css/style.css">
<div id="central">
 <div id="menu">
      <!-- Zone pour le menu -->
 </div>

    <!-- Zone pour le contenu -->
</div>

 

La zone menu va utiliser une liste d’hyperlien pour présenter un menu (voir le site alsacreation pour les étapes de construction en CSS)

<ul><li><a href="#">Menu 1</a></li><li><a href="#">Menu 2</a></li></ul>

Modifier les marges et les couleurs à votre convenance.

Refaite une mise en forme de votre application, avec le framework Bootstrap CSS, en utilisant par exemple le jumbotron comme exemple: Jumbotron

2/ Utilisation des logs

Plutôt que de multiplies les sorties sur la console via des classiques:

System.out.println("Erreur " + e);

Il parait plus stable d’avoir sur un serveur Tomcat de multiples informations selon les applications et selon les besoins de ces applications. En production, les logs permettent de gérer les sorties d’informations de l’application en se limitant au maximum, au contraire en développement, on peut avoir besoin d’un niveau très important de détails des logs.

Nous allons exploiter une librairie de log qui s’appelle log4j disponible en version simple 1.2.17 ici. Vous pouvez télécharger ce jar et le placer dans un dossier lib dans le dossier WEB-INF du dossier WebContent.

Nota: vous pourrez mettre d’autres librairies .jar à déployer dans votre projet web dans ce dossier pour que chaque Application Web disposent de ses propres jars.

Nota 2:  Une autre option est d’utiliser le dossier lib dans le dossier tomcat pour indiquer les jars disponible pour tous les projets déployés.

Pour configurer le logger, on va créer un fichier log4j.properties dans le dossier Java Resources > src (il n’a pas à être dans un package ce n’est pas un fichier java juste un fichier de configuration). Pour créer un fichier texte, faire clic droit sur le dossier > New > Other …> General > Untitled Text File.

Entrez les informations suivantes dans le fichier et sauver le dans votre projet, dans le dossier src avec comme nom log4j.properties.

Le fichier log4j.properties doit contenir ces informations:

log4j.rootLogger=DEBUG,stdout,file

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n


log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/Developpement/workspace_jee/BoostrapSample/out.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n

La première ligne indique que le niveau de log est DEBUG et qu’il y a 2 loggers: stdout et file.

Les lignes commençant par log4j.appender.stdout indique les réglages pour le logger stdout soit une sortie d’information sur la console de l’ordinateur (là où va habituellement le System.out.println).

Les lignes commençant par log4j.appender.file indique les réglages pour le logger file soit une sortie dans un fichier. Il vous faut corriger mon exemple pour que le fichier puisse être créer dans le dossier qui correspond à votre workspace ( vous n’avez peut être pas de dossier: c:/Developpement/workspace_jee/BoostrapSample/ ).

L’instruction ConversionPattern indique la forme de la sortie:

La date: %d{ABSOLUTE}
Le niveau de log: %5p
Le nom du logger: %c{1}
La ligne du log: %L
Le message: %m

Vous pouvez trouver des exemples de pattern avec log4j

Pour utiliser le logger dans une classe, on va simplement créer une instance log de type org.apache.log4j.Logger:

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("BoostrapSample");

Nota: j’utilise le chemin absolut de la classe en spécifiant sont package devant (org.apache.log4j) car il existe d’autres solutions de log et Tomcat utilise d’ailleurs pour son utilisation interne org.apache.commons.logging. Il peut donc y avoir conflit entre les 2 systèmes de Log. Nous avons ici une démonstration de la force/faiblesse de Java qui va foisonner de solutions pour proposer une variété de réponses mais qui peut gêner par leur multiplicité.

Au moment où on veut logger une information, il suffit d’appeler l’instance avec le niveau de sévérité du message  et de passer en paramètre le message :

log.trace("Niveau le moins important");
log.debug("Niveau au dessus du moins important");
log.info("Niveau habituel de fonctionnement");
log.warm("Erreur non bloquante");
log.error("Niveau Erreur classique");
log.fatal("Niveau Erreur maximum");

Au final on peut utiliser qu’un nombre limité de niveaux d’erreurs ou au contraire ajouter ses propres niveaux. L’important est d’éviter de saturer d’erreurs le fichier de tomcat avec tout type de niveau d’erreur ou au contraire de trop filter l’affichage de potentiels problèmes mineurs.

C’est la première ligne du fichier log4j.properties qui indique le niveau d’erreur minimum que je filtre, avec le niveau DEBUG, log4j, va afficher les logs FATAL,ERROR,WARM, INFO et DEBUG.

log4j.rootLogger=DEBUG // affiche FATAL,ERROR,WARM, INFO et DEBUG
log4j.rootLogger=ERROR// affiche FATAL et ERROR

Je peux modifier le niveau de Log avec l’instruction suivante en cours d’exécution:

log.setLevel( org.apache.log4j.Level.INFO );

Ajouter un troisième logger en html en vous inspirant de ce code:

log4j.appender.html=org.apache.log4j.DailyRollingFileAppender
log4j.appender.html.DatePattern='.'yyyy-MM-dd-HH-mm
log4j.appender.html.layout=org.apache.log4j.HTMLLayout

Ce logger a plusieurs spécificités si vous lancer des logs en nombres. Consulter régulièrement le dossier où va être stocker vos logs et si vous utilisez Eclipse pour afficher le contenu de dossier, n’hésitez pas à faire rafraîchir le contenu du dossier.

Pour afficher les logs, j’utilise un plugin d’Eclipse qui s’appelle « Log Viewer« . Vous pouvez installer ce plugin en faisant  glisser-deposer le bouton « Install » dans Eclipse.

Vous pouvez ensuite mettre dans votre pesrpective Eclipse ce nouveau plugin via le menu Windows > Show View > Other… et chercher Log Viewer

Dans la fenêtre Log Viewer, on peut ensuite ouvrir différents fichier de log, régler la coloration des logs, rafraichir l’affichage, etc.

En premier lieu, il faut ouvrir le fichier des logs créé avec le bouton Open Logfile:

log-viewer-open-file .

Ensuite, on peut indiquer les règles que l’on veut appliquer au Log Viewer via le bouton Show rules preferences:

log-viewer-rules

La liste des règles peut être modifiée pour mettre en surbrillance différentes lignes des logs selon un critère de recherche:

Log-viewer-preferences

 

3/ Classe Helper

Une classe Helper permet de stocker des méthodes utilitaires pour la classe dont elle porte le nom.

Par exemple, nous allons ajouter une classe ControleurHelper qui va nous permettre de réaliser le log des paramètres passés au Controleur.

private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger( "Emacs2016" );

public static void logAllParameters(HttpServletRequest request){

 Map<String, String[]> parameters = request.getParameterMap();
 
 for(String parameter : parameters.keySet()) { 
    String[] values = parameters.get(parameter);

    String value = Arrays.stream( values ).collect(Collectors.joining(","));

    log.info( "Parametre " + parameter + " " + value ); 
 }

}

Cet exemple utilise une fonctionnalité avancée du Java 8+ appelée stream. Cette fonctionnalité est à couplé avec un appel de méthode inline pour par exemple filtrer les informations.

Par exemple, si on souhaite traiter la liste des Todos comme un stream pour extraire le texte des Todos actifs uniquement.

Nous partons d’une liste de Todos que nous convertissons en stream

lesTodos.stream()

Maintenant nous allons utiliser une méthode filter pour n’utiliser que les Todos actif, nous pourrions passer une méthode qui donne la raison de la comparaison à la méthode filter. C’est l’opérateur -> qui indique à gauche quel est le nom paramètre sur chaque élément du stream que nous allons exploiter et à droite de l’opérateur l’action à réaliser.

todo -> todo.isActif()

est à mettre en parallèle à la création d’une classe anonyme avec une méthode qui est automatiquement appelé

Class anonyme{
    public static boolean méthode_appelé_automatiquement(Todo todo){
        return todo.isActif();
    }
}

Cela suppose un peu de code pour une méthode qui au final ne va pas être énormément exploitée. D’où l’utilisation des appels inline plus simple à écrire:

lesTodos.stream().filter( todo -> todo.isActif())

L’idée derrière les streams qui est utilisées dans le traitement de données de type fouille de données et Big Data et de pouvoir chaîner les opérations pour permettre à la JVM d’exploiter les multiples processeurs en parallélisant les actions.

Nous allons ensuite recupérer le résultat du filtrage et indiquer quel partie du Todo nous voulons extraire le texte du todo:

lesTodos.stream().filter( todo -> todo.isActif()).map( todo -> todo.getTexte() )

Nous pouvons maintenant exploiter la méthode collect pour fusionner les données en les contenants avec un séparateur et en transformant le résultat en String:

String reponse = lesTodos.stream().filter( todo -> todo.isActif()).map( todo -> todo.getTexte() ).collect(Collectors.joining(","));

Vous trouverez sur le web énormément d’exemple sur l’utilisation des streams qui sont en train de devenir très performant pour l’exploitation de données en parallèle (voir l’exemple de la somme d’entier en stream sur le site d’Oracle).

 

4/ Ajout de la partie Base de données

Pour exploiter la base de données, nous devons ajouter un connecteur JDBC pour que notre code Java puisse se connecter s’y connecter.

Si on a une base de données Mysql, il faut le connecteur Mysql, nous allons exploiter par contre une base de données Sqlite. Pour cela, il faut ajouter le fichier sqlite-jdbc-3.8.11.2.jar accessible sur cette adresse dans le dossier lib dans le dossier WEB-INF du dossier WebContent.

Vous pouvez vous inspirer de la classe DaoManager pour réaliser votre propre classe qui doit gérer la connexion et les opérations de manipulation de la base de données.

Le fichier contenant la base de données s’appelle todo.db, ce dernier se trouve par défaut dans le dossier eclipse. On peut l’ouvrir avec le plugin SQLite Manager dans Firefox.

Vérifier que votre application peut ajouter  des Todos dans la base de données et que vous pouvez recharger la liste des Todos depuis cette dernière.

Il faut ensuite faire évoluer votre application en intégrant un identifiant numérique id produit par la base de données. Normalement, le DAOManager a créer une colonne auto incrémenté pour les Todos, cette information est à retrouver avec une séries d’instructions qui commencent par:

ResultSet rs=preparedStatment.getGeneratedKeys();

 

 

Publié dans Emacs | Laisser un commentaire

Tp1 Ema EMACS Développement Web

1/ Description de l’application

Notre première application Web a pour objectif de gérer une liste de choses à faire par exemple une liste de courses (des todo):

On ne pourra avoir deux fois un « todo » avec le même texte par exemple impossible d’ajouter encore « chocolat » à la liste. Il n’y aura pas d’erreur mais l’élément ne sera pas ajouté une seconde fois.

Pour la partie métier/modèle qui est extrêmement simplifié pour permettre de se focaliser sur la partie Web.

Diagramme de classe simplifié :

Pour la gestion d’une seule et unique instance d’application, nous allons utiliser le Design Pattern Singleton:

public class Application {
   private static Application instance = null;
   
   public static Application getInstance() {
      if (instance == null) {
           instance = new Application ();
      }
      return instance;
     }

  private Application() {
    // initialisation de la liste 
  }

}

Comment instancier une application sachant que le constructeur est privé ?

Nous allons utiliser l’interface List pour gérer la liste lesTodos qui seront de nature ArrayList<Todo>.

Un interface est une liste de nom de méthode que doit avoir un classe instanciable pour être facilement remplaçable par une évolution. On pourra par exemple dans une évolution de notre application en exploitant une classe instanciable LinkedList ou un résultat d’un stream.

2/ Création du projet et de la partie métier

Faire un nouveau « Dynamic Web Project » ( File > New > Dynamic Web project )

Les codes de la partie métiers ne doivent pas être directement dans le dossier « Java Ressources > src » mais dans un package metier ou model (clic droit sur le dossier src > New > Package)

Préparez aussi des packages controleur et test pour la suite des TPs.

Codez les deux classes du diagramme UML ci-dessus et les méthodes nécessaires au fonctionnement (clic droit sur le package metier > New > Class)

Vous pouvez vous aider de la génération des méthodes get et set avec clic droit sur le code de la classe > Source > Generate Getters and Setters…

 

Profitez-en pour générer les méthodes hashCode() et equals() dans le même menu, en utilisant le champ « texte ».
Essayer de comprendre à quoi peuvent servir ces 2 méthodes sachant.

Créer dans Application, une méthode main pour exécution en mode Java classique et utiliser cette méthode pour créer une application

public static void main(String[] args){

}

Coder les méthodes de la classe Application qui permettent de manipuler la liste lesTodos

3/ Tests unitaires

Nous allons produire différents tests unitaires pour vérifier que les classes suivent quelques règles.

Sur le package test, faire clic droit > New > Other > Junit Test Case puis remplir l’interface comme la capture d’écran ci-dessous :

J’indique que je veux dans le dossier src de mon application, dans le package test créer une classe de test TodoTest qui va tester la classe metier.Todo puis faire « Next ».

Dans la fenêtre suivante, j’indique la liste des méthodes que je souhaite tester:

Dans notre cas, on souhaite tester les méthodes de la classe Todo qui sont sélectionné. Il peut paraître peut utile de tester les classes parentes comme Object.

Voici un extrait en exemple de code pour le test unitaire de la classe Todo.
Essayez de coder quelques tests pertinents et exécutez les via clic droit sur le projet > Run As > Junit Test

public class TodoTest {

  @Test
  public final void testTodo() {
     Todo todo = new Todo("du lait" , false);
     assertNotNull( todo );
  }

@Test
public final void testGetTexte() {
   Todo todo = new Todo("du lait" , false);
   assertEquals ( todo.getTexte() , "du lait");
}

@Test
public final void testIsActif() {
   Todo todo = new Todo("du lait" , false);
   assertFalse( todo.isActif());
}

}

Autant les tests sur la classe Todo (un POJO) sont très basiques autant les tests unitaires sur la classe Application sont plus pertinent.

On peut ainsi tester que le Singleton n’est jamais null, que la liste des Todo est vide au démarrage, que l’ajout d’un Todo nous permet ensuite de le retrouver, etc…

Coder un test unitaire pour vérifier que l’on ne peut avoir qu’un seul Todo avec le texte « chocolat » dans la liste.

A chaque fois que vous développerez une méthode importante, pensez à coder le test unitaire et à relancer la batterie de test pour vérifier la non régression de votre application.

Refaite une classe de Test sur Application en cochant les méthodes: setUpBeforeClass, tearDownAfterClass, setUp, tearDown:

Coder dans chacune de ces méthodes un affichage d’information. Par exemple pour tearDown:

System.out.println( "teardDown" );

Mettez un point d’arrêt sur TearDown et lancer le test en mode Debug, via Clic droit sur le code source > Debug As > Junit Test

A quoi peut bien servir ces 4 méthodes: setUpBeforeClass, tearDownAfterClass, setUp, tearDown ?

 

4/ Liaison entre la partie métier et une JSP

Faite une JSP de test pour l’affichage de 4 todos :


Voici un exemple de code pour créer Application (noter que la construction de la liste est faite dans le constructeur) :

private Application() {
     lesTodos = new ArrayList<Todo>();
     create4TestTodos();
 }
 private void create4TestTodos(){
     addTodo( "Test1 " , false );
     addTodo( "Test2 " , false );
     addTodo( "Test1actif " , true );
     addTodo( "Test2actif " , true );
 }

 

Créer une JSP et importer les classes métier dans cette dernière, habituellement en tête de page:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="fr.ema.lgi2p.emacs.metier.*" %>
Parcours de la liste des Todos de type « foreach » :
<%
for(Todo todo : Application.getInstance().getLesTodos() ){
%>
<p>
   <%=todo.getTexte() %>
</p>
<%
}
%>

Cet affichage est statique, cela nous permet juste d’afficher depuis la partie Métier les données dans une JSP qui symbolise la partie Vue.

5/ La Servlet comme partie Controleur

Notre contrôleur va utiliser la technologie de Servet pour recevoir les données (Menu clic droit > New > Servlet ). La servlet devra être dans un package controleur.

 

Attention ne mapper pas *.jsp

 

Nous allons créer une Servlet de la classe Controleur qui répond à une liste d’URL, dans notre cas /Controleur.

L’URL Mapping permet de faire la liaison entre l’URL http://127.0.0.1:8080/Controleur et la servlet appelée (Nota : je ne recommande pas de mapper *.jsp en développement mais uniquement en production).

 

Développez votre contrôleur en vous inspirant de cet exemple :

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

String vueFinale = "index.jsp";

// Actions du controleur pour calculer la vueFinale
     
request.getRequestDispatcher(vueFinale).forward(request, response);

}

Le but de la variable « vueFinale » est de contenir le nom de la JSP qui va être appelé par la commande getRequestDispatcher.

Si une opération, par exemple addTodo ne fonctionne pas, alors la vueFinale sera par exemple « erreur.jsp » et c’est cette vue (JSP) qui sera affichée alors.

Dans le controleur, nous allons coder une méthode doAction qui va prendre des paramètres de la requête HTTP Get ou Post et notamment un paramètre action qui va permettre d’appeler les méthodes des la partie Modèle et de fabriquer cette fameuse vueFinale:

private String doAction(HttpServletRequest request) {

String vueFinale = "erreur.jsp";

String action = request.getParameter("action");

// Action1 addTodo
if ("addTodo".equals(action)) {

    String texte = request.getParameter("todo_texte");
    Application.getInstance().addTodo(texte, false);

    vueFinale = "index.jsp";
}

// Action2  ...


// ... 
return vueFinale;
}

 

Développer une JSP pour présenter cette vue:

Ajouter un formulaire pour mettre à jours la ou les cases( checkbox) sélectionnées.

Les listes en HTML se basent sur les tags suivants:

<ul>
<li> chocolat</li>
<li> bonbons</li>
</ul>

 

6/ Ajout d’une nouvelle action

Si le paramètre « action » de l’URL contient le mot xml, il faut alors appeler une nouvelle JSP qui va fabriquer un fichier XML qui aura cette forme:

<?xml version="1.0" encoding="utf-8"?>
<todos>
<todo id="1" texte="a faire" actif="false" />
<todo id="2" texte="a ne pas faire" actif="true" />
<todo id="3" texte="surtout a faire" actif="false" />
</todos>

Bien sur ces données doivent être extraites de la liste des Todos de la partie Modèle.

Si le paramètre « action » de l’URL contient le mot json, il faut extraire les données dans un autre format, le format JSOn qui est une autre façon moins verbeuse de présenter de l’information:

{
 "todos":
 [
    {
      "id": "1",
      "texte": "a faire",
      "actif": "false"
    },
    {
       "id": "2",
       "texte": "a ne pas faire",
       "actif": "true"
    },
    {
      "id": "3",
      "texte": "surtout a faire",
      "actif": "false"
    }
  ]
}

Ce format est prévu pour un échange entre le code javascript et le serveur web et non pour être consulté par des internautes.

Vous pouvez vérifier que votre fichier est JSOn via un visualisteur en ligne tel que: Online JSON Viewer.

 

 

 

 

 

 

 

 

 

 

 

 

Publié dans Emacs | Laisser un commentaire

TP Emacs 0

Les cours de technologie Web EMACS est disponible en téléchargement ici.

Les outils de développement (Eclipse J2EE et tomcat 7) sont disponibles selon l’OS de votre poste à cette adresse 146.19.252.215/Emacs/. Ce sont des anciennes versions mais vu le peu d’évolution des deux logiciels, il n’y a pas beaucoup de différence avec les versions actuelles.

Je ne peux que vous recommander l’utilisation des outils de développement de Chrome (CTRL+MAJ+I) ou de Firefox (CTRL+MAJ+Q) surtout l’onglet « Réseau/Network » et le clic droit sur une page web > « Inspecter » et « Source de la page/Code source de la page ».


TP 0 Configuration et installation de Tomcat avec Eclipse J2EE  à adapter selon votre OS et votre configuration personnelle

  1. Installation d’un JDK récent version Oracle: télécharge par exemple JDK 8uXXX en version sans exemple ou netbeans. Notez le dossier où se trouve votre JDK, attention en cas de mise à jours du JDK, le dossier peut changer…
  2. Installation d’Eclipse J2EE depuis 146.19.252.215/Emacs/ dans un dossier dont le chemin ne comporte pas d’espace et d’accents par exemple sur le bureau dans un dossier Developpement.
    NOTA: Windows 7/8/10 contrôle de manière très précautionneuse les fichiers se trouvant dans les dossiers Programmes, Program Files (x86), Windows et tout dossier à la racine du disque C. Il est préférable d’avoir un dossier Developpement à la racine du disque dur dans lequel on place les outils de développement.
  3. Démarrer Eclipse J2EE pour vérifier que le JDK a bien été trouvé car Eclipse utilise Java pour s’exécuter. A l’exécution d’Eclipse, un workspace est demandé pour stocker tous les configurations d’Eclipse et les projets Java Web. Merci de faire attention que le chemin de ce workspace ne contienne pas d’espace ou d’accents. Je vous conseille par exemple c:/Developpement/workspace_j2ee par exemple.
    NOTA: si vous voulez changer de workspace, faire dans Eclipse menu « File » > « Switch Workspace »
  4. Téléchargement d’une version de Tomcat 7.0.67 et la dézipper dans votre dossier Developpement par exemple dans C:/Developpement/apache-tomcat-7.0.67/. Attention à ne pas avoir tomcat dans un sous dossier d’apache-tomcat-7.0.67.
  5. Configuration d’un JDK par défaut et non d’un JRE. Eclipse J2EE utilise un Java JDK ou JRE pour s’exécuter. Il peut gérer aussi plusieurs JRE/JDK selon vos besoins de configuration. Pour simplifier nos développement, nous allons indiqué un unique JDK auprès d’Eclipse pour éviter les conflits et les erreurs.
    1. Menu « Windows » > « Preferences » > « Java » > « Installed JREs »
    2. Bouton Add pour ajouter une  » Standard VM « dont le JRE Home et le dossier localisé dans l’étape 1 avec l’installation du JDK.
    3. Rendre le JDK par défaut et effacer l’ancien JRE
      eclipse_preference_jre
       Un seul JDK ici en version jdk1.7.0_17 pour éviter les problèmes d’en avoir plusieurs et de ne plus savoir lequel est activé par défaut. Eclipse permet de jongler entre plusieurs perspectives qui sont affichées en haut à droite dans un sorte d’onglet. Dans la version xubuntu il s’agit d’un JDK 8.
  1. Pour ouvrir une nouvelle perspective, faire
    Menu « Window » > « Open Perspective » > « Other »
    Les perspectives que l’on va utiliser sont Java EE et Debug, il faut afficher la perspective Java J2EE et dans cette perspective, activer l’onglet server (voir l’image)
    eclipse_perspective-server
  2. Menu File > New > Other > Server > Server > Next > Apache > Tomcat v7.0 Server. Il faut indiquer le  » Tomcat Installation Directory » c:/Developpement/apache-tomcat-7.0.67/ puis Finish. Le JRE à indiquer est celui qui a été configuré à l’étape 6 (il s’agit donc un JDK et non un JRE)
  3. Dans l’onglet « Server  » faire clic droit sur le serveur nouvellement créé, puis choisir Debug
    eclipse-debug-server
  4.  L’onglet « Console  » doit afficher les traces du serveur Tomcat. Ouvrez un navigateur et indiquez cette URL (Le port par défaut de tomcat est 8080) http://127.0.0.1:8080/
  5. Dans Eclipse, faire un nouveau projet File > New > Other > Web > Dynamic Web Project
  6. Il faut indiquer un nom de projet par exemple  » Essai  » puis Finish
  7. Il faut ensuite placer une image PNG ou JPG dans le dossier « WebContent » du projet Essai
  8. Trouver l’URL pour accéder à cette image par le navigateur puis déplacer cette image dans un sous dossier img dans WebContent
  9. Ensuite, télécharger une page HTML et CSS par exemple depuis cet exemple du CSS Zen Garden.
  10. Vous pouvez copier coller le fichier Html et CSS depuis votre dossier téléchargement dans Eclipse en faisant glisser les fichiers dans le dossier WebContent.
  11. Vérifier que cette page s’affiche correctement en vérifiant les URLs via les outils de développement dans le navigateur: 
  12. Il faut fabriquer ensuite une page index.jsp dans le dossier WebContent avec le code ci-dessous par exemple:code-index.jsp
  13. Pour lancer le Debug, après avoir placé un point d’arrêt, il faut faire un clic droit sur ce code puis Debug As > Debug on Server ( on peut cocher « Always use this server when running this project » pour éviter cette étape):
    eclipse--clic-droit-debugeclipse-debug-choix-server
  14. Bouton Next pour ajouter le projet dans la liste à droite des projets déployés sur ce tomcat. Puis bouton « Finish » pour lancer le debuggage pas à pas.
  15. Pour plus de détail sur le Debug voir cet article spécifique : (Eclipse débogage et points d’arrêts)
  16. Essayez d’inclure différents contenu comme des images et du Css avec la page jsp en mettant ces images et un fichier css dans des dossiers séparés dans le dossier WebContent.
Publié dans Emacs | Laisser un commentaire

Typescript avec Vim sur Windows Seven

Le développement avec Typescript propose une solution d’intégration avec un grand nombre d’IDE (Eclipse, Atom, Visual Studio, etc.).

Pour l’administration système et pour le traitement de très gros fichiers texte, j’utilise VI ou VIM depuis très longtemps. Du coup, j’ai testé l’installation d’outil de coloration syntaxique et d’auto-complétion pour Typescript dans VIM.

Coloration syntaxique

En premier, il faut télécharger la coloration syntaxique depuis ce blog, dézipper le contenu pour copier le fichier typescript.vim dans le dossier des syntaxes de VIM soit dans mon cas : C:\Program Files (x86)\Vim\vimfiles\syntax\

Pour activer la reconnaissance de la syntaxe, il faut créer un fichier typescript.vim dans le dossier suivant: C:\Program Files (x86)\Vim\vimfiles\ftdetect\ contenant l’instruction d’association de l’extension .ts avec le type typescript:

au BufRead,BufNewFile *.ts set filetype=typescript

 Installation d’un gestion de plugins dans VIM

Je ne me doutais pas que VIM avait des installateurs de plugins; habituellement je me contentais de copier des fichiers pour activer une fonctionnalité. Au final, on trouve des évolutions dans VIM de manière tout à fait similaire à tous les autres IDEs.

Donc j’ai installé le plugin gérant les plugins vim-plug.

Il faut copier le fichier plug.vim en provenance du site GitHub  dans le dossier C:\Program Files (x86)\Vim\vim80\autoload\.

Pour activer l’installation d’un plugin il faut éditer le fichier C:\Program Files (x86)\Vim\_vimrc en ajoutant les lignes suivantes

call plug#begin('C:/Developpement/vim/plugged')

call plug#end()

Le dossier C:\Developpement\vim\plugged\ contiendra les plugins installés dans la suite.

Installation de Tsuquyomi en attente

Ce plugin permet de réaliser l’auto-complétion mais son installation suppose des pré-requis: les installations de Node.js, Typescript et Shougo/vimproc.vim.

Node.js

L’installation de node.js se fait assez simplement sous windows via le téléchargement de l’installeur windows via https://nodejs.org/en/download/.

Typescript

L’installation se fait tout aussi simplement pour Typescript via la commande suivante à exécuter dans le dossier où on veut avoir Typescript (dans mon cas dans c:\Developpement\typescript\)

npm install --prefix . -g typescript

Vimproc

L’installation de vimproc va s’appuyer sur le gestionnaire de plugin. Dans le fichier C:\Program Files (x86)\Vim\_vimrc il faut demander l’installation et la compilation de vimproc pour fabriquer la DLL vimproc.dll. L’ajout du Plugin se fait avec la ligne Plug à ajouter entre le plug#begin et le plug#end

call plug#begin('C:/Developpement/vim/plugged')

Plug 'Shougo/vimproc.vim', {'do' : 'mingw32-make'}

call plug#end()

Il faut disposer d’un compilateur gcc par exemple MinGw et indiquer dans la variable d’environnement PATH le chemin vers le dossier bin (dans mon cas C:\Developpement\MinGW\bin)

Ouvrir vim et taper la commande pour installer les plugins et la compilation via mingw32-make (qui est dans la variable d’environnement %PATH%) car c’est VIM qui va exécuter la commande de compilation.

:PlugInstall

Voici la fin de la compilation du nouveau plugin:

Installation de Tsuquyomi enfin

Il faut réouvrir le fichier C:\Program Files (x86)\Vim\_vimrc pour ajouter à la ligne d’installation de vimproc.vim une installation en plus de tsuquyomi:

call plug#begin('C:/Developpement/vim/plugged')

Plug 'Shougo/vimproc.vim', {'do' : 'mingw32-make'} | Plug 'Quramy/tsuquyomi'

call plug#end()

Un rappel de nouveau à la commande :PlugInstall pour installer le dernier plugin.

L’ajout du nouveau plugin se passe correctement mais à l’ouverture d’un fichier typescript test.ts…

Problème rencontré

La compilation a réalisé la création d’une dll vimproc_win64.dll, cette dernière est pour windows 7 x64 hors mon VIM est en version x32 d’où incompatibilité:

La compilation à la main via la commande suivante dans le dossier C:\Developpement\vim\plugged\vimproc.vim\ devrait fabriquer la dll correcte:

mingw32-make -f make_mingw32.mak

Cette commande fabrique correctement la dll dans le même dossier que la version x64:

C:\Developpement\vim\plugged\vimproc.vim\lib\winproc_win32.dll

Enfin

L’ouverture d’un fichier test.ts associé avec gvim avec la commande Control+x Control+o permet d’obtenir l’auto-complétion dans VIM selon typescript:

Il ne me reste qu’à rajouter dans le fichier C:\Program Files (x86)\Vim\_vimrc les derniers réglages pour avoir une complétion plus détaillé en ajoutant ces lignes:

let g:tsuquyomi_completion_detail = 1
autocmd FileType typescript setlocal completeopt+=menu,preview

Maintenant, je vais pouvoir commencer à utiliser angular.j version 2 qui se base sur typescript en utilisant ce bon vieux VIM qui rend encore énormément de service.

 

SourceMap

Comme on a le fichier typescript.ts qui est compilé en typescript.js, il peut être difficile dans les debuggers intégrés des navigateurs de trouver la correspondance entre le code .ts et l’exécution en javascript .js.

Bien entendu, les développeurs de typescript (et d’autres surcouche/framework javascript) on trouvé une solution qui est de réaliser une correspondance entre les 2 qui s’appelle SourceMap.

Pour utiliser la sourceMap, il faut en premier lieu l’activer dans le navigateur, par exemple. Dans Chrome, il faut ouvrir les outils de développement (CTRL+SHIFT+I) puis F1 pour avoir les préférences et on peut alors activer les sourcesMap:

Pour Firebug, l’intégration est en cours dans la version 3.0.

Pour Firefox, il semblerait que l’option est activé par défaut:

Au boulot…

 

Publié dans Blog, Développement | Laisser un commentaire

TP3 – Technologies Web

Compteur de nombre de tweets

Bien que des solutions via les API existent, nous allons faire afficher le nombre de tweets parlant du sujet Master CTN.

Si je vous donne comme indication que l’on peut créer une variable PHP via la ligne suivante:

$nombreTweetMasterCTN = 0;

Et que l’on peut la faire augmenter de 1 à chaque fois qu’il y a cette ligne PHP dans le code:

$nombreTweetMasterCTN = $nombreTweetMasterCTN + 1;

Essayer de lister sur une feuille de papier ce que devrait faire l’algorithme comme enchaînement d’instructions:

  1. Créer la variable contenant le nombre de tweet en l’initialisant à zéro
  2. Récupérer successivement chaque tweet
  3. …. étape suivante à compléter….
  4. …. étape suivante à compléter….
  5. …. étape suivante à compléter….

Nota : le nombre d’étape de l’algorithme est purement informatif, il peut y en avoir plus ou moins selon votre niveau de détail.

Affichez un div avec une couleur de fond rouge dont la largeur va dépendre du nombre de tweet (multiplié par 10 ainsi 1 tweet aura un div de largeur 10px, 2 tweets auront un div de largeur 20px, etc.)

Par exemple voici un exemple de div avec une largeur de 50px pour symboliser que j’ai trouvé 5 tweets:

<div style="background-color:red; height:100px; width:50px; "/>
 5 tweets
</div>
 5 tweets

Création d’un formulaire dans la page

Notre objectif dans cette nouvelle page est de proposer un champ de formulaire pour que l’internaute puisse choisir le sujet au lieu de ne chercher qu’à suivre le sujet Master CTN.

Fabriquez une nouvelle page formulaire.html  qui doit contenir un formulaire et un champ de formulaire dont le name est sujet. Vous pouvez consulter le cours pour disposer des tags que composent le formulaire HTML.

Nota: Le formulaire doit aussi avoir un bouton submit et il doit appeler par l’attribut action la page client-twitter.php.

Remarque: wordpress remplace automatiquement les doubles quotes (en VF le guillement) par un guillemet typographique. Il faut lire donc lire:

$_REQUEST["sujet"]

et non pas

$_REQUEST[« sujet »]

Comment faire pour afficher dans la page client-twitter.php la variable $_REQUEST[« sujet »] après avoir rempli le champs de formulaire et appuyer sur le bouton submit de ce dernier?

S’il n’y a pas de variable $_REQUEST[« sujet »], vous devriez avoir ce message d’information (Notice) :

notice-undefined

La fonction isset( $_REQUEST[« sujet »] permet de tester si $_REQUEST[« sujet »] existe, essayez de créer une variable $sujet qui contient soit la valeur de $_REQUEST[« sujet »] si elle est définie (« is set » en anglais = isset) sinon une valeur autre par exemple « CTN ».

Pour cela, regarder comment on peut utiliser l’instruction if dans le Memento PHP.

Cette page PHP devrait pouvoir afficher le sujet que l’internaute souhaite chercher dans les tweets, le nombre de tweets et le div de largeur variable en fonction de ce nombre trouvé.

Publié dans CTN | Laisser un commentaire