nyroBlog
Bannière NyroBlog, par DëuG
Image par DëuG - ?

Catégorie : Programmation


jQuery : coup de boost dans le développement

J'en parlai dans mon dernier billet, jQuery UI ne se développait pas ou on entendait pas du tout parler...

Cela va changer puisque le développeur principal de jQuery, Paul Bakaus, vient de se faire embaucher par Liferay pour développer jQuey UI et plus généralement jQuery afin d'utiliser cette librairie dans les produits qu'ils vendent.

Donc il va bien y avoir une personne qui va travailler à temps plein sur jQuery, de quoi avancer le projet à grands pas !

Plus qu'à attendre les premiers résultats de cette nouvelle.

MySQL : Multiples tris et sous-requêtes

Un petit truc en MySQL qui j'en suis sûr servira à plus d'un.

Pour California Apparel News, cela fait plusieurs fois que j'utilise cette technique qui marche à merveille.

Le problème est le suivant : Comment récupérer les 10 derniers ajouts d'une table mais triés par ordre alphabétique ?

La solution qui vient tout de suite à l'esprit est :

SELECT * FROM table ORDER BY date DESC, titre ASC LIMIT 0,10

On récupère bien les 10 derniers résultats, mais ils ne sont en aucun cas triés par ordre alphabétique. En effet, le tri se fait d'abord sur la date dans l'ordre décroissant, puis sur le titre. Le tri sur le titre ne sera effectif que si on a des éléments à la même date. Un exemple de ce qui pourrait sortir de cette requête est :

  • 11/01/2008 - Il fait beau à Los Angeles
  • 09/01/2008 - Nuageux mais pas froid à LA
  • 03/01/2008 - Il pleut à Los Angeles
  • 03/01/2008 - Tempête sur Los Angeles

(Bon que 4 résultats, je ne me souviens pas d'autres choses niveau météo ici)

On a les bons résultats, mais pas triés correctement. Alors c'est sûr, on pourrait écrire une fonction PHP pour trier les résultats et c'est bouclé. Mais une fonction de tri n'est jamais évidente à écrire et trier dès la requête augmentera les performances.

La solution est d'utiliser une sous-requête dans la clause FORM; la sous-requête récupèrera les 10 derniers résultats, la requête principal les triera par ordre alphabétique. La requête complète :

SELECT * FROM (SELECT * FROM table ORDER BY date DESC LIMIT 0,10) AS subSelect ORDER BY titre ASC

Noter le AS subSelect qui est indispensable, comme indiquée dans la doc.

Le résultat sera :

  • 11/01/2008 - Il fait beau à Los Angeles
  • 03/01/2008 - Il pleut à Los Angeles
  • 09/01/2008 - Nuageux mais pas froid à LA
  • 03/01/2008 - Tempête sur Los Angeles

La différence entre les 2 résultats est minime, mais vous avez compris !

Nous voilà donc avec nos résultats tout bien trié comme on le voulait !

J'ai utilisé ça à 2 endroits :

En espérant que vous aurez l'occasion d'utiliser cette petite technique qui gagne du temps.

PHP, mes lectures du moment

Comme il m'arrive d'avoir du temps libre pendant mon stage, j'en profite pour lire de nombreux articles sur la programmation objet en PHP, la conception de sites, framework ou applications web.

Je vais donc vous faire une petite liste des plus intéressants. Beaucoup d'articles datent de 2004 ou même avant. La plupart sont en PHP 4, il faut donc savoir ce que l'on peut maintenant faire de mieux grâce à PHP 5 et son nouveau modèle objet.

Pour commencer, un petit tour sur la doc officielle et son paragraphe sur le langage objet en PHP 5. La lecture complète de ce paragraphe est plus qu'instructive, et changera sans doute votre vision des objets PHP.
La partie sur la surchage est très intéressantes, pour pouvoir faire des choses du genre $objet->variable = 'chouette';, où variable n'existe pas réellement en tant que propriétés de l'objet. La même chose est possible avec les appels de fonctions.
La petite page sur Réflexion et ses différentes classes/interfaces est tout aussi intéressante pour qui veut faire des instanciations et appels de méthodes dynamiquement et proprement.
Enfin, la minuscule page sur les masques introduit ce qui suit.

Qu'est-ce qu'un masque (ou design pattern ou patron de conception) ?
Wikipédia nous répond très simplement :

Un patron de conception est un concept destiné à résoudre les problèmes récurrents suivant le paradigme objet.

En lisant cet article, une fièvre studieuse est montée en moi pour lire tous les articles sur chaque patron de conception. Certains sont très peu explicites, il faut donc se creuser un peu la tête pour en voir l'application ou l'implémentation quand elle n'est pas donnée. Parfois, il est plus facile de lire le code et le comprendre, puis de remonter à la description pour comprendre à quoi cela sert vraiment. L'idée ici n'est pas d'utiliser tous ces patrons de conception, mais c'est d'en connaître leur existence et leur fonctionnement. Plus tard, si vous vous retrouver face à un problème susceptible d'être résolu par l'un de ces design pattern vous vous en souviendrez et vous pourrez l'appliquer rapidement, puisque vous l'aurez compris.

Ensuite, je me suis mis en tête de lire sur les différentes implémentations de ces patrons de conception PHP. C'est là que les vieux articles entre en jeux.
Le plus important est PHP Patterns, dont le dernier article date de 2005, mais dont la pertinence des articles et les exemples simples en font selon moi une référence. La partie la plus intéressante se trouve dans la partie design. Lisez-donc un maximum d'article en gardant à l'esprit que c'est du PHP4, et qu'il faudra donc repasser ça à la sauce PHP 5 à grands coups d'abstract, interfaces et autres...

Et puis avec ces lectures, j'atteri sur ce post à propos de Smarty et des moteurs de templates, de 2001 mais qui garde tout son sens encore maintenant. La plupart des arguments sont pertinents, quelques-uns un peu moins... Et puis là où ça devient encore plus intéressant, au délà de la discussion, c'est sur cette page où la personne donne un exemple utlra-léger mais ultra-fonctionnel d'un moteur de templates.

Et puis d'autres liens, donnés en vrac :

Enfin, une liste de framework, tous ayant des points de vues différents et des philosophies différentes. Les regarder et se plonger un peu dans le code de chacun est long est fastidieux, mais croyez-moi, très instructif !

Et plein d'autres sur Wikipédia fr et un joli comparatif sur la version anglaise.

La branche des développeurs d'IBM a posté un premier billet sur un comparatif détaillé des 3 premiers cités ci-dessus, à suivre.

Voilà, bonne lecture à tous, et si vous en avez d'autres sous le coude, n'hésitez pas à les mettre en commentaires ici.

Scriptaculous : Callbacks de l'effet Shake.

Comme j'ai oublié mes photos de ce week-end (à Beverly Hills), un petit poste programmation.

Je m'amuse avec Scriptaculous pour faire des retours d'informations intéressants aux utilisateurs. Durant mes tests, je me suis rendu compte que les callback que je donnai à l'effet Shake n'était jamais exécuter.

Un petit tour dans le fichier effects.js et je me rends compte que rien n'est fait pour le faire. En effet, l'effet Shake est simplement une combinaison de 6 effets Move les uns après les autres, dans des sens différents. Et les options de callback données à l'effet Shake ne sont pas retranscrit à chacun d'entre eux.

Qu'à cela ne tienne, voici le bout de code permettant de palier à ça (dont la modification de ce fameux effet) :

Effect.combinedOptions = function(options) {	
	var ret = {
		start:{},
		update:{},
		finish:{}
	};
	
	if (options.beforeStart)
		Object.extend(ret.start,{'beforeStart':options.beforeStart});
	
	if (options.beforeUpdate) {
		Object.extend(ret.start,{'beforeUpdate':options.beforeUpdate});
		Object.extend(ret.update,{'beforeUpdate':options.beforeUpdate});
		Object.extend(ret.finish,{'beforeUpdate':options.beforeUpdate});
	}
	if (options.afterUpdate) {
		Object.extend(ret.start,{'afterUpdate':options.afterUpdate});
		Object.extend(ret.update,{'afterUpdate':options.afterUpdate});
		Object.extend(ret.finish,{'afterUpdate':options.afterUpdate});
	}
	
	if (options.afterFinish)
		Object.extend(ret.finish,{'afterFinish':options.afterFinish});
	
	return ret;
}

Effect.Shake = function(element) {
  element = $(element);
  var options = Effect.combinedOptions(arguments[1] || {});
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
  return new Effect.Move(element, 
      Object.extend(options.start,{ x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      Object.extend(options.update,{ x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      Object.extend(options.update,{ x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      Object.extend(options.update,{ x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      Object.extend(options.update,{ x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      Object.extend(options.finish,{ x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
        effect.element.undoPositioned().setStyle(oldStyle);
  }})) }})) }})) }})) }})) }}));
}

Le combinedOptions prendra donc en paramètre l'objet option de l'effet Shake pour en ressortir un autre, dans lequel on aura inséré les callback nécessaires selon si l'effet Move est au début, au milieu ou à la fin de l'effet Shake.

Et voilà, c'est tout bon maintenant.

A mon avis ce bug existe pour beaucoup d'autres effets de combinaisons, vous pouvez employer la même technique (et la combinedOptions pour les corriger). J'ai soumis le code sur le wiki de scriptaculous.

Je n'avais jamais testé auparavant Scriptaculous et prototype. C'est une nouvelle façon de voir le javascript et c'est tellement agréable de coder avec ces framework que je crois que je ne pourrai plus m'en passer, après seulement quelques jours d'utilisation...

Gallerie d'images automatique

Comme j'ai un peu de temps, je vous donne ici les sources du script que j'ai mis en place pour ma galerie d'images.

En fait, j'utilise JW Image Rotator pour le diaporama en flash. Ce player est génial et très bien documenté. On peut le faire communiquer avec du JavaScript très simplement. C'est donc ce que j'ai fait avec la liste déroulante qui va envoyer l'url de la playlist à recharger.

Pour gagner du temps et être vraiment simple à utiliser, j'ai décider de ne pas avoir d'administration et que le simple fait d'envoyer un nouveau dossier mettrait en ligne les photos. La liste déroulante est donc générée en PHP pour faire apparaitre tous les dossiers existants. Le script générant la playlist récupère juste la liste des fichiers du dossier demandé et ressort un fichier XML, au format souhaité.

Etant donné que j'ai hébergé ce script sur mon ftp de free, j'ai du changer un peu les fonctions de récupération des dossiers/images pour qu'il fonctionne. si vous êtes dans le même cas, utiliser fonc.free.php à la place de fonc.php et tout ira bien.

Enfin, j'ai mis en place un rss pour permettre aux gens de suivrent simplement l'actualité de mes photos. Il suffit simplement de créer un flux XML au format demandé et on a un beau fil RSS tout nouveau tout beau !

NB : Pour mettre en place ce script sur votre site, vous devrez sans doute modifier des petits trucs dans tous les fichiers. Faites un tour complet avant.