Lancer NodeJS comme un service avec Upstart

Il est facile de lancer un serveur web, par exemple, avec NodeJS et une de ces commandes :

  1. La première lance le script web.js en console. Dès que la console est coupée, le script l’est aussi. Ballot.
  2. La seconde permet de garder le script  web.js en arrière-plan, mais si le script cherche à écrire quelque chose sur stdout et que la console est coupée, le script va crasher. Et oui stdout n’existe plus.
  3. La dernière solution est la meilleure des 3 mais en cas de crash ou de redémarrage du serveur, on est obligé de relancer le script à la main.

Mais alors, comment je fais ? Je reste au cul du serveur, à guetter sur htop si mon script disparait pour pouvoir garder un service continu ?

Et non, il y a Upstart !

Upstart est un outil basé sur les évènements et permet de lancer des tâches ou des services pendant un boot, les arrêter quand le serveur s’arrête et pouvoir superviser le service à tout moment.

Comment installer Upstart ?

Si vous êtes sur Ubuntu, il n’y a rien à faire. C’est installé d’origine.
Sinon un classique fera l’affaire :

Configuration de Upstart

Cet outil fonctionne avec des fichiers de configuration qu’il faut placer dans /etc/init/. Voici mon fichier web.conf pour mon serveur web NodeJS:

Voilà rien de bien compliqué. Je vais pas détailler plus, c’est assez simple à comprendre.

Utilisation de Upstart

Maintenant pour lancer son script comme un service c’est super simple. Il suffit d’exécuter:
Pour lancer le service:

Pour arreter le service:

Pour vérifier le statut du service:

Astuce

Si vous voyez celà pendant que vous lancez le service

C’est qu’il y a une erreur dans le fichier de configuration.
Ou que le fichier n’est pas dans /etc/init, ou que le fichier n’est pas web.conf. Mais là c’est que vous n’auriez pas bien suivi le tuto ;).

Contrôle d’accès simple avec CodeIgniter

Une des choses redondantes dans un projet, c’est le contrôle d’accès. Savoir jusqu’où un utilisateur non connecté peut aller, ou même limiter les droits de certains utilisateurs.
Le truc basique c’est de checker soit dans le constructeur du contrôleur, soit dans chaque fonction du contrôleur si l’utilisateur a les droits suffisants pour continuer. Or lorsque le projet atteint une certaine ampleur, il devient vite contraignant et lourd de rajouter ce contrôle à chaque fonction.

Étendre la classe controller

Au début, je pensais créer un hook pre-controller mais toutes les fonctionnalités dont j’avais besoin n’étaient pas chargées. Du coup j’étends la classe controller afin que chaque contrôleur commence par checker l’accès avant d’aller plus loin.

Pour étendre la classe controller il faut créer un fichier /application/core/MY_Controller.php

Préparer les liens accessibles sans connexion

Ici je définis tous les liens ( controleur/fonction ) qui peuvent être accessibles sans connexion. Pour moi c’est plus simple dans ce sens, il est possible de faire l’inverse s’il y a plus d’endroits accessibles sans connexion qu’avec connexion.

Je créé donc un tableau avec les fonctions qui n’ont pas besoin de contrôle d’accès. C’est utile de mettre les fonctions car on peut très bien imaginer une fonction profil dans le contrôleur user, qui aurait besoin d’un contrôle d’accès.

Mise en place du contrôle d’accès

Voila tout est fait.

Explications:

A chaque chargement du contrôleur, on construit l’URI pour n’avoir que le contrôleur et sa fonction. On vérifie à partir de la session si la personne est connectée et si l’url qu’elle demande lui est autorisée. Avec cet exemple simple, un utilisateur non connecté peut accéder qu’aux liens présents dans le tableau. Pour tous les autres il doit être connecté. Lorsque l’utilisateur n’est pas accepté, il est redirigé directement vers l’accueil.

Maintenant c’est bien beau, mais il va falloir modifier chaque contrôleur afin de les étendre à partir de notre nouveau contrôleur de base.

Conseil d’utilisation de ce système:

Si vous n’avez pas du tout besoin du contrôle d’accès dans votre contrôleur, vous créez votre contrôleur normalement ( extends CI_Controller ).

Si au moins une fonction de votre contrôleur a besoin du contrôle d’accès alors vous créez à partir de votre contrôleur étendu ( extends MY_Controller ).

Sauvegarder les mots de passe dans Postgresql avec bcrypt

On voit de plus en plus souvent dans les news, que des bases de données se sont faites hackées, et des gros dumps de mots de passe circulent ainsi dans la nature.

La sauvegarde old school

La manière classique de sauvegarder les mots de passe utilisateur est de les garder en clair de les hasher (md5, sha1, …) avec un salt.

Exemple:

Voila, on récupère ainsi une chaine de caractère illisible. Le problème c’est qu’elle est crackable très très rapidement, puisque les algorithmes de hash rapides, tels que md5 et ceux de la famille SHA, ne sont plus vraiment fiables: voir cet article.

Et oui décrypter un hash en quelques secondes avec les technologies d’aujourd’hui est clairement possible.

La nouvelle façon

Maintenant il existe une approche plus moderne pour faire tout ça avec Postgresql: bcrypt qui fait partie du module pgcrypto.

Attention, si vous avez déjà une application avec des utilisateurs, ils seront obligés de mettre à jour leur mot de passe pour cette nouvelle solution.

Avantages de bcrypt

  • On utilise un algorithme de hash lent (Blowfish)
  • Plusieurs cycles de hash sont exécutés afin de renforcer la sécurité
  • Un salt aléatoire est généré pour chaque mot de passe. Inutile de garder un salt dans son code/BDD et la sécurité est plus accrue.

Mise en place

Modification du type du champ mot de passe (facultatif):

Ajout du module à votre base:

Mise à jour d’un mot de passe pour un utilisateur donné:

Dans la génération du salt, bf correspond à l’algorithme (blowfish) et le chiffre 8 correspond au nombre de passage. Plus le nombre de passage est élevé, plus c’est long et plus c’est sécurisé. Sur la doc de pgcrypto il est conseillé d’avoir une vitesse d’exécution entre 4 et 100 mots de passe par seconde. La vitesse change évidemment suivant la puissance du processeur. Un tableau est aussi disponible, toujours sur la doc afin de comparer les temps d’exécution suivant les différents types d’algorithme avec un même processeur.

Comparer le mot de passe entré par l’utilisateur à celui en base:

Ici le mot de passe en base est utilisé comme salt du mot de passe entré.

Et voila, il n’y a rien de bien compliqué, c’est facile à mettre en place, donc sautez sur l’occasion pour améliorer la sécurité de votre application.

Recherche avec auto-complétion multi-mots et Postgresql

L’auto-complétion multi-mots ? Kézako ? Bon c’est un terme que j’ai un peu inventé (oui je me la raconte ;)), mais je vais vous expliquer la théorie rapidement.

Avec une auto-complétion normale, sur une base importante, on utilise en général like ‘blabla%’. Avec un index sur le champ concerné, les performances sont très correctes, et ce genre de méthode est fréquemment utilisée.

Mon problème: j’aimerai effectuer une recherche auto-complétée à partir de n’importe quel mot d’un titre.

Exemple: Trouver « Tour Eiffel » en tapant « eif ».

Exemple 2: Trouver « Tour Eiffel » en tapant « eiffel to ».

Ceci est impossible avec l’auto-complétion basique. Il faudrait taper « tou » pour trouver ce que l’on veut. De plus, un problème de casse apparait (sauf si l’on utilise ilike).

L’idée alors est de découper tous les titres par mot, et de les rassembler dans une seule et même table. Ceci fonctionne bien mais que pour l’exemple 1.

Pour l’exemple 2, j’utilise en plus le Full Text Search.

Dans la suite de cette article, j’utilise une table film avec pour champs id et titre.

Postgresql 9.1 est utilisé sur une Ubuntu 12.04 LTS.

Formatage des textes

Dans un premier temps j’ai créé une fonction qui me permet de formater tous mes titres sans majuscule, ni accent. Un avantage, l’utilisateur ne sera pas obligé de mettre toutes les majuscules et/ou accents afin de trouver ce qu’il veut.

Création de la fonction dans postgresql:

Si unaccent n’est pas disponible sur votre serveur, il faut installer postgresql-contrib, qui contient plusieurs fonctions d’aide comme unaccent.

Mise en place du Full Text Search

Dans un premier je créé une nouvelle colonne dans ma table film:

Ensuite je remplis la colonne à partir des titres de mes films:

Et pour finir la mise en place de l’index:

On peut d’ores et déjà tester le Full Text Search.

Le Full Text Search est un outil très puissant pour la recherche de mots dans un document. Le problème ici c’est que l’utilisateur est obligé de taper le mot entier pour avoir une réponse. Pas très pratique.

Mise en place de la table de mots

Cette table de mots permet d’avoir une auto-complétion avec n’importe quels mots des titres des films.

On commence donc par créer une nouvelle table:

Puis remplir la table:

Ici la fonction un peu magique c’est regex_split_to_table, qui permet de spliter une chaine de caractères suivant un modèle; ici l’espace et ensuite de créer plusieurs entrées à partir d’une seule.

On rajoutes les index pour que ce soit un minimum efficace:

Et voila le système est mis en place.

On peut tester les 2 systèmes en même temps:

Voila on voit que la requête est exécutée très rapidement. Si je compare cet exemple à l’utilisation de like ‘%mechant%’, la vitesse de résultat n’est pas du tout la même et ne pas être utilisé dans un cas d’auto-complétion.

Maintenant il ne reste plus qu’à intégrer tout ça avec Jquery et PHP.

Intégration

Jquery

J’utilise Jquery UI avec le widget Autocomplete, c’est simple et rapide à mettre en place:

PHP

Et les fonctions pour la recherche en PHP avec Codeigniter comme d’habitude 🙂

Maintenant vous avez tout à votre disposition pour mettre vous aussi en place une auto-complétion multi-mots.

Avantage:

  • Extrêmement performant (testé sur une table de 600 000 titres et un peu plus de 1 100 000 de mots)

Inconvénients:

  • Base de données plus lourde
  • Impossible de trouver « Tour eiffel » si la personne tape « ffel » comme peut le faire like ‘%bla%’

Archivage continu Postgresql avec WAL-E

La sauvegarde de sa base de données est une chose essentielle pour la pérennité de son site. Actuellement je fonctionne sur le principe très basique du dump (pg_dump) de toute ma base de données. Mais cette pratique est loin d’être optimum, et il faut effectuer des dumps assez régulièrement s’il l’on ne veut pas perdre trop de données en cas de crash.

Pour la sauvegarde, il existe un autre moyen avec Postgresql, qui consiste dans un premier temps à enregistrer une sauvegarde complète de la base, et ensuite de ne sauvegarder que les changements apportés à la base sous forme de fichiers WAL. Ainsi « terminé » les gros backups entiers de la base de données, et nous pouvons garder une trace de chaque action effectuée sur la base de données et les rejouer à n’importe quel moment (Point-In-Time Recovery).

Faire des sauvegardes c’est bien, mais faut aussi les sauvegarder quelque part ailleurs que sur le serveur. Sinon en cas de problème avec le disque dur, bye bye la BDD et bye bye les sauvegardes. Et pour cela il existe un très bon outil: Amazon S3. Je ne vais pas détailler ici comment utiliser S3, mais c’est vraiment simple.

Du coup, maintenant nous avons un outil pour effectuer un archivage continu de la base de données, et un outil pour le stockage.

Et il n’existerais pas un outil pour simplifier l’utilisation de ces choses ? Et bien si: WAL-E, à ne pas confondre avec Wall-E 😉

Toute la suite de l’installation se fait sur une Ubuntu 12.04.2 LTS avec Postgresql 9.1.

Installation de WAL-E

On commence avec l’installation des dépendances:

Téléchargement de WAL-E. Pour moi c’est la version 0.6:

Et installation:

Installation de Daemontools

Afin d’exécuter WAL-E dans un environnement sécurisé, nous avons besoin de envdir présent dans la suite Deamontools de D.J. Bernstein.

Préparation:

Téléchargement:

Décompression:

Attention, il est nécessaire de modifier un fichier de configuration afin de pouvoir compiler les daemontools sur Ubuntu.

Modifiez le fichier /package/admin/daemontools/src/conf-cc et ajouter « -include /usr/include/errno.h » à la fin de la première ligne (commande gcc):

Nous pouvons maintenant compiler:

Configuration de WAL-E

Dans un premier temps, nous allons préparer les variables d’environnement nécessaires à l’utilisation de WAL-E. Ces variables sont les informations de connexion à votre S3.

Pour retrouver access-key et secret-key-content, allez ici et connectez-vous.

Nous allons maintenant modifier le fichier /etc/postgresql/9.1/main/postgresql.conf avec les informations suivantes:

J’utilise le chemin entier pour appeler wal-e car sinon la commande ne fonctionne pas.

Il faut maintenant recharger Postgresql afin que la nouvelle configuration soit prise en compte:

Et voila la configuration est terminée !

Sauvegarde complète de la base

Maintenant il est nécessaire de faire un premier backup de votre base de données vers S3, et donc d’exécuter votre première commande WAL-E à partir de l’environnement sécurisé grâce à envdir.

Cela peut prendre quelques secondes à quelques dizaines de minutes en fonction de la taille de votre base de données et de la vitesse d’upload entre votre serveur et Amazon.

A la fin de cette commande, vous devriez trouver 2 nouveaux dossiers dans votre bucket S3. Un dossier pour les backups de base et un dossier pour tous les fichiers WAL.

De nouveaux fichiers WAL sont envoyés très régulièrement vers votre s3.

Restauration des données

Pour récupérer sa base après un crash, il suffit de créer un fichier recovery.conf, qui sera lu au démarrage de Postgresql. Se fichier se place dans /var/lib/postgresql/9.1/main/.

Il est possible de définir dans ce fichier une heure de restauration. Ainsi nous pouvons récupérer l’état de la base à moment bien précis. Si cette variable n’est pas définie, WAL-E essaie de restaurer l’état de la base au plus proche du dernier état.

Vérifier que le fichier recovery.conf appartient bien à postgresql. Sinon:

Maintenant il suffit de démarrer Postgresql

Vous pouvez suivre l’évolution du démarrage à partir des logs:

Une fois la restauration terminée, le fichier recovery.conf devient recovery.done afin d’éviter tout problème en cas de redémarrage du serveur.

Et voilà, votre base a été restaurée.

Créer une nouvelle base de données à partir des sauvegardes

Par exemple pour une machine de développement, il peut être nécessaire de recréer une machine avec une base de données.

Dans un premier temps, il faut bêtement installer Postgresql.

Ensuite supprimer toutes les données présentes dans cette base:

On récupère la dernière version de base avec WAL-E:

Une fois cela terminé, il suffit de reprendre toute la partie Restauration des données, juste au dessus, afin de récupérer la dernière version de la base.

Sauvegarde de base quotidienne

Il est peut être bien d’effectuer une sauvegarde totale de la base tous les jours, afin d’accélérer les remises en production en cas de crash. Ajoutez cette ligne à cron:

Sources:

http://jamesreubenknowles.com/centos5-daemontools-143
https://github.com/wal-e/wal-e
https://gist.github.com/ruckus/2293434

Simple upload en drag and drop avec HTML5 / Jquery / PHP

Il existe actuellement plusieurs plugins qui gèrent les uploads en drag and drop avec HTML5, et avec une pléthore d’options. Mais c’est bien là le problème. Encore un plugin lourd pour effectuer une action simple. Le but ici est de mettre en place un système permettant de télécharger une image sur un serveur, en glissant une image simplement dans une « dropbox » présente sur une page web ; rien de plus.

Posons les bases

Je commence juste par créer la dropbox de base :

Avec son petit code css :

 

Jquery

Je commence par initialiser tous les évènements liés au drag et au drop, afin d’éviter la propagation des évènements.

 

 

Un peu de CSS est rajouté afin d’avoir une petite animation suivant les différents évènements.

Maintenant je m’occupe de l’événement drop, qui va lancer toutes les actions à faire au moment où on va lâcher notre image dans la dropbox.

 

 

La fonction principale pour l’upload de mon image, commence par effectuer un contrôle sur le type de fichier, puis nous utilisons FileReader, un objet d’une API disponible avec HTML5 : File. Cet objet va permettre de lire directement le fichier depuis le navigateur.

La chose importante à comprendre avec la lecture de fichier depuis le navigateur, c’est que le traitement est asynchrone. C’est normal, le temps que la lecture de l’image se fasse, le script continu de tourner.

Je vais donc ordonner l’exécution d’une nouvelle fonction (handleReaderLoad), lorsque l’image sera chargée (reader.onload).

 

 

La fonction handleReaderLoad va s’occuper d’uploader l’image sur le serveur dès que l’image est chargée dans le navigateur.

Rien de bien compliqué ici, c’est juste une requête Ajax avec l’image encodée en Base64.

 

 

Coté PHP

Pour PHP, comme souvent sur ce blog, j’utilise CodeIgniter. Donc voici le contrôleur qui gère le décodage de l’image et qui l’enregistre dans un dossier.

 

 

Voilà avec ce simple code, il est maintenant possible d’envoyer rapidement une image en drag and drop de votre site vers votre serveur, pour une photo de profil par exemple 😉

Migration MySQL vers Postgresql

J’ai été amené à effectuer un changement de base de données, et après des journées de recherche/modifications/tests, je suis enfin arrivé à mes fins.

Pourquoi changer de base de données?

C’est vrai que je n’avais aucun problème avec MySQL, mais j’ai découvert PostGIS, un plugin qui transforme Postgresql en base de données spatiale. Et ce plugin très puissant va s’avérer très utile dans mon projet. C’est donc la principale raison qui m’a poussée à migrer.

De plus, le projet n’étant pas encore en production, le changement devait se faire maintenant. Mais des données importantes étaient quand même présentes, et il n’était pas question de juste faire une adaptation de schéma.

Préparation du terrain

Afin d’effectuer le transfert proprement, j’ai utilisé deux machines.

La machine avec MySQL 5.1 qui tourne sous Debian 6.0

La nouvelle machine avec Postgresql 9.1 qui tourne sous Ubuntu 12.04 (Afin d’avoir des paquets plus récents qu’avec une Debian)

Installation basique de la nouvelle machine

Création de la base de données

Posgresql utilise un utilisateur nommé postgres afin d’effectuer toutes les taches d’administration. C’est le superutilisateur.

Afin de protéger cet utilisateur, il est nécessaire de rajouter un mot de passe à celui-ci.

Ensuite nous pouvons nous connecter avec cet utilisateur à l’aide de la commande suivante:

Et accéder à la base de données:

Vous voilà connecté à Postgresql en tant que superutilisateur (un # est présent dans la ligne de commande).

Pour commencer, nous allons créer un utilisateur:

Lui ajouter un mot de passe:

Et lui donner les droits de création de base de données:

Maintenant qu’un utilisateur existe, vous pouvez créer votre première base de données:

Afin de pouvoir vous connecter à la base avec votre nouvel utilisateur, il faut modifier le fichier /etc/postgresql/9.1/main/pg_hba.conf qui gère toutes les connexions à Postgresql.

Dans l’état actuel du fichier, vous êtes obligé d’avoir un utilisateur système du même nom que celui que vous venez de créer pour pouvoir vous connecter. Personnellement je préfère bien scinder les choses.

Il faut donc remplacer la valeur peer par md5 au niveau de la ligne local all all :

La première ligne local all postgres peer doit rester intacte, afin de garder une certaine sécurité. Cette ligne veut dire: « Je peux me connecter à Postgresql avec l’utilisateur postgres que si je suis connecté au système avec le compte postgres ».

Maintenant pour se connecter avec votre utilisateur il suffit de faire:

Maintenant que Postgresql est prêt, nous allons pouvoir commencer la migration.

Création d’un dump propre pour Postgresql

Quand je dis création d’un dump, je ferais mieux de dire créations de plusieurs dumps. Car c’est le plus simple pour éviter les erreurs.

Afin de créer ces dumps, j’ai utilisé un outil qui m’a BEAUCOUP aidé: py-mysql2pgsql

Installation de py-mysql2pgsql

Normalement toutes les dépendances s’installent avec easy_install, si vous rencontrez des problèmes, essayez de les installer manuellement.

Dans un premier temps, il faut générer un fichier de configuration avec la commande:

Le fichier mysql2pgsql.yml est maintenant présent dans le répertoire courant.

Ce fichier est extrêmement simple à comprendre. Il y a une partie pour se connecter à MySQL, une autre pour l’export (soit vers un fichier, soit directement vers Postgresql) et une partie de configuration avancée.

Afin de tout contrôler, je n’utiliserai que l’export vers un fichier durant toute la migration.

Migration du schéma

Certainement la partie la plus délicate de la migration, et c’est ici que py-mysql2pgsql est d’une très grande aide, puisqu’il va convertir tous les types de données qui diffèrent entre MySQL et Postgresql.

Je configure le fichier mysql2pgsql.yml afin de ne récupérer que le schéma:

A vous de remplacer les informations propre à votre connexion à MySQL.

Un fichier schema.sql a maintenant été généré, et il est nécessaire de tout vérifier afin d’éviter les incohérences. Personnellement j’ai dû modifier des types integer qui étaient devenus des bigint.

Une fois le schéma validé, vous pouvez l’ajouter à votre base:

Voila une bonne chose de faite, la structure est en place. Maintenant nous pouvons ajouter les données.

Migration des données

Pour cette partie il faut y aller étape par étape, et ça peut être long.

Je vais ici vous expliquer la méthodologie utilisée plutôt que de faire un tuto puisque chaque cas est différent.

Dans un premier temps j’ai exporté les tables « mères » une par une, de la plus importante à la moins importante. Ce que j’appelle ici table « mère », c’est une table dont vont dépendre d’autres tables via des clés étrangères.

Exemple: Une table personne et une table voiture. Une clé étrangère est présente dans la table voiture afin de savoir à qui appartient cette voiture. La table personne est donc une table mère par rapport à la table voiture. Je dois donc ajouter les données de la table personne avant d’ajouter celles de la table voiture afin d’éviter des erreurs de contrainte. (J’espère être clair sur cette partie, je n’ai peut-être pas le bon vocabulaire).

Pour cela, il faut modifier le fichier mysql2pgsql.yml pour chaque table:

Ensuite, vous pouvez ajouter les données de la table directement dans Postgresql:

Si des erreurs apparaissent, vérifiez les données dans votre base MySQL. Il peut exister des incohérences qui troublent l’import. Cela a été le cas pour moi, une dizaine de lignes sur plus d’un million de lignes. Dans ce cas il faut corriger l’erreur et recommencer l’export avec py-mysql2pgsql jusqu’à temps qu’il n’y ait plus d’erreur.

Une fois que toutes les tables « mères » sont importés dans Postgresql, vous pouvez ajouter les tables restantes en une fois, en utilisant la condition exclude_tables dans le fichier mysql2pgsql.yml, pour exclure les tables déjà ajoutées.

Une fois que tout cela est terminé, la migration commence à se terminer.

Après les imports

Et oui, ce n’est pas encore terminé ! Un certain nombre de choses sont maintenant à vérifier, comme la création/modification de certains index, l’ajout des triggers, de fonctions, etc…

De plus il faut modifier un certain nombre de choses dans le code votre projet, car MySQL et Postgresql n’utilisent pas les mêmes fonctions.

Modifications pour CodeIgniter

Les modifications sont ici relativement simples, et doivent être adaptables pour d’autres frameworks.

Dans un premier temps il faut installer l’extension Postgresql pour PHP:

Et enfin, modifier le fichier /application/config/database.php:

Rien de plus n’est nécessaire pour connecter votre projet à Postgresql.

Sauvegarde de la nouvelle base

Maintenant que tout est propre au niveau de la base Postgresql, n’oubliez pas de faire un dump:

 

CodeIgniter avec Nginx

Depuis un moment je voulais essayer Nginx, puisqu’il est apparemment, bien plus performant qu’Apache. Donc je me suis décidé à passer le pas, et je vais expliquer ici ma démarche.

D’abord je vous conseille de lire cet article (en anglais) qui explique les différences importantes entre Apache et Nginx. Ca permet de savoir où on met les pieds.

Pour cette installation je travaille sur Ubuntu 12.04.2 LTS.

Installation

Dans un premier, il faut arrêter tous les services qui pourrait écouter sur le port 80 (http). Dans mon cas, j’ai besoin de stopper Apache

Ensuite on installe les paquets nécessaires.

Configuration de PHP-FPM

Une petite modification au fichier /etc/php5/fpm/php.ini est nécessaire afin d’empêcher un potentiel risque de sécurité.

Et redémarrer le service

Configuration de Nginx

Créer un fichier « nom_de_votre_domaine » dans /etc/nginx/sites-available et y ajouter ceci

Modifier les valeurs de server_name (votre nom de domaine) et de root (le répertoire où se situe votre site CodeIgniter) afin qu’ils correspondent à votre configuration.

Ajouter le lien symbolique afin d’activer le nouveau site

Recharger Nginx

Et voila, vous devez avoir accès à votre site via Nginx !

Source

Créer un site multilingue avec CodeIgniter

Version de CodeIgniter utilisé: 2.1.2

Les fonctionnalités souhaitées:

  • Affichage de la langue dans l’URL. Cela permet un meilleur référencement, avec un lien unique vers un contenu dans une langue donnée. (exemples: www.mondomaine.com/fr, www.mondomaine.com/en)
  • Détection de la langue du navigateur
  • Facilité d’évolution (ajouter une nouvelle langue)
  • Facilité d’utilisation pendant le développement

URI Language Identifier

Le vrai secret pour faire ce que l’on souhaite, est une extension de la bibliothèque Lang, disponible sur le wiki de CodeIgniter.

Cette extension permet d’afficher la langue dans l’URL et de modifier la config suivant cette langue. Si aucune langue n’est détectée, la langue par défaut est chargée.

Avec la fonctionnalité de base, on a déjà une bonne partie, mais nous n’avons toujours pas de détection de la langue du navigateur. Donc si la langue par défaut est l’anglais, qu’un utilisateur français accède à votre site sans langue spécifiée dans l’URL, il se retrouvera avec un site en anglais, alors que vous supportez aussi le français.

J’ai donc modifié cette extension afin qu’elle supporte la détection de la langue du navigateur lorsque aucune langue n’est précisée dans l’URL.

application/core/MY_lang.php

Voila, maintenant notre librairie répond parfaitement à nos attentes. Je vais maintenant vous expliquer comment la configurer, et comment l’utiliser sur votre site.

Configuration de la librairie

/application/config/config.php

$config[‘language’] représente la langue par défaut.

$config[‘language_abbr’] représente l’abréviation de la langue par défaut.

$config[‘lang_uri_abbr’] représente les langues acceptées par le site. Si vous souhaitez ajouter une nouvelle langue, c’est ici que ça se passe.

$config[‘lang_ignore’] permet de ne pas afficher la langue dans l’URL, et de seulement l’enregistrer dans un cookie. Ici cette fonctionnalité ne nous intéresse pas, donc FALSE.

application/config/routes.php

Maintenant il faut configurer les routes, puisque notre URL ressemble à ça : www.mondomaine.com/lang/controller/method/variables et ne correspond plus au modèle de fonctionnement de CodeIgniter: www.mondomaine.com/controller/method/variables.

Par contre, si vous souhaitez ajouter une nouvelle route, il faudra l’ajouter avant ces dernières et tenir compte de la langue. Exemple:

Voila maintenant tout est configuré et fonctionnel. Je vais maintenant vous comment utiliser tout cela.

Utilisation

Configuré c’est bien beau, mais comment je fais pour récupérer les bons textes suivant la langue ???

Tout se passe dans le répertoire application/language. Normalement vous avez un répertoire « english » qui est déjà créé. Il suffit de rajouter un nouveau répertoire pour chaque langue souhaitée.

Ensuite il faut créer un fichier de langue par répertoire de langue, ayant exactement le même nom et le suffixe « _lang ». Par exemple form_lang.php. Ce fichier de langue servira pour tous mes formulaires.

Ensuite le contenu de ce fichier est un simple tableau PHP.

application/language/francais/form_lang.php

application/language/english/form_lang.php

Maintenant il ne reste plus qu’à charger le bon fichier de langue dans le constructeur de votre contrôleur.

Pour l’utilisation, il suffit d’utiliser le helper présent dans l’extension de la librairie Lang:

Ensuite pour toutes les fonctions d’aide à la création d’URL (URL Helper), il faut utiliser base_url pour avoir l’URL du site (www.mondomaine.com), et site_url pour avoir l’URL avec la langue (www.mondomaine.com/fr).

Astuces

Pour les fichiers de langue en Français et autres, n’oubliez pas d’enregistrer en UTF-8 sans Bom afin d’éviter les erreurs.

Pensez à copier les fichiers de langue présents dans system/language/english vers vos nouveaux répertoires de langue afin d’avoir les erreurs affichées au moins en anglais.

Faire une recherche sur Geonames à partir de PHP

Geonames est une base de données géographiques sous licence Creative Commons qui contient plus de 8 millions d’éléments (villes, monument, parc, etc…).

Un webservice est mis à disposition afin de pouvoir récupérer tout un tas d’information facilement. Pour y accéder il suffit de créer un compte ici, tout est gratuit. Il y a une limite qui est très haute: 30 000 crédits par jour et 2000 crédits par heure. La taille du crédit change suivant le type de service web appelé, mais pour une recherche, un crédit = une requête.

Donc dans l’exemple qui suit nous allons rechercher « tour eiffel » et nous allons récupérer les coordonnés géographiques, ainsi que la traduction en Anglais.

Nous récupérerons les informations dans un XML.

Voila avec ce simple PHP on peut récupérer des informations sur une ville ou autre très rapidement.

Jetez un oeil au XML afin de voir toutes les informations potentiellement utilisables.