Posts tagged ‘php’

iGraal a développé un bundle pour répondre à la question suivante : comment pouvoir utiliser les extensions et filtres twig dans un fichier javascript, qui sera lui-même passé dans la moulinette d’assetic ?

Expression du besoin

iGraal a une application mobile compatible Android et iOS. iGraal souhaite utiliser le cache varnish pour son site, mais certains traitements traînent dans les request listeners, dont le test de compatibilité mobile. Hors, il faudrait éviter de faire un appel à toute la couche Symfony juste pour détecter qu’un utilisateur est mobile ou non. Une solution qui fonctionne très bien est de passer ce test en javascript.

Le rôle de ce javascript est donc 1) la détection du device utilisé par la personne (iOS / Android), 2) la décision de l’affichage (via cookies), 3) la redirection vers une URL donnée et 4) la possibilité d’inclure ce JS dans notre JS global déjà compilé par assetic.

Le filtre assetic Twig

Nous voulions donc utiliser :

  1. Assetic pour inclure ce JS dans notre JS global
  2. Utiliser la fonction twig path pour trouver vers quelle URL rediriger notre internaute

Un bundle a donc été créé : https://github.com/igraal/twig-assetic-filter-bundle

Au début, c’était pas vraiment un bundle, juste un bout de code, mais autant partager !

Ce bundle permet d’utiliser un filtre « twig » pour inclure des JS ou des CSS.

Exemple d’utilisation

Fichier HTML

  1. <DOCTYPE html>
  2. <html>
  3.   <head>
  4.     <% javascripts
  5.       '@AcmeWhateverBundle/Resources/js/main.js'
  6.       '@AcmeWhateverBundle/Resources/js/feature.twig.js'
  7.       filter="twig" %>
  8.     <script type="text/javascript" src="{{ asset_url }}" async defer />
  9.     <% endjavascripts %>
  10.   </head>
  11. ...
  12. </html>

Fichier JS

  1. if (isMobile()) window.location.replace('{{ path('www_mobile') }}');

 

Principales utilisations

Utilisation du filtre :

  1. Utiliser les routing dans du javascript (comme le montre l’exemple)
  2. Utiliser des traductions dans du javascript, surtout utile lors de validation de form en JS, dans tous les cas il y a l’ajax 😉
  3. Utiliser vos propres extensions pour du JS, par exemple pour faciliter le codage ou autre. On pourrait très bien imaginer une fonction js_debug qui fait un console.debug en javascript en dev, rien en prod.

 

J’ai lu pas mal d’articles sur comment créer un cluster de session en PHP, afin de pouvoir utiliser plusieurs serveurs web en front tout en conservant les sessions entres les différents serveurs. Finalement, je vais expliquer la solution de repcached.

Memcached

Memcached est un serveur qui sert à enregistrer et redélivrer des valeurs diverses et variées directement dans la RAM d’un ordinateur.

Avantages : la rapidité d’éxecution des commandes et le support dans PHP en installant une simple extension PECL.
Inconvénient : perte des données en cas de reboot

Dans notre cas, pour stocker des sessions, c’est parfait : un accès rapide à des données, et plusieurs serveurs peuvent accéder à cette base de donnée en même temps.

Repcached

Repcached permet de pallier l’inconvénient de memcached : il s’agit simplement d’un patch qui permet de gérer la réplication entre deux serveurs. En effet, toute commande d’écriture sur un serveur est directement reportée sur l’autre serveur. Ainsi, si l’un des deux tombe, l’autre est à jour et peut prendre le relai. De plus, lors du reboot, toutes les données seront automatiquement récupérées auprès du premier serveur.

Cette solution permet du coup de gérer la redondance de l’information.

Puis-je mettre plus de 2 serveurs ?
Certainement, mais je ne sais pas trop comment… On pourrait mettre 3 serveurs en cycle, mais si l’un tombe, la chaîne est rompue. Il faudrait automatiquement adapter le routage des paquets non plus vers le serveur qui est tombé, mais vers le serveur survivant (en redirigeant les paquets par iptables par exemple).

Installation sous Gentoo

J’ai mis à disposition le serveur memcached 1.2.8 avec repcached 2.2 en ebuild à disposition ici :
http://cyril.me/ebuild/net-misc/memcached/

Cet ebuild se base sur la version 2.1-1.2.6 disponible dans l’overlay wolf32o1.

Match et non-match…

En cette période de coupe du monde de football 2010, quoi de plus naturel que de parler de match ? … Hum.

Problématique

Mon problème aujourd’hui, c’est de sélectionner les listes qui contiennent une certaines expression régulière, mais pas une autre. Plus exactement, et pour faire dans les anglicismes, je cherche « foo.* », mais pas « foobar ».

La solution

Il faut utiliser la forme suivante : (?!regexp) pour choisir quelque chose qui ne match pas la regexp en question.

Mon exemple en pratique :

$ echo -e 'foo\nfoobar\nfoofighting' | grep -P 'foo(?!bar)'
foo
foofighting

Plus d’informations disponible avec perldoc perlre, en particulier le chapitre sur les expressions régulières étendues (Extended Patterns)

Problème

Lorsque l’on parse des fichiers, surtout les fichiers HTML, on a parfois besoin d’extraire un texte compris entre deux balises. Voici donc un moyen d’y parvenir avec les expressions régulières.

Considérations techniques

Je parlerais ici des expressions régulières perl (et par extension : grep -P et preg_* de php).

Par défaut, un /.*/ ou toute autre expression sera « gourmand » : ça matche tant que ça peut encore matcher. Par exemple, /a*/ appliqué à la chaîne "aaa" va matcher "aaa", et non pas "".

Dans mon cas pratique, j’ai une balise <td id="identifier"> et j’en cherche le contenu. Donc si la regexp utilisée est /<td id="identifier">(.*)<\/td>/ alors je vais matcher ce qu’il y a entre mon td ouvrant, et le dernier td fermant.

La solution

La solution consiste à dire au moteur d’expression régulière de prendre le moins possible, et ça se code comme suit : /<td id="identifier">(.*?)<\/td>/.

Bibliographie : http://social.msdn.microsoft.com/Forums/en-US/regexp/thread/ab975ba5-31dd-4e6d-b72f-5cd6bf374b02 (et oui, parfois on trouve des choses utiles sur les forums de microsoft).

Les arrondis peuvent parfois réserver des surprises. Regardez par exemple le code suivant :

  1. <?php
  2. for ($i = 0; $i <= 1; $i += 0.05)
  3. {
  4.   printf ("%.2f %.1f %.1f\n", $i, $i, round($i, 1));
  5. }
  6. ?>

Ce qui nous donne :

0.00 0.0 0.0
0.05 0.1 0.1
0.10 0.1 0.1
0.15 0.2 0.2
0.20 0.2 0.2
0.25 0.2 0.3
0.30 0.3 0.3
0.35 0.3 0.4
0.40 0.4 0.4
0.45 0.4 0.5
0.50 0.5 0.5
0.55 0.5 0.6
0.60 0.6 0.6
0.65 0.7 0.7
0.70 0.7 0.7
0.75 0.8 0.8
0.80 0.8 0.8
0.85 0.9 0.9
0.90 0.9 0.9
0.95 1.0 1.0

Les deux résultats sont différents !

L’explication, vous la trouverez dans la documentation de perl (perldoc -q round) :

Don’t blame Perl.  It’s the same as in C.  IEEE says we have to do this.  Perl numbers whose absolute values are integers under 2**31 (on 32 bit machines) will work pretty much like mathematical integers.  Other numbers are not guaranteed.