Tag : symfony2

new-york

Notifications temps réel via Symfony2 + NodeJs + Redis

Dernièrement, j’ai développé une super appli PHP Symfony2. Une feature de dernière minute est apparue comme par magie dans la tête du client (NON CA N’ARRIVE JAMAIS) et c’était des notifications en temps réel pour les utilisateurs.

J’ai hésité à faire directement de l’ajax polling, puis j’ai découvert une solution bien plus sexy.

tumblr_m3wo9r9Jjc1rrlbpeo1_250

Utiliser un adaptateur SocketIO pour PHP, un serveur NodeJS et Redis !

Bref, aujourd’hui on va apprendre à rajouter dans votre appli Symfony existante des interactions temps réel.

 

Bon déjà, comment ça marche ?

D’abord, il faut que je vous explique chacune des technos utilisées.

 

NodeJS: A part si vous avez vécu dans un trou ces 5 dernières années, vous en avez déjà entendu parler. Il s’agit d’une plate-forme côté serveur faite en JavaScript. NodeJS c’est un ensemble de librairies, un environnement d’exécution mais aussi une machine virtuelle ! NodeJs se distingue par son aspect asynchrone (ça été fait pour) et sa forte résistance aux montées en charge.

 

Redis: Une base de données clef-valeur avec la particularité intéressante que tout est stocké dans la RAM.
Autant vous dire que niveau performance ça envoie violemment du steak. Il y a une partie événement intéressante dans Redis :  le système SUBSCRIBE/PUBLISH.
Subscribe peut écouter un canal de communication et Publish peut envoyer un message dans un canal. On va s’en servir ici !

 

SocketIO: Il s’agit d’une bibliothèque JavaScript pour les applications web qui permet le temps réel, elle comporte deux parties : une côté client qui fonctionne dans le navigateur et une côté serveur pour Node.js.
Elle utilise le protocole WebSocket mais avec un fallback en Ajax Pooling. Ce dernier détail fait fonctionner SocketIO même sur l’ordi de mamie avec son super IE 5.5 (rien que ça).
Ici on utilisera également un adaptateur PHP de socket IO !

 

Le plan c’est qu’on va installer l’adaptateur Socket IO en PHP coté Symfony2.
Il nous permettra d’envoyer un signal (emit) quand on le souhaitera dans notre controller au serveur NodeJS et à Redis.
Ces derniers seront en écoute permanente d’un signal, une fois reçu ils enverront également un signal à tous les clients connectés en temps réel.
EASY ! Allez go on se lance.

 

Le roi et ses serviteurs

throne

Commençons par NodeJS et Redis!
Je pars du principe que vous êtes sur une distrib’ linux debian/ubuntu.
Vous n’êtes pas sur Linux ? Sérieusement ? Bon bah vous pouvez utiliser ce fabuleux outil pour l’install alors, l’installation est simple sur toutes les plateformes.

Mais c’est encore plus simple dans la console de votre Linux :

Oui on installe NPM avec car on va avoir besoin de quelques modules NodeJS pour faire fonctionner notre solution.
D’ailleurs n’hésiter pas à redémarrer votre PHP, notamment pour la prise en compte de l’extension Redis.

N’oubliez pas de lancer aussi votre serveur redis, sans quoi vous allez avoir de la belle erreur de connexion!

 

Maintenant faites vous un petit dossier dans un coin, quelque part sur votre serveur, et installons ces modules à cet endroit.

On installe donc socket.io côté serveur pour NodeJS, Express qui est notre framework web coté Node et enfin Redis.

Une fois que tout est installé on va créer notre serveur JS !
Pour se faire, créons un fichier « app.js » dans votre dossier qui ressemble à ça :

/path/to/server/app.js

Enfin vous pouvez lancer votre serveur :

Rien ne se passe, oui, c’est normal, votre serveur tourne et attend des news du channel de notifications.
Retour sur notre projet Symfony 2!

 

Le FUN pour tous en live !

fun-live

On va commencer par installer notre adaptateur socket IO PHP et on va utiliser celui là via composer.
Allez a la racine de votre projet et lancer l’installation :

Comme vous pouvez le constater, il s’agit d’une librairie et pas d’un bundle, donc elle ne sera pas automatiquement chargée !
Pas de problème on va la rajouter manuellement.
Rendez-vous dans votre fichier autoload, on va insérer notre namespace de la façon suivante :

/app/autoload.php

Désormais le namespace « SocketIO\Emitter » pointera vers notre librairie installer dans le vendor grâce à composer. On pourra l’utiliser à tout moment dans notre controller !

Allez hop sans plus attendre direction ce dernier :

/src/Acme/AcmeBundle/Controller/DefaultController.php

Alors concernant le controller:

Dans la première partie on a juste créé un formulaire vide, on va l’utiliser pour déclencher notre process d’emit.
Une fois le formulaire validé, on instancie Redis, on s’y connecte, on crée un emiter et on envoie un message sur le channel notification.
On renvoie enfin au JSON ce qu’on a envoyé au front, pour avoir l’info que tout s’est bien passé.

Si le formulaire n’a pas été validé (première entrée sur la page) on renvoie le template suivant :

/src/Acme/AcmeBundle/Resources/views/index.html.twig

Dans ce template on commence très simplement par afficher un formulaire vide.
La partie intéressante est dans le block javascript. En effet, on appelle la librairie de socket IO (ici directement sur le cloud, à vous de voir) ainsi que jQuery.

Ensuite on se connecte au socket sur notre serveur Node.
On écoute le channel notification, à la réception d’un message sur ce channel de la part du serveur on ajoute une ligne dans la div serveur.

Enfin, on écoute la soumission du formulaire et ont le POST en AJAX. Si tout ça se passe bien on indique dans la div client qu’ons as bien envoyer le message.

 

Voilà, ouvrez deux fenêtres de navigateur, et commencer à valider tour à tour les formulaires dans chacune des fenêtres, vous allez voir que tout se fait en temps réel dans chacunes des fenêtres !

 

dealwithit

Epilogue

Je n’en parle pas mais je vous conseille d’aller voir la documentation de l’adaptateur socket, en effet vous y trouverez les notions  de broadcasting qui peuvent être très utiles dans beaucoup de cas!
Enfin sachez qu’il existe des bundles (implémenter via une librairie) comme Elephant.io qui peuvent vous aider aussi bien que ma solution !

Categories: NodeJS, PHP, Symfony2

spacejump

Upload drag & drop via DropZoneJS + Symfony2 sur le CLOUD Amazon S3

Glissez-déposez dans le CLOUD

Si ça c’est pas la classe !

Hop un drag & drop depuis l’OS d’un paquet d’images dans une zone de la page qui fera l’upload direct dans le CLOUD Amazon S3 !
Ho et puis en plus, avec une belle présentation génération de thumb dynamique pour chaque images et une barre de progression pour que notre utilisateur s’impatiente pas trop !
Le tout avec une gestion multi-upload, des events et de la customisation à gogo! Que demande le peuple ?

Aujourd’hui on va voir comment réaliser ça avec DropZone, une librairie javascript, et notre merveilleux framework Symfony 2 avec le bundle SonataMedia.

 

Javascript sans les mains

On aime le javascript, mais pas besoin d’en faire ici ! En effet DropZone nous facilite la tâche.

Alors, commençons par le commencement :  Télécharger DropZone et mettez les fichiers dans votre « /Resources/public/js  » et  « /Resources/public/css »du bundle de votre choix !

Détails qui a son importance, DropZone n’a pas besoin de jQuery !

Notre template twig va s’appeller « dropzone.html.twig »  et va ressembler à ça :

Alors on a fait quoi ?

– On a étendu notre template layout de base. Basique me direz vous ? Je suis d’accord mais je fait juste un copier coller ici  !

– Ensuite,  on a appelé notre block stylesheet pour le css de base de dropzone en utilisant Assetic avec le bon gros filter des familles « cssrewrite ».

– Le block body sur lequel on va mettre un formulaire de base en Symfony2. Point important :  la class « dropzone » et le action en « app.request.uri » qui sont primordiales au bon fonctionnement de DropZone !

– Enfin notre block javascript avec le script DropZone. Le tout forcement via Assetic et un bon gros filter « yui_js » des familles ! Voir comment faire fonctionner cet merveille. OUI vous en avez besoin !

Et mon petit script d’instanciation hein ? Mon petit javascript il est ou ?

Hé bien nulle part ! Pas besoin la petite classe « dropzone » sur la balise form déclenche le script et met en place toute la machine ! Sans les mains je vous ai dit.

Bon si vous voulez vraiment faire du  javascript sachez que c’est possible, notamment si vous voulez créer une zone de drop à la volée ou l’intégrer à un formulaire déjà existant etc etc :  Rendez-vous sur la page de dropzone dont j’ai donner le lien plus haut.

 

Media management bundle on steroid !

Hey vous connaissez SonataMediaBundle ? C’est une des solutions de gestion de médias que j’utilise le plus, tant pour sa puissance que pour ces possibilitées !
Seul vrai problème : il a des dépendances, dont le générateur d’administration SonataAdminBundle. Il faut le savoir avant de vous lancer dedans !
Mais si vous avez prévu un magnifique backoffice dans votre appli ou si vous voulez tout simplement le découvrir, je vous le recommande chaudement ! Parole de dev : Ça vaut vraiment le coup !

De toute façon la suite de l’article est basée sur Sonata Media. On installe tout ça et on revient.

Une fois que tout fonctionne on s’attaque au controller qui devrait ressembler à ça :

Ici on a créée un formulaire vide. Au post et après validation on as instancié un media auquel on rentre les infos nécessaire, dont le fichier image.
Ensuite on utilise le service de management des médias pour l’enregistrer. Enfin on envoie notre formulaire au twig. EASY !

En l’état ça marche !! WOOOT ! Sauf que sans toucher au config de base du bundle de média, votre image sera bien uploadée, mais sur le disque de votre serveur. C’est cool mais sans plus !

Une envie de faire un tour dans les nuages ?

 

 Il est temps de parler directement au CLOUD

tim-and-eric-mind-blown

 

Je suis tomber sur le service Amazon S3 un peu par hasard comme souvent en cliquant partout quand je voyais un truc intéressant.Et je dois dire que ça ma tout de suite séduit ! Tous les avantages pro mais aussi et surtout le niveau gratuit d’AWS qui comprend :  5 Go de stockage, 20 000 requêtes GET et 2 000 requêtes PUT disponible  sans frais d’installation sans abonnement. Bref, c’est totalement un compte de test ! Et on aime ça tester des choses :)

Par contre, je vous préviens, en plein milieu de l’inscription il vous demandent votre numéro de carte bleu les coquins ! Hé oui le compte à beau être gratuit et n’empêche que vous utiliser leur serveur  dans le cloud avec des services hyper pro (console web, api et tout ce qui va avec). Si vous dépassez les limitations ils vous factureront. Ceci dit pas de panique,  avec le calculateur de coût d’Amazon vous pouvez vous donner un ordre d’idée des coûts.

Mais peut importe le prix finalement, ça ne vous concerne pas. Faite vos tests avec, amusez vous un coup et supprimés simplement les images de votre espace, ou mettez les simplement en privé. Rappelez vous que vous ne payez que ce que vous consommez !

Bref vous êtes inscrit ? Très bien on peut passer à la suite.

– Aller dans la console. Cliquer sur « Identity and Access Management » puis « Users ». Vous l’aurez compris on va créer un utilisateur. Il pourra taper ensuite sur votre espace via des clefs privées.

– Cliquer sur « Create new users » rentrer un nom d’utilisateur et pensé bien à cocher la case « Generate an access key for each user ». Une fois votre utilisateur crée ils vous filent deux clef : « Access Key ID » et « Secret Access Key » copier/coller dans un coin on en aura bientôt besoin.

– Retourner à la console, cliquer sur « S3″, puis cliquer sur « Create Bucket ».

bucket

– Mettez un nom a votre « seau » en Français et choisisser une région. L’Ireland c’est le plus prés, alors c’est parti.

– Une fois dans l’interface, cliquer sur le nom de votre Bucket, cliquer sur « Properties » en haut à droite, puis sur « Permissions » dans le menu qui apparaît. Cliquer sur « Add more permissions » puis donner l’accès à votre utilisateur créé juste avant comme ci-dessous :

permissions

 

– Dernière étape cliqué sur « Add bucket policy ». Par défaut, personne ne peut faire de requêtes sur votre bucket, pas même vous ! Il faut donner l’autorisation à internet de consulter vos images. Pour ce faire, copier/coller ce bout de code dans la fenêtre qui apparaît :

Pensez à remplacer « examplebucket » par votre nom de bucket. Ce petit bout de code permet à n’importe qui (avec l’adresse) de consulter les images que vous aurez mit sur votre bucket.

Vous pouvez le changer à volonté et à tout moment, consulter la liste officiel des bucket policies d’Amazon pour plus d’info. Sachez juste que vous pouvez tout fermer, tout fermer sauf pour une IP, interdire le hot linking. Bref vous avez le contrôle.

 

Retour à notre code : on va commencer par installer le SDK pour PHP d’Amazon. Dans le composer.json :

Un coup de composer

Etape finale direction le fichier config : app/config/config.yml et mettez les directives suivantes pour sonata media.

Et voila !

Re-Uploadé donc une image et tout se fera automatiquement !
Félicitation, vous êtes dans le CLOUD, vous pouvez laisser exploser votre joie.

14038303339

 

 

Epilogue

Je n’ai pas insisté dessus du tout, mais coté front, vous pouvez tous faire. Ecouter des événements, changer l’affichage de la zone de drop mais aussi les petites thumbs générées automatiquement jusqu’à la barre de progression. Aller voir sur la page officiel, tout y est.
Si vous ne voulez pas de SonataMedia, la même solution est possible si vous gérez l’enregistrement des médias vous même, mais il vous faudra utiliser également le SDK à la main.
Enfin sachez que si vous détestez Amazon, Google à également des solutions similaires.

Categories: CLOUD, PHP, Symfony2

giphy

ElasticSearch : Explication, Introduction et mise en pratique via FOSElastica Bundle

Le client veut une recherche de dingue !

Et oui y’en as marre de la recherche toute pourrite à base de like en sql ! Non, on veut du gros, du gras, de la recherche phonétique  sur laquelle on met du filtre et le tout (presque)instantanément. Oui on veut de l’elasticsearch !

Mais elasticsearch c’est quoi ? Et bien c’est un moteur de recherche open source écrit en java basé sur Lucene. Il utilise une base de donnée NoSQL, codé au format JSON, qu’il indexe et interroge via une API rest.
Autrement dit via une requête HTTP PUT il va remplir et/ou mettre à jour ces fichiers JSON (la base de donnée) et via une autre requête HTTP GET il va accéder à ces données, et nous renvoyer ce qu’on recherche dans notre cher projet.

Il y en d’autres hein, comme dans tout rest le POST et le DELETE sont de la partie aussi.

 

We need to go deeper

OK mais comment ça marche la bête ? Pour comprendre il faut connaitre les termes utilisés dans le monde elastic.

Cluster : Le cluster est formé d’un ou plusieurs nodes. Le cluster va accueillir tout nos nodes et donc toutes nos données. Un cluster est formellement identifier  par un nom. Par défaut ce nom est ‘elasticsearch’ mais on peut le modifier comme on le souhaite. Vous y viendrez si vous voulez plusieurs clusters.

Node : C’est une instance d’elasticsearch. Il fait partie de votre cluster comme dit plus haut. Il stocke vos données, participe à l’indexation mais aussi à la recherche. Comme le cluster, le node est identifié par un nom. Par défaut il lui est attribué un nom de héros Marvel (!!). Je vous conseille Iron Man, car Iron Man il est cool. Un node peut être configuré pour joindre un cluster spécifique par le nom de ce dernier, par défaut il cherchera à aller dans le cluster ‘elasticsearch’. Donc si vous ne touchez à rien et que vous lancer plusieurs nodes sur votre serveur, vous aurez alors plusieurs héros Marvel qui vont tout se joindre au cluster ‘elasticsearch’ ensemble. Tout  ça sachant que vous pouvez avoir autant de nodes que vous voulez dans un cluster.

Index : Un index est une collection de document qui ont tous un point commun. Un index peut regrouper tous vos utilisateurs, un autre tout vos articles. En faite vous pouvez mettre n’importe quoi à partir du moment ou ces données on un point commun et qu’il est logique de les classer dans le même index pour une recherche.

Type : Il s’agit du typage  des index. Par exemple dans votre index article vous pouvez les typer par article sur Symfony2, Doctrine, MySQL etc etc..

Document :  C’est dans le document qu’est représentée la donnée. Elle est organisée avec des champs. De la même façon qu’une table avec des champs en MySQL. Cependant ici il s’agit d’une représentation NoSQL en JSON.

 

Installation

Je vais ici montrer la manière d’installer elasticsearch en services sur Linux Debian/Ubuntu.

Si vous n’êtes pas sur Linux ou si vous ne souhaitez pas l’installer en service allez voir de ce coté la.

On doit d’abord installer JAVA indispensable au bon fonctionement d’elastic :

 

On va chercher le package via wget

On installe ensuite notre paquet

Par défaut elasticsearch n’est pas configuré pour redémarrer à chaque reboot serveur. On trouve cependant dans la documentation officiel une commande pour ça:

Si vous souhaitez changer de nom de cluster et/ou de node ça se passe dans un fichier de config YAML à cette emplacement : /etc/elasticsearch/elasticsearch.yml

Quand tout est prêt lancer votre service comme n’importe qu’elle autre service :

Pour savoir si votre elasticsearch marche bien rendez-vous à cette adresse : http://localhost:9200

 

Les API REST c’est le bien

hap

Et oui, c’est le bien, et elastissearch l’utilise et en abuse !
Ce format bien précis est utilisé pour y accéder :

Pour qu’elastic puisse trouver vos données il va falloir les indexer, cet à dire stocker tout ce que vous voulez dans sa base de données à lui.

Commençons par le commencement pour comprendre on va utiliser notre bon vieux terminal et on va indexer des données via CURL :

Alors qu’avons nous fait ici ?

On as simplement indexer notre article, via un PUT, dans l’index ‘article’ et le type ‘elasticsearch’, que nous avons créés au passage, on y a mit quatre champs avec des données qui sont désormais accessible à une recherche !

Un joli message de type « {« _index »: »article », »_type »: »elasticsearch », »_id »: »1″, »_version »:1, »created »:true} » a dut apparaître nous indiquant que tout c’est bien passé, on peut maintenant faire une recherche !

OUI ! Nous avons fait une recherche sur oui et Elastic malin comme il est, il à trouvé quelque chose :

{« took »:2, »timed_out »:false, »_shards »:{« total »:5, »successful »:5, »failed »:0}, »hits »:{« total »:1, »max_score »:0.067124054, »hits »:[{« _index »: »article », »_type »: »elasticsearch », »_id »: »1″, »_score »:0.067124054, »_source »:{
« titre » : « ElasticSearch est le meilleur moteur de recherche »,
« contenu » : « Oui en effet »,
« date » : « 2012-12-21T00:00:00″,
« url »: « http://www.jesuisundev.fr/introduction-explication-elasticsearch/ »
}}]}}

C’est bien nos données et il est a trouvées car le mot ‘oui’ y apparaît !

De base il y a des trucs bien sympa genre :

Le mot oui est mal orthographié et pourtant  notre article est trouvé  grace au caractère : ‘~’ .

Il s’agit ici d’un seule épisode de ce que propose l’API d’elastic. La série entière est ici.

 

 OK c’est cool mais on va pas tout se taper à la main

Bien sur que non et c’est la qu’intervient nos amis de chez FOS et leur bundle !

Alors, je sous-entend que vous bosser sur Symfony2. Bien sur, vous bosser sur Symfony2 hein ? Non?! Bon sinon il y a l’api PHP officiel  par la.

Concernant l’installation, je ne reviens pas dessus c’est clair, simple et limpide sur le Github.

Par contre au niveau de la  config on va regarder un petit peu :

Ici nous avons indiquer que notre host est la maison (localhost) et qu’il faut taper sur le port 9200.

Ensuite nous avons indiquer que l’index ou stocker nos données est ‘jesuisundev’. Nous avons demandé l’indexation de deux types dans cette index : ‘article’ et ‘user’.

Nous avons choisit qu’elle champs de notre entité sont indexés,  mais surtout demandé au bundle d’utiliser nos entités via doctrine ORM.
Le listener est la pour savoir quand et comment indexer vos nouvelles données.

Le tout étant évidement configurable, vous trouverez plus d’info par ici.

Cette commande dans votre terminal et la magie opère ! Tout ce qui trouve dans votre entité sera indexé de façon automatique et disponible à la recherche ! Un petit coup d’utilisation de service est il  y à plus qu’a afficher !

Épilogue

On pourrait écrire un livre sur Elasticsearch. En fait on pourrait faire plusieurs tomes.

Ici nous avons juste fait une introduction basique sur une première utilisation.

Mais cet outil est fait pour aller beaucoup plus loin, des recherches phonétiques, de la pluralisation, de l’adaptation à chaque langue, l’utilisation de facettes, des filtres à gogo et bien d’autres vous attendent avec ce fabuleux outil qui s’appelle google.

Ou alors, vous attendez mon second article la dessus 😉

Categories: PHP, Symfony2