Archive pour la catégorie ‘PHP’

Petit bench sur la recherche dans un tableau PHP

Samedi 1 août 2009
Préambule…

Hier, j’avais à parcourir un tableau d’objets (pouvant avoir potentiellement des centaines voire exceptionnellement milliers d’entrée) pour rechercher si l’identifiant de l’un d’eux se trouvait dans un second tableau. J’avais commencé par utiliser pour ça la fonction in_array() à chaque itération pour voir si l’identifiant de l’objet était présent ou non dans le second tableau.

En voyant cela, un collègue m’a fait remarquer que ce serait peut-être plus performant de construire un tableau dont les clés sont les valeurs du second tableau (via array_flip()) pour pouvoir utiliser isset() au lieu de in_array() et voici les résultats obtenus :

Structure du bench

Le bench consiste à rechercher 100 000 fois la même valeur dans le tableau array('11345', '7437', '7329', '45494', '7894311', 'sdfsdg', 'qsqsdcirt', 'd787 sdfs df'), avec trois méthodes différentes :

  • in_array()
  • array_flip() suivi de isset()
  • array_flip() suivi de array_key_exists()

Le test est effectué avec deux valeurs différentes : d’abord avec la première valeur du tableau (cas théoriquement le plus favorable puisqu’on arrête la recherche une fois la valeur trouvée) puis avec une valeur qui n’est pas dans le tableau (cas théoriquement le plus défavorable puisqu’on est obligé de parcourir tout le tableau). Le résultat en conditions réelles sera donc compris dans cette fourchette.

Cas in_array()

Code exécuté :

for ($i = 0; $i < 100000; $i++)
{
   in_array($value, $values);
}

Cas favorable ($value = '11345') : ~0.33 secondes
Cas défavorable ($value = 'uottuyi') : ~0.52 secondes

Cas isset()

Code exécuté :

$keys = array_flip($values);
for ($i = 0; $i < 100000; $i++)
{
   isset($keys[$value]);
}

Cas favorable ($value = '11345') : ~0.12 secondes
Cas défavorable ($value = 'uottuyi') : ~0.09 secondes

Cas array_key_exists()

Code exécuté :

$keys = array_flip($values);
for ($i = 0; $i < 100000; $i++)
{
   array_key_exists($value, $keys);
}

Cas favorable ($value = '11345') : ~0.27secondes
Cas défavorable ($value = 'uottuyi') : ~0.24 secondes

Et pour de plus petites quantités ?

Les grands volumes c’est bien mais qu’est-ce que ça donne quand on a peu d’itérations ?

Un test à 5 itérations au lieu de 100 000 donne environ le même résultat pour les trois méthodes : avec ~6E-05 secondes pour les méthodes 1 et 3 et ~5E-05 pour la méthode 2.

Tandis qu’un test sur une unique itération donne la première méthode gagnante avec ~4E-05 secondes contre ~5E-05 pour les deux autres (à ce niveau c’est le array_flip pour transformer les valeurs en clés qui coute cher).

Conclusion

À moins d’avoir toujours très peu d’itérations (moins de 5), la méthode passant par array_flip() puis isset() est d’assez loin la meilleure (environ quatre fois plus rapide sur des grands nombres et pas plus lente sur des petits).

En passant, on remarque aussi qu’avec cette méthode, rechercher une valeur qui n’existe pas dans le tableau est plus rapide que de rechercher la première valeur du tableau, même si je ne vois pas forcément trop pourquoi :pense:

  • Print this article!
  • Turn this article into a PDF!
  • E-mail this story to a friend!
  • Facebook
  • Twitter
  • del.icio.us
  • Digg
  • Google Bookmarks
  • BlogMemes Fr
  • Wikio FR
  • Netvibes

Quelques trucs sur PHP #2

Samedi 31 janvier 2009

Une deuxième série de petits trucs sur PHP…

Page blanche

Plus j’utilise PHP, plus je me rends compte qu’il y a quand même des trucs bien foireux dedans… Notamment ceci : lorsqu’une classe contient deux définitions de la même méthode (du moins dans certains cas, j’ai pas trop approfondi pour voir si c’est vraiment systématique), on n’obtient pas d’exception, ni même la traditionnelle “fatal error” non-catchable et sans trace, mais bel et bien une page blanche sans aucune explication \o/ J’imagine que derrière PHP doit mourir lamentablement sur un “Segmentation fault”… Bref, quand vous obtenez une page blanche, pensez à vérifier si vous n’avez pas raté un copier/coller quelque part…

Duplication de tableaux

Après avoir tenté en vain de dupliquer un tableau avec le mot-clé clone (qui retourne null), j’ai cherché un peu et je suis tombé sur cet article. Donc apparemment une simple affectation suffit à dupliquer un tableau (ce qui explique au passage certaines choses concernant la quantité astronomique de mémoire qu’arrive à bouffer PHP dans certains cas) ! Comme quoi même en utilisant un langage pendant des années, on peut passer à côté de certains trucs de base…

L’instruction continue

Je parlais il y a quelque temps de l’instruction break qui admet un paramètre permettant de sortir de plusieurs boucles imbriquées d’un coup, eh bien l’instruction continue se comporte de la même façon.

Je n’avais pas insisté dessus à l’époque (parce que dans le cas du break, c’est évident) mais dans les deux cas, un switch est considéré comme une boucle. Donc si vous êtes dans un switch contenu dans une boucle et que vous voulez passer à la prochaine itération de la boucle il faut appeler un continue 2;.

Pour plus de détails sur l’instruction continue, rendez-vous sur le manuel officiel de PHP.

  • Print this article!
  • Turn this article into a PDF!
  • E-mail this story to a friend!
  • Facebook
  • Twitter
  • del.icio.us
  • Digg
  • Google Bookmarks
  • BlogMemes Fr
  • Wikio FR
  • Netvibes

Personnaliser la barre latérale dans un thème WordPress

Dimanche 11 mai 2008

Vu qu’on m’a posé certaines questions là dessus cette semaine, ça va faire le sujet de l’article d’aujourd’hui.

Ajouter une seconde zone de widgets

WordPress - gestion des widgetsDepuis la version 2 (il me semble) de WordPress, si le thème est bien fait, on peut depuis le panneau d’administration ajouter des widgets dans certaines zones bien définies. Dans le thème par défaut, il y a une zone unique pouvant accueillir des widgets, qui se trouve dans la barre latérale. Mais on peut vouloir en ajouter d’autres.

Pour ajouter une nouvelle zone, il faut effectuer deux modifications dans le code du thème :

  1. premièrement, il faut “enregistrer” une nouvelle zone pour que celle-ci soit disponible dans le menu de sélection des zones. Pour cela il faut en général se rendre dans le fichier functions.php du thème et rechercher où est appelée la fonction register_sidebar (dans le thème par défaut, c’est tout en haut du fichier) et l’appeler une fois de plus pour enregistrer une nouvelle zone.

    Cette fonction peut optionnellement prendre en argument un tableau de paramètres permettant de personnaliser le code HTML qui enrobera la liste de widgets. Dans la plupart des cas on n’en a pas besoin mais au cas où c’est bon de savoir que c’est possible, notamment pour éventuellement spécifier une classe particulière à l’une ou l’autre zone en vu d’appliquer des styles différenciés.

    Une fois cela fait, la nouvelle zone est disponible dans le menu de sélection des zones du panneau d’administration (cf la capture d’écran ci-dessus).

  2. dans un deuxième temps, il faut inclure cette zone dans le rendu de la page à un endroit ou un autre (sinon, forcément, ça sert pas à grand chose). Pour cela il suffit d’intégrer le code suivant dans l’un des fichiers de template :
    <?php dynamic_sidebar(n); ?>
    en prenant garde de bien remplacer le paramètre “n” par un entier représentant le numéro de la zone que vous voulez afficher.

    Par exemple, si vous venez d’ajouter une zone et qu’il y en avait une seule avant, la nouvelle aura fort logiquement le numéro 2 et le code à insérer sera le suivant :

    <?php dynamic_sidebar(2); ?>

N’afficher certaines choses que sur la page d’accueil

Afin de ne pas trop surcharger les pages on peut ne vouloir afficher certaines informations et liens que sur la page d’accueil. Par exemple sur ce site, les encarts “Mes autres sites”, “News du serveur” et “Divers” ne s’affichent que sur la page d’accueil (et les pages de contenu fixe).

Pour restreindre l’affichage d’une portion de code d’un fichier de template, c’est très simple :

Code (HTML)

<?php if ( [CONDITION] ) { ?>
[CODE HTML À RESTREINDRE]
<?php } ?>

WordPress propose quelques fonctions PHP qui testent dans quel type de page on se trouve et qui peuvent servir à composer la condition (qui remplacera la portion “[CONDITION]” du code ci-dessus). Ces fonctions sont définies dans le fichier wp-includes/query.php et comprennent notamment :

  • is_home() disant si l’on se trouve sur la page d’accueil.
  • is_page() disant si l’on se trouve sur une page de contenu fixe.
  • is_search() disant si l’on est dans la page de recherche.
  • is_404() disant si l’on se trouve sur la page d’erreur 404.
  • etc.

Pour composer la condition, il suffit d’appeler une ou plusieurs de ces fonctions séparées par une double barre verticale (||) qui représente un “ou” en PHP.

Par exemple pour ajouter une zone de widgets qui ne sera affichée que sur la page d’accueil et les page de contenu fixe, on utilisera le code suivant :

Code (HTML)

<?php if ( is_home() || is_page() ) { // Home and pages only. ?>
   <?php dynamic_sidebar(2); // Home and pages sidebar. ?>
<?php } ?>

Et ça marche que pour la barre latérale ?

Bien entendu ces deux “astuces” sont valable aussi bien pour la barre latérale que pour n’importe quelle autre partie de votre site. Mais c’est dans la barre latérale que c’est le plus souvent utilisé.

  • Print this article!
  • Turn this article into a PDF!
  • E-mail this story to a friend!
  • Facebook
  • Twitter
  • del.icio.us
  • Digg
  • Google Bookmarks
  • BlogMemes Fr
  • Wikio FR
  • Netvibes

Quelques trucs sur PHP #1

Mercredi 22 août 2007

Quelques petits trucs que je n’ai appris que récemment. Peut-être étais-je le seul à les ignorer… ou peut-être pas, donc dans le doute…

Sortir de plusieurs boucles à la fois

Classiquement l’instruction break; s’utilise telle quelle pour sortir de la boucle ou du switch courant. Cependant en PHP (et sans doutes dans d’autres langages également), on peut lui adjoindre un paramètre entier permettant de sortir de plusieurs boucles à la fois. Ceci est à utiliser avec parcimonie car ce n’est pas forcément des plus lisible mais ça peut aider à accélérer une recherche dans un tableau multi-entrées par exemple :

Code (PHP)

// Supposons que $array est un tableau à
// double-entrée contenant des entiers
// et que l'on en cherche un supérieur à 10.
$result = null;
foreach ($array as $subArray)
{
   foreach ($subArrayas $item)
   {
      if ($item > 10)
      {
         $result = $item;
         break 2;
      }
   }
}

Paramètre de la fonction die

C’est plus une instruction qu’une fonction mais bon, passons. Elle peut prendre en argument un entier ou une chaine de caractère mais cet argument n’est affiché à l’écran que s’il s’agit d’une chaine. Ça n’a l’air de rien mais c’est bon à savoir…

DOM ou SimpleXML ?

SimpleXML c’est bien gentil et comme son nom l’indique, c’est «simple» (du moins dans son interface qui compte très peu de méthodes), mais à l’usage c’est quand même des plus limités. Et c’est plutôt chiant à utiliser parce qu’il faut caster pas mal de choses pour obtenir des chaines de caractère au lieux de nœuds XML (sans compter le bug dont je parlais il y a quelques temps). D’autant qu’il existe une alternative…

En effet, j’en étais resté à PHP4 où l’API DOM se cantonnait l’extension DOM XML non-incluse par défaut, ce qui n’était pas bien pratique… Mais en PHP5, elle a été remplacée par une nouvelle implémentation incluse en natif dans PHP sous le nom de DOM. Bref, en ce qui me concerne, SimpleXML va direct à la poubelle et je n’utilise plus que DOM, avec l’avantage supplémentaire d’être similaires aux bibliothèques DOM présentes dans d’autres langages tels que Javascript, puisque DOM est un standard, ce qui raccourcit d’autant l’apprentissage.

  • Print this article!
  • Turn this article into a PDF!
  • E-mail this story to a friend!
  • Facebook
  • Twitter
  • del.icio.us
  • Digg
  • Google Bookmarks
  • BlogMemes Fr
  • Wikio FR
  • Netvibes

PHPTAL, moteur de templates XML

Samedi 16 juin 2007

PHPTAL est un moteur de templates spécialisé dans la production de documents XML (et donc (X)HTML puisqu’il s’agit d’un langage XML).

Les templates qu’il utilise sont définis en XML valide, PHPTAL ajoutant ses propres attributs qui sont ensuite traité par le moteur. Le code des templates est donc purement de l’XML et non un code bâtard XML/PHP comme c’est le cas avec certains autres moteurs.

Avantages :

  • il n’accepte que du code XML valide, ce qui permet de détecter rapidement toute erreur d’imbrication.
  • le code des templates est de l’XML ce qui donne la possibilité de l’exploiter ou de le générer via les bibliothèque de gestion de fichiers XML habituelles.
  • il est installable sous forme de package pear ce qui rend son déploiement et sa mise à jour très simples.
  • comme il est entièrement XML il est en général plus accessible pour le graphiste qui pourra être chargé de construire les templates.

Inconvénients :

  • il ne permet a priori de générer que du code XML (ou de tout langage XML) ce qui peut être limitatif.
  • peut s’avérer limité par rapport à d’autres moteurs pour des traitements complexes.
  • le code des templates n’est pas forcément toujours des plus compacts.

Cela fait quelques mois que je l’utilise au boulot et j’en suis globalement satisfait, du moins dans les cas que j’ai eu à traiter avec… Cela dit je n’ai pas beaucoup expérimenté d’autres moteurs (à part celui de phpBB 2 qui est assez limité).

  • Print this article!
  • Turn this article into a PDF!
  • E-mail this story to a friend!
  • Facebook
  • Twitter
  • del.icio.us
  • Digg
  • Google Bookmarks
  • BlogMemes Fr
  • Wikio FR
  • Netvibes