Développement web — Haltevent

Explication du fonctionnement interne de l’application.

(Certaines notions d’informatique sont indispensables pour comprendre cet article dans son entièreté mais cela ne vous empêchera pas de visualiser le processus complet de la concrétisation d’une idée. Si vous avez la moindre question n’hésitez pas à me contacter via mail ou par twitter).

Cela fait bientôt un an que je me suis acheté la dernière Raspberry (un petit ordinateur), sans savoir réellement quoi en faire. Branchée derrière un des quatre ports Ethernet de ma box, elle ronronnait là sans prendre de place. Je l’ai tantôt transformée en media-center, tantôt utilisée comme serveur pour les projets d’école.

En cette mi-août 2016, je me suis retrouvé confronté à cette problématique :

Je ne sais pas où sortir ce soir à {complétez ici avec le nom d’une ville}, à quelle heure, à quel prix et pour quels artistes.

Qu’on soit en déplacement à l’étranger ou bien tout simplement un peu déconnecté des actualités événementielles du moment, il est peu aisé de trouver son bonheur sans devoir remuer les contacts ou l’Internet auparavant. Et ça prend du temps. Sans forcément y parvenir.

Alors bien entendu, il y a le site Residentadvisor ou l’application Bandsintown qui permettent d’avoir un rapide aperçu de ce qui se passe autour de soi, mais rien de bien exhaustif dans leurs entrailles. Aussi, quand on pense événement, on pense Facebook. Gratuit et fort de ses 1,7 milliards d’utilisateurs, c’est le meilleur moyen pour une organisation/club de rallier les gens à ses festivités. Malheureusement, il faut auparavant connaitre la page, aller dans ses événements, vérifier le prix, la description, le lieu et moultes informations complémentaires susceptibles de nous intéresser. Réitérer ensuite l’opération avec toutes les autres afin d’être certain de ne rien louper. Oui, c’est long et chiant.

L’idée qui a donc germée est la suivante : pourquoi ne pas centraliser tous les événements Facebook sur un site avec des choix de filtrage par localisation, par prix, par artistes, par nombre de participants, par dates etc ?

Si cette idée vous semble moisie, vous avez tout à fait le droit. C’est même probable qu’elle existe déjà. Mais au delà de l’objectif final (qui sera au moins utile pour moi), c’est tout le processus de conception qui sera à même d’être le plus intéressant. Je compte aboutir ce projet courant Octobre. Afin d’être au goût du jour (et par curiosité permanente envers les nouvelles technologies), j’utiliserai les outils les plus récents à ma disposition :

  • Raspian 8 (fork de Debian pour Raspberry)
  • Nginx 1.1 (le serveur sûr)
  • Symfony 3.1 et Php7 (pour récupérer les événements de Facebook et les afficher)
  • ElasticSearch 5.1( pour enregistrer les événements de Facebook sur ma Raspberry, on verra pourquoi plus tard)
  • Ionic2 et Angular2 (je prépare le terrain pour la suite avec la plausible création d’une application Android/iOS/Windows Phone)
  • API Graph 2.7 de Facebook (pour accéder aux événements de Facebook)

Au cours de ce projet, j’essayerai aussi d’éviter au maximum l’utilisation d’obscures libraires afin d’avoir le code le plus généraliste possible (adieu donc les classes PHP des api Facebook et Elasticsearch. Tout se jouera directement en HTTP). Ce projet devait initialement s'appeler “Eventail” (petite dédicace à la commande UNIX “tail”). Mais au final, le grand fana de série Halt & Catch Fire que je suis a décidé de le renommer “Haltevent” (pas plus mal pour le SEO).


Le développement d’un site/application web est divisé en au moins deux parties : ce que l’utilisateur voit sur son écran (aussi appelé “frontend”) et ce qu’il ne voit pas (“backend”). Par exemple, lorsque vous vous connectez à votre compte sur n’importe quel site, vous ne voyez pas l’algorithme qui fait en sorte de rechercher votre nom et votre mot de passe dans la base de données . Vous voyez simplement un petit message qui affiche une erreur ou un succès. En général, le frontend est confié à une armée de designers et le backend est confié à une armée de mathématiciens essayant d’optimiser les algorithmes et les processus présents sur le serveur (j’exagère et je caricature mais le principe est là). Pour résumer :

https://s6.postimg.io/e8udn4qtd/Website_Frontend_and_Backend.jpg

Lorsqu’un dévelopeur sait gérer ces deux environnements, on dit qu’il est “fullstack”.

Cette première partie va concerner le backend du site et la mise en place des différents outils cités auparavant. Voici un schéma de ce que nous allons traiter ici :

La procédure d’installation des dernières version de Nginx et de PHP sur Raspberry est détaillée sur ce lien qui explique en détail les étapes à suivre. Ça a marché du premier coup pour moi donc je ne vais pas en parler plus ici. Le téléchargement de Symfony3 n’est pas nécessaire (une simple connaissance en PHP suffira) mais il nous permettra de structurer notre site selon le modèle MVC. Nous allons le placer dans notre répertoire /home/pi/sites/.

Pour ce qui est de la configuration de Nginx avec Symfony, le fichier complet est sur le site du développeur. Si vous décidez comme moi d’utiliser PHP7, pensez néanmoins à remplacer la ligne :

fastcgi_pass unix:/var/run/php5-fpm.sock;

par

fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

Et aussi bien entendu le chemin vers notre Symfony récemment téléchargé, qui dans mon cas est :

root /home/pi/sites/web;

à la place de

root /var/www/project/web;

N’oublier pas de redémarrer ensuite le service Nginx avec la commande

sudo service nginx restart

Le framework Symfony est maintenant fin prêt à être utilisé en localhost. Son utilisation permet d’avoir accès à différentes interface de supervision. Pour cela, commentez la structure “if” du fichier /home/pi/sites/web/app_dev.php. Si vous souhaitez le voir d’un ordinateur situé sur le même routeur, tapez “ifconfig” dans votre terminal raspian et copiez l’adresse de “inet addr” dans votre navigateur, suivi de /app_dev.php. Chez moi par exemple il suffirait de taper “192.168.0.11/app_dev.php” dans le navigateur. Si vous souhaitez y accéder de l’extérieur de votre réseau, renseignez-vous sur ce lien et n’oubliez pas d’ouvrir le port 80 tcp/udp de votre box.

Capture d’écran du backend Symfony3

Je ne vais pas passer en revue le fonctionnement de Symfony car c’est déjà fait et refait. Sachez juste qu’il apporte des outils qui peuvent se révéler être très intéressants pour la suite et que c’est un framework PHP. Si vous savez vous en servir c’est un plus. Sinon la documentation est facilement compréhensible pour un développeur.


Tous nos outils sont en place, exceptée notre base de données Nosql Elasticsearch. Afin de récapituler le tout, voici un aperçu de ce que nous avons accompli jusqu’ici :

Les poupées russes du web

Le Système d’Exploitation (= Operating System ou OS en anglais) permet de lancer le programme Nginx qui n’est autre que le serveur qui permettra au langage PHP de s’exécuter. Langage utilisé par Symfony qui n’est autre qu’un squelette d’application (ou framework) dans lequel nous allons coder ! Il est important de savoir que seul le framework n’est pas obligatoire pour un projet web.

Essayons maintenant de réfléchir à ce dont nous avons besoin pour atteindre notre objectif. Nous voulons capturer les événements de Facebook de certaines pages et les afficher sur notre site selon quelques filtres et quelques recherches. Il faut tout d’abord savoir que ça ne dérange absolument pas Facebook que vous piochez dans ses données (c’est d’ailleurs le principe de l’API). La liste entière de ce que vous pouvez lui soutirer est disponible ici. Cependant ce qui nous intéresse se situe là. Grâce à ce petit outil, je vous fais confiance pour tester un peu tout ce qui vous passe par la tête. Pas trop non plus cependant car il faut savoir que pour limiter le nombre de demandes faites par les usagers de ce service, Facebook donne un jeton (ou token) à chacun permettant de l’identifier afin de limiter son accès. En théorie, un jeton est limité à 200 appels vers ses données, par heure. Si vous êtes seul à l’utiliser, le danger devrait être écarté. Mais concernant un projet comme celui-ci, c’est loin d’être le cas, il faut donc trouver une parade. C’est là qu’ElasticSearch interviendra.

Mais mettons tout d’abord l’API de Facebook en pratique !

Afin de récupérer les événements d’une page, il nous en faut tout d’abord une : https://www.facebook.com/SndMtn/. Son nom est ici “SndMtn”. Si nous l’injectons dans l’API de Facebook cela nous donne (attention, le token est peut-être expiré donc le lien sera mort mais le principe reste le même) :

https://graph.facebook.com/v2.7/SndMtn/events?access_token=EAACEdEose0cBAO7pgk7ZBZBekz2fzm4fbi2tdLEGUdb4ZBlE9ybN8yhMlr0a2FYpr00W2Gfrnq2V4zkug5qXJFIEVDJFbVBqzatnyF0ha5evsmYEmzDEAgcuczj5zpE5S1DeowdMcigwFZBUdtlOhf06TyMye0ePXWrkCtokDwZDZD

Cet url est de la forme https://graph.facebook.com/{version de l’api}/{nom de la page}/events/access_token={notre jeton personnel}. Le résultat est le suivant :

Nous recevons tous les événements de la page SndMtn, hurra ! Néanmoins, c’est illisible pour l’instant, mais ce format appelé JSON est très facile à retravailler en PHP pour être affiché en frontend ensuite.

Imaginons maintenant que la page décide de changer de nom, nous serions bien embêté car notre url ne fonctionnerait plus ! C’est pour cela que nous devons nous rabattre sur un attribut bien plus fiable : l’ID de la page. Un outil est disponible ici et permet cette conversion. A la place de https://graph.facebook.com/v2.7/SndMtn/events nous avons donc maintenant https://graph.facebook.com/v2.7/ 343457565765698/events. C’est moche mais plus stable.

Le début du code va donc consister à initialiser une liste d’ID des clubs/pages qui nous intéressent (cette étape sera manuelle dans un premier temps mais pourquoi pas permettre aux utilisateurs d’ajouter à terme leurs propres lieux fétiches):

Une fois cette dernière créée, nous allons nous attarder au plus gros de la tâche : tout insérer dans Elasticsearch. Téléchargez le tout d’abord ici. Et suivez les consignes d’installation disponibles . Contrairement aux bases de données relationnels, il y a aucun schéma à configurer donc vous êtes déjà prêts ! Je vous conseille en revanche d’installer le plugin Head qui vous permettra de visualiser votre base ElasticSearch afin de déceler d’éventuelles modifications/ajouts. Enfin, si vous êtes sous Chrome, prenez le plugin Sense qui vous permettra de faire des tests avec la base sans avoir besoin de passer par PHP.

Il n’y a pas de schéma ici, en revanche il va falloir réfléchir à la façon dont on va enregistrer nos événements. En effet, Elasticsearch nous permet de classer un minimum nos données afin de ne pas devoir chercher partout à chaque fois pour accélérer le processus.

http://192.168.0.11:9200/{index}/{type}/

Nous avons donc la possibilité de choisir le nom de l’index et du type. J’ai décidé de mettre “events” pour l’index car cela regroupera tous les événements. En type, j’ai mis l’ID du club. En effet, tous les événements appartenant au même club seront donc sous le même type.

http://192.168.0.11:9200/events/{ID_CLUB}/

N’oublions pas que les utilisateurs voudront aussi certainement avoir de plus amples informations concernant le club. Nous allons donc ajouter un second index “club” et nous allons tous les classer par ville (c’est un choix personnel) :

http://192.168.0.11:9200/clubs/{VILLE_CLUB}/

Il y a donc 2 étapes : enregistrer les clubs dans un index puis les événements dans un autre.

Puis à la suite pour chacun de ces clubs, vérifier ses événements :

Le premier passage sera douloureux car nous allons devoir enregistrer TOUS les événements et les pages. Par la suite, nous n’enregistrerons que ceux dont nous n’avons pas l’ID (car oui, tout comme les pages, les événements possèdent aussi des ID qui permettent de les identifier de façon unique).

Et voilà ! Nous avons capturé 8200 événements au total ! Il n’y a plus qu’à faire une belle l’interface et à filtrer les recherches des utilisateurs.