Amélioration du script d'ajout d'image sur Black-Frames

Le script cron que l'on utilisais pour mettre à jour les images sur Black-Frames souffrait d'un bug gênant.

En effet, lorsqu'il n'y avait plus d'images à afficher, le script envoyait quand même un tweet vide et moche, du genre :

http://black-frames.net/i- - :

C'est maintenant chose corrigée. Lorsqu'il n'y a plus d'images dans le système de queue, le script prends une ancienne image affichée et la remet au goût du jour, ce afin de toujours proposer des images.

Certains vont penser que du coup, le site semblera un peu répétitif. Nous avons une base de plus de 1500 images. Si on part du principe que l'on affiche 5 images par jours, vous verrez la même image au bout de 300 jours.

Mais cela ne veux pas dire que nous n'ajouterons plus de nouvelles images ! Nous avons encore de côté 300 images à ajouter (il faut juste trouver le temps de le faire) et nous récupérons régulièrement de nouvelles images !

Ce script nous permettra juste d'effectuer une mise à jour constante du site afin de vous proposer des images régulièrement !

Filed under  //  Development   Php   Projects   Scripts   black-frames   bug   cron   tweet   twitter  
Posted by Cyril Nicodème 

Comprendre le model objet en PHP

Cette présentation explique plutôt bien le modèle objet en PHP de manière assez simple et concrète.

Ca fait jamais de mal de revoir nos bases :)

Filed under  //  Development   Howtos   Php   model   objet   online   ppt   presentation   screencast   slideshare  
Posted by Cyril Nicodème 

[Astuce] - Formater une durée en heures, minutes, secondes

Voici un bout de code qui, j'en suis sûr, beaucoup d'entre vous ont déjà tenté d'implémenter dans leur projets, dans différentes façons.

En effet, qui n'a jamais voulu afficher une durée donnée en secondes, découpée en mois, jours, heures, minutes, secondes ?

La solution que je vous propose tiens en 2 lignes :

<?php
/**
 * Créer un objet DateTime avec le nombre de secondes donné en paramètres
 * Comme la date est de l'an 0, le temps retourné correspondra au temps 
 * en jours, heures, minutes, secondes du timestamp indiqué
 * 
 * @param Integer $iTime : Timestamp en seconde
 * @param String $sFormat (optionel) : Le format de la date à retourner
 * 
 * @return String : La date formatée
 */
function timetostr ($iTime, $sFormat = 'd\j H\hi\ms\s') {
    $oTime = new DateTime ('@'.$iTime);
    return $oTime->format ($sFormat);
}
?>

Attention ! Ne fonctionne que sous PHP 5.2 (utilisation de DateTime) !

Filed under  //  Development   Php   Scripts   date   day   duration   format   hour   minute   second   time   timestamp  
Posted by Cyril Nicodème 

Benchmark de mon ORM

Pour les besoins d'un nouveau projet, j'ai crée mon propre ORM, que je voulais à la fois simple et rapide.

Histoire de tester ses performances, j'ai fait un benchmark sur les insertions. Au niveau des insertions, j'ai fait un script qui insérait une ligne dans la base de donnée, 1000 fois. Je pense que 1000 était la limite car la durée moyenne était de 27 secondes :p (j'ai atteint à la fin plusieurs fois le temps limite !).

On peux constater deux choses : Mon script ne se débrouille pas si mal, il est aussi rapide que PDO, et à peine plus lent que mysql_query.

Pour les plus perspicaces, vous remarquerez que, à ma grande surprise au début, mon script, qui utilise PDO, est plus rapide que PDO lui-même !

La raison qui me semble être la plus logique, est que plus il y a d'entrées dans la base, et plus les insertions vont mettre du temps. Comme j'ai procédé dans l'ordre : Mon Orm, PDO, mysql_query, PDO devait mettre à peine plus de temps que mon orm car il avait plus d'entrées. Du coup je pense qu'ils sont quasiment aussi rapide (malgré les couches de tests et autres que je fait dans mon orm !).

Voici les divers scripts utilisés et leur résultats :

Read the rest of this post »

Filed under  //  Development   Php   Projects   benchmark   orm  
Posted by Cyril Nicodème 

Petit problème PHP :)

Trouvez la solution à ce petit problème :

Ce bout de code :

<?php
$arr = array('A', 'B', 'C');
foreach ($arr as &$val) {}
foreach ($arr as $val) {}
var_dump($arr);
?>

Affiche :

array(3) {
     [0]=>  string(1) "A"
     [1]=>  string(1) "B"
     [2]=>  &string(1) "B"
}

Oui ! A, B, B !

POURQUOI ?

Read the rest of this post »

Filed under  //  Development   Php   foreach   probleme   scope   var  
Posted by Cyril Nicodème 

Multi-Threading en PHP5

L'article rédigé par Martin Roest nous montre à quel point il peut-être facile de jouer avec plusieurs processus en même temps, même en PHP.

J'ai personnellement été très séduit par la simplicité, mais je trouve que l'on pouvais encore faire plus simple : une petite classe :)

L'utilité d'un tel code se trouve sur des scripts de traitement, tel qu'un remaniement de base de donnée, une modifications sur plusieurs fichiers, etc. Par contre, il est important de savoir que la gestion des processus tel qu'il est utilisé ici ne fonctionne pas sous Windows, et qu'il n'est pas conseillé d'appeler ce script depuis un environnement type Apache.

En gros et pour faire simple, ce type de script s'utilise en ligne de commande (php-cli) et dans un environnement Unix, type cron.

Pour vous prouver l'efficacité de mes dires, voici un code bateau qui utilise 5 processus simultanés pour exécuter un script :

<?php
require_once ('ProcessManager.php');

function doBigWork ($iWork) {
        echo 'Sleeping for Work N° '.$iWork."\n";
        sleep (20);
}

try {
        // We instanciate the ProcessManager with 5 childs
        $oPM = new ProcessManager (5);
}
catch (Exception $oE) {
        die ('Your configuration does not support "pcntl" methods.');
}

for ($i = 0; $i &:t; 12; $i++) {
        // It could happen that the script couldn't fork a process. In that case, an Exception would be raised
        try {
                $oPM->fork ('doBigWork', array ($i));
        }
        catch (Exception $oE) {
                echo 'Using non forked way :'."\n";
                doBigWork ($i);
        }
}
?>

Au final, sans utiliser plusieurs processus, ce code aurait pris 12*20 = 240 secondes. Avec 5 enfants, le temps de travail est divisé par ... 5, soit 48 secondes ! Quand même !

Bien entendu, vous pouvez augmenter le nombre d'enfant, tout dépendra des ressources que consomment votre fonction de travail (histoire de ne pas tuer votre machine (je l'ai fait pendant les tests :p)).

Une dernière modification qui serait sympathique, c'est d'inclure les fonctions lambdas dans la méthode fork, au lieu de l'appel à une méthode en utilisant le call_user_func_array. Mais ma configuration actuelle de Php n'est pas encore en 5.3, donc je ne peux ni jouer avec les closures, ni avec les fonctions lambdas :p Peut-être plus tard ? :)

Voici la classe à proprement parler :

Read the rest of this post »

Filed under  //  Development   Howtos   Php   cli   command   fork   line   multi   pcntl   pid   processus   script   thread  
Posted by Cyril Nicodème 

N'utilisez plus les fonctions mysql_*

Dans cet article, nous verrons en quoi il est préférable d'utiliser PDO et d'oublier les fonctions telles que mysql_*

0. Sommaire

  1. Introduction
  2. Mise en place de l'environnement
  3. Instanciation de l'objet PDO
  4. Requêtes simples
  5. Requêtes préparées
    1. Sans bind de valeurs
    2. Avec bind de valeurs
  6. Les transactions
  7. Conclusion
  8. Ressources
  9. Notes

1. Introduction

La sortie de PHP 5 le 13 Juillet 2004, a apporté son lot de nouveauté. Parmis eux, se trouve la librairie PDO, originalement fournie en tant qu'extension PECL, mais ensuite adaptée dans le coeur de PHP dans sa version 5.1. PDO fournit une abstraction des bases de données, permettant ainsi au développeur de communiquer avec une base de donnée sans (trop) se soucier du serveur avec qui il communique (MySQL, PostgreSQL, MsSql, Oracle, etc). La puissance de PDO réside dans le fait que cette librairie est écrite en C, contrairement aux Pear:DB, AdoDb et companie, écrite elles, en Php. De ce fait, on constate un gain de performance et le développeur n'a pas à se soucier de télécharger les classes * au cas ou * le serveur ne les aurait pas à disposition (cas de PEAR par exemple).

Mais alors pourquoi trop de monde utilise encore mysql_* ?

Nous verrons dans cet article que PDO est très simple d'usage et qu'il existe maintenant plus aucune excuse à utiliser mysql_* !

Read the rest of this post »

Filed under  //  Development   Php   begin   commit   execute   mysql   pdo   prepare   query   rollback   transaction  
Posted by Cyril Nicodème 

Optimisation PHP

On parle très souvent de l'optimisation de code PHP, mais dans le concret, on se rend très vite compte que tous les conseils ne sont pas appliqués. Après la publication d'un article en anglais, sur 12 astuces d'optimisations PHP, je vais ici traduire ces astuces et indiquer les autres qui me semblent indispensables.

  1. Préférez les méthodes statiques. La rapidité d'exécution du code PHP est multiplié par 4 !
  2. Évitez autant que vous pouvez l'utilisation des méthodes magiques (__get, __set, etc)
  3. Require_once est plus lourd que require (logique puisqu'il va vérifier que le fichier n'à pas déjà été chargé !)
  4. Préférez l'utilisation des chemins absolus, qui évitent au moteur PHP de résoudre le chemin par le biais du système (utilisez $_SERVER ['DOCUMENT_ROOT'])
  5. Pour avoir le temps en secondes, préférez $_SERVER['REQUEST_TIME'] à time (). En effet, time () demande un temps de calcul à PHP alors que $_SERVER['REQUEST_TIME'] est déjà calculé !
  6. Evitez au maximum l'utilisation des expressions régulières (utilisation des fonctions strncasecmp, strpbrk et stripos)
  7. str_replace est plus rapide que preg_replace, mais strtr est 4 fois plus rapide que str_replace ... !!
  8. Preferez le passage de paramètre à des fonctions en String plutôt que Array, ce qui évitera un temps de traitement supplémentaire pour le parcours du tableau !
  9. L'utilisation du @ pour ne pas afficher les erreurs ralentit considérablement le traitement.
  10. $row['id'] est 7 fois plus rapide que $row[id] !!!
  11. Les messages d'erreurs ralentissent votre code ! Normal puisqu'ils sont (peuvent) être écrit dans le fichier de log, affichés, etc
  12. Essayez au maximum de sortir les fonctions telles que count, sizeof, ... des boucles. Car ces fonctions sont appelées à chaque itérations, ce qui alourdit considérablement le traitement !
  13. Préférez l'usage des simples quotes plutôt que des doubles quotes. Les doubles quotes sont parsées, tandis que les simples quotes non ! (le $ est affiché et n'est pas traité en tant que variable !)
  14. Évitez au maximum la redondance de code, en utilisant des classes ou des fonctions. Cela permet aussi une maintenance et une pérennité de votre code, puisqu'il suffira ensuite de modifier qu'à un seul endroit, au lieu de parcourir tous vos fichiers !
  15. Préférez l'utilisation des fonctions preg_* au lieu de ereg_* qui sont maintenant dépréciée !
  16. Préférez l'utilisation de
    if (!isset ($myvar{5}))
            echo $myvar.' is too short';
    au lieu de
    if (strlen ($myvar)
    Isset n'est pas une fonction mais une structure du langage, qui est donc beaucoup plus rapide !
  17. Préferez l'usage de ++$i plutot que $i++, qui est plus rapide (s'applique uniquement à PHP !)
  18. echo est plus rapide que print tout simplement car print retourne un état de succès tandis que echo ne fait qu'afficher.
  19. Tout ce qui n'est pas du PHP doit être en dehors des ?><?php ! Eviter les longs echo '<html>....'; qui seront plus long à parser que des ?><html>... !!!
  20. Préférez l'utilisation de la librairie ctype (activée par défaut depuis PHP 4.2.0) plutôt que des expressions régulières pour valider des entrées utilisateurs simple (tel que des nombres, des chaines, etc). Jetez un oeil à la librairie ctype sur php.net
  21. true est plus rapide que TRUE (sisi c'est vrai ! :p). Pourquoi ? parce que dans la structure de langage de PHP, la valeur booléenne est true. Si vous mettez TRUE, PHP va déjà vérifier si ce n'est pas une constante. C'est donc une perte de temps.
  22. 1 est plus rapide que true (et inversement 0 est plus rapide que false). Et comme PHP n'est pas typé ...
  23. Préferez if (42 == $value) plutot que ($value == 42). Ce ne sera pas plus rapide, mais vous obtiendrez une erreur si vous omettez un égal ! (42 = $value vous retournera une erreur. $value = 42 ne fera qu'assiger 42 à la variable $value, et vous comprendrez pas pourquoi votre code ne fonctionne pas :p)
  24. Il est préférable d'utiliser :
    $myArray = array ('banane' => 0, 'pomme' => 1, 'orange' => 2); 
    if (isset ($myArray[$fruits])) {
            echo $fruits.' exist';
    }
    plutot que
    $myArray = array ('banane', 'pomme', 'orange');
    if (array_exists ($myArray, $fruits)) {
            echo $fruits.' exists';
    }
  25. De plus gros blocs de code php augmentent la rapidité du script plutôt que des <?php .. ?> à chaque lignes
  26. Si vous utilisez echo, la concaténation est plus rapide avec des virgules qu'avec des points !!
    echo 'Bonjour Mr',$sName,', vous avez ',$iMsg,' message(s)'
  27. Utiliser au maximum unset, afin de libérer le plus de mémoire possible
  28. Essayer au maximum de génerer des pages html statiques une fois le contenu mis à jour, afin d'éviter un traitement à chaque affichage !

Toutes ces méthodes vous permettront d'avoir un code performant, ce qui aura pour conséquence d'améliorer la rapidité de rendu de vos pages en cas de forte consultation.

Filed under  //  Development   Php   cache   conseil   eviter   optimisation   préférable   quote   rapidity   rendu  
Posted by Cyril Nicodème 

Les fonctions mysql_* sont à considérer comme obsolètes !

On voit encore beaucoup de fonctions mysql_* traîner sur les applications web car les développeurs ont toujours connu cette pratique, surtout ceux qui ont démarré PHP à l'ère de PHP 3 et PHP 4. Néanmoins, ces fonctions sont aujourd'hui beaucoup trop limitantes car elles ne permettent pas de profiter des spécificités d'un environnement MySQL 5 à savoir :

  • Les transactions,
  • Les triggers,
  • Les requêtes préparées,
  • Les procédures stockées...

C'est pour ces raisons que l'extension MySQLi est apparue en PHP 5 pour venir petit à petit essayer de supplanter l'extension MySQL classique. Ainsi en utilisant l'extension MySQLi, le développeur peut jouir des mêmes fonctionnalités qu'avec MySQL ainsi que des nouveautés propres à MySQL 5 avec des performances légèrement meilleures.

Quant à PDO, il est vrai que cette extension est légèrement moins performante en terme de vélocité du fait notamment de la POO mais a le mérite d'être beaucoup plus performante en terme de fonctionnalités offertes (support des transactions, procédures stockées, triggers, requêtes préparées...) et d'indépendance. Avec PDO, on dépend beaucoup moins de son SGBDR contrairement aux fonctions propres à MySQL. Dans le cadre d'une application de forum open-source, c'est un réel avantage de pouvoir offrir aux utilisateurs un support de l'application sur plusieurs SGBDR. Grâce à PDO, la difficulté de cette tâche est largement réduite puisqu'il n'est pas nécessaire d'avoir à écrire soi même les connecteurs pour chaque base. Il suffit juste d'adapter les requêtes SQL. Il est bon de noter qu'en PHP, seul PDO est capable de se connecter à une base de type SQLite 3 par exemple.

Je tiens à préciser également qu'une version 2 de PDO est en cours de réécriture et devrait paraître avec PHP 6 si je ne me trompe pas (à vérifier). Toujours est-il que c'est un chantier en cours du côté de l'équipe de développement de PHP. Le succès de PDO grandit de jour en jour, notamment grâce aux frameworks. Il suffit par exemple de constater combien d'applications d'ORM intégrées aux frameworks PHP 5 actuels s'appuient sur PDO. C'est le cas par exemple de Propel 1.3 et Doctrine 0.9 intégrés à Symfony ou bien encore le composant Zend_Db du framework Zend. C'est notamment grâce aux différents feedbacks des développeurs concernant les performances et la potentielle lourdeur de PDO que l'équipe de développement a ouvert un chantier pour améliorer tout ça dans les mois à venir.

Enfin, je rappelle que la nouvelle extension native MySQLnd, dédiée à MySQL, sera packagée avec PHP 5.3 au moment de sa sortie en version bêta dans le courant du mois d'août et en version stable à l'automne. Donc entre MySQL, MySQLi, PDO, MySQLnd et PDO 2, le choix des connecteurs pour MySQL est large et on peut affirmer aujourd'hui que le driver simple MySQL est obsolète. D'autant plus que PHP 4 ne sera plus supporté à partir du 08 août prochain et MySQL est à l'origine une extension PHP 4 destinée à interagir avec des bases de données MySQL 4. Elle a rendu de très bons services aux développeurs jusqu'à maintenant et je pense que ça continuera encore malgré tout, mais il est temps de montrer aux développeurs d'aujourd'hui qu'il existe des solutions plus fiables, plus "performantes", plus pratiques, plus fonctionnelles et plus pérennes. :)

Commentaire de Hugo HAMON (Webdeb) sur le site de phpcs.com

Filed under  //  Development   Howtos   Php   database   mysql   obsolete   pdo   sgbd   sqlite  
Posted by Cyril Nicodème 

Catapult Origin (v0.1.1)

I'm pleased to anounce you the release of my PHP Framework, Catapult.

You will have more information at this address : http://catapult.reflectiv.net

The next version, "Emergence" (v0.2) will be available during June (I hope ! :p), and will bring a newest Sgbd management, an User (User, Authentication and maybe Acl) objects and some other good stuffs :)

I hope you will like it :)

Filed under  //  Catapult   Development   Emergence   Origin   Php   Projects   framework  
Posted by Cyril Nicodème