I’ve just released a new Symfony bundle to use easily the PHP TorControl library with the framework. TorControl is a library I’ve wrote designed to control a Tor server using the control socket.
Install the bundle using Composer. Type this command in your Symfony project directory:
Enable the bundle, edit your app/config.yml to match your Tor server configuration (look at the README.md file) and get a TorControl instance using the Symfony’s service container. In a controller implementing the ContainerAware interface:
TodoMVC est un projet présentant de nombreuses implémentations de la même application de gestion de tâches (todo) à l’aide des frameworks JavaScript MV* les plus populaires (Backbone.js, AngularJS, Ember.js, KnockoutJS…). Il permet ainsi de découvrir ces frameworks et de choisir celui qui nous semble le plus adapté.
L’ implémentation que je propose contient le code du frontend, mais aussi le backend réalisé à l’aide de Symfony.
Le bundle fourni un example d’intégration complète de Backbone, Chaplin et Symfony. Il inclus une API REST JSON réalisée à l’aide de FOSRestBundle et du framework de formulaire de Symfony, l’entité Doctrine représentant un Todo, le code CoffeeScript de l’application cliente, la vue chargeant la SPA et quelques tests fonctionnels.
TodoMVC is a project which offers the same Todo application implemented using MV* concepts in most of the popular JavaScript MV* frameworks of today.
This a backend and frontend implementation of this project. It is a demo of Chaplin and Backbone working with Symfony.
My bundle includes a JSON REST API built with FOSRestBundle and the Symfony’s form framework, the Doctrine entitiy, the view to load the SPA, the CoffeeScript code and some functional tests.
Le développement d’applications web modernes de qualité est une tache complexe : elles doivent être performantes, réactives, maintenables, modulaires, évolutives et, à minima, être compatibles avec la diversité de navigateurs et de plateformes avec lesquelles elles seront utilisées (ordinateurs, tablettes, smartphones…). Elles doivent s’intégrer avec un nombre croissant de services tiers (Facebook, Twitter…). Elles doivent pouvoir être déployées sur des hébergements classiques comme sur des plateformes de Cloud Computing.
Pour réussir, la partie client de l’application doit désormais être tout aussi soignée et bien conçue que la partie serveur. Heureusement de nombreux composants logiciels permettent d’accélérer et de fiabiliser ces développements. Encore faut-il savoir choisir dans cette jungle des bibliothèques et de frameworks puis les faire fonctionner ensembles.
Question choix, pas d’inquiétudes, je les impose !
Côté client je me baserais sur la bibliothèque Backbone.js, une étoile montante du monde Javascript, via Chaplin.js. Backbone permet de synchroniser très aisément les données d’une application cliente via des appels à une API REST côté serveur. Le framework Chaplin.js qui repose sur Backbone propose un structure de projet et quelques fonctionnalités bien utiles comme le support des modules AMD et une implémentation des design-patterns usuels.
J’écrierais le code client en CoffeeScript, une syntaxe alternative à JS inspirée de Ruby mais vous n’êtes pas obligés de faire de même.
Je vais m’employer à décire au long de deux articles l’utilisation conjointe de ces deux technologies. Dans le premier nous installerons et configurerons ces composants pour qu’ils fonctionnent ensembles. Dans le second je réaliserais un microblogune implémentation de TodoMVC. Sa partie serveur sera réalisée avec Symfony sous la forme d’une API REST / JSON directement compatible avec sa partie cliente réalisée à l’aide de Chaplin.js et Backbone.js.
Pré-requis
Connaissances
maîtrise de PHP et de la programmation orienté objet
bonnes notions du développement avec Symfony 2
maîtrise de JavaScript
notions de CoffeeScript si vous souhaitez utilisez cette syntaxe
si vous souhaitez utiliser la version Coffee de Chaplin.js il faudra bien entendu CoffeeScript, qui lui même dépend de Node.js et de NPM
Si vous utilisez Mac OS X je ne saurais que trop vous conseiller Homebrew pour installer MySQL, Node.js (si vous utilisez la version CoffeeScript de Chaplin.js) et une version récente de PHP.
Création du projet Symfony
Installez Symfony via Composer grâce à cette commande :
Puis suivez le guide pour configurer correctement votre environnement.
Génération du bundle qui contiendra l’application client Backbone.js / Chaplin.js
Créez ensuite un bundle qui contiendra votre application en tapant la commande suivante à la racine de votre projet Symfony:
$ php app/console generate:bundle
Et répondez aux question posées par le générateur. Pour ma part j’ai indiqué Dunglas/ChaplinDemoBundle comme namespace et j’ai laissé les choix par défaut pour toutes les autres options.
Installation de Chaplin.js, de Backbone.js et de leurs dépendances
Téléchargez maintenant le boilerplate Chaplin.js, version CoffeeScript ou version JavaScript (cliquez sur le bouton ZIP sur ces pages pour récupérer une archive de la dernière version), décompressez le.
Si vous utilisez la version en pure JavaScript copiez le contenu du répertoire js/ dans le dossier Ressources/public/ de votre bundle et passez directement à l’étape d’installation des assets.
Pour ceux qui préfèrent CoffeeScript copiez le répertoire coffee/ de l’archive dans le répertoire Ressources/ du bundle généré à l’étape précédente et le répertoire js/ de l’archive dans le répertoire Ressources/public/ (créez le si il n’existe pas encore).
Pas besoin de s’embêter à récupérer toutes les dépendances de Chaplin.js (Backbone.js, Undescore.js, jQuery…) elles sont déjà incluses dans le boilerplate.
Voici la structure que doit avoir le répertoire Ressources/ de votre bundle après la copie des dossiers issus du boilerplate Chaplin :
coffee/ : code CoffeeScript de votre application, ne sera pas accessible depuis le serveur web
public/
js/ : code JavaScript compilé de votre application
vendor/ : bibliothèques JavaScript tiers utilisées par votre application (dépendances)
templates/ : les templates Handlebars.js
views/ : les templates Twig
Ouvrez un terminal dans le répertoire Ressources/ de votre bundle et lancer la commande suivante :
L’argument –watch permet la recompilation automatique en JavaScript des fichiers CoffeeScript dès qu’ils sont modifiés et –bare supprime l’encapsulation automatique dans une fonction (nécessaire à Chaplin.js).
Installez maintenant les fichiers statiques de notre bundle contenant Chaplin.js dans le répertoire web du projet en utilisant un lien symbolique afin ne pas avoir à répéter la manipulation lors de chaque changement apporté au code du client :
$ php app/console assets:install --symlink
Un peu de ménage
Si ce n’est pas encore fait supprimez les routes de démonstration créez lors de l’installation de Symfony. Il s’agit de _welcome, _demo_secured et _demo dans le fichier app/config/routing_dev.yml.
Supprimez la ligne qui charge le DemoBundle du fichier config/AppKernel.php :
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle();
Supprimez maintenant le DemoBundle lui même (répertoire src/Acme/).
Création de la page chargeant le code JavaScript
Pour initialiser notre SPA, il va nous falloir créer une page qui charge notre application JavaScript.
Commençons par adapter le controlleur par défaut de notre bundle. Remplacez le contenu de src/Dunglas/ChaplinDemoBundle/Controller/DefaultController.php par :
L’action index assignée à la route / se contente de charger la template index.html.twig. Remplaçons le contenu de Ressources/views/Default/index.html.twig par une version adaptée à Twig et à Symfony de la page index.html fournie avec le boilerplate Chaplin.js :
J’ai apporté quelques petites modifications relatives à Symfony.
Ligne 18 j’utilise Assetic pour charger Require.js au bon endroit dans la structure de répertoires Symfony.
De la même manière ligne 25 j’indique à Chaplin.js ou trouver les fichiers JavaScript compilés.
Ligne 51 si l’application est en mod développement je contourne le cache navigateur en passant l’heure actuelle en paramètre GET de tous les fichiers JavaScript chargés afin de ne pas avoir à appuyer frénétiquement sut “Cmd + r” à chaque modification.
Puis ligne 56 je passe en paramètre de notre application je chemin vers la racine de notre projet pour que le Router de Chaplin.js fonctionne toujours même si le projet est en mode développement (fichier app_dev.php) ou que l’on utilise pas l’application par défaut.
Cette modification en entraine d’autres dans le fichier Ressources/coffee/hello_world_application.coffee :
Ligne 12 j’ajoute un constructeur qui prend en paramètre une propriété contenant le chemin relatif vers la racine du projet.
Ligne 31 j’utilise cette propriété pour initialiser le routeur de Chaplin.js
Chargez la page d’accueil de votre application dans en navigateur ou /app_dev.php en mode développement. Si tout est OK vous devez voir apparaitre “Hello World!” en bas de la page.
Symfony, Backbone.js et Chaplin.js sont maintenant installés et configurés pour fonctionner ensembles. Nous avons une bonne base pour construire une application web moderne.
Il faudra tout de même adapté cette template pour charger les fichiers JavaScript optimisés avec r.js en production car comme vous l’aurez remarqué, je n’utilise Assetic, l’excellent gestionnaire d’assets fourni en standard avec Symfony, que pour charger require.js.
La compilation des fichiers Coffee et l’import des modules AMD n’est pas faite par ce biais. Un bundle existe pourtant pour cela, HearsayRequireJSBundle, mais il ne semble plus maintenu et supporte assez mal CoffeeScript. Il m’a semblé plus simple pour ce tutoriel d’utiliser directement require.js et le compilateur CoffeScript.
A la prochaine
Dans le prochain article j’irais un peu plus loin en réutilisant cette installation pour développer un petit moteur de microblogging. Nous réaliserons une API REST compatible avec Backbone.js à l’aide des bundles Symfony FOSRest et JMSSerializer puis je présenterais la partie client s’y connectant bâtie avec Chaplin.js.
Le projet n’était jusque le pas du tout documenté, j’ai donc mis en ligne une petite documentation inspirée de celle du composant pour l’ORM. Attention, elle s’affiche mal sur GitHub à cause du format RST, il faut télécharger les fichiers.
J’en ai également profité pour corriger le composer.json qui ne fonctionnait plus et je publierais bientôt sous licence libre la démo d’un tout petit moteur de blog qui utilise MongoDB et l’admin Sonata, en espérant que ça puisse servir à quelques-uns.
Souvent, pour des raisons de coups liées aux certificats SSL, il n’est pas possible d’installer une application Symfony dans son propre virtual host. L’application se retrouve alors dans un sous-répertoire du DocumentRoot, ouverte à tous vents et c’est une catastrophe en terme de sécurité !
Imaginons que notre DocumentRoot soit /home/web et que l’application Symfony soit installée dans le répertoire /home/web/my-sf-app/. Ainsi l’URL de l’application est https://example.com/my-sf-app/web. Si un utilisateur mal intentionné accède à https://example.com/my-sf-app/app/config/config.yml il obtient le fichier de configuration principal de l’application qui contient entre-autre les identifiants d’accès à la base de données… Mauvaise idée.
Sécurisons tant bien que mal tout ça (en partant du principe que votre serveur est Apache) grâce aux fichiers de configuration .htaccess :
Le premier, à créer, sera /home/web/my-sf-app/.htaccess et servira à interdire l’accès à tous les fichiers de l’application :
Order allow,deny
Deny from all
Le second, /home/web/my-sf-app/web/.htaccess, existe normalement déjà dans notre application Symfony (il est utilisé pour l’URL rewriting), ajoutons-y au début :
Order allow,deny
Allow from all
Ce n’est toujours pas la panacée, il est toujours aisée de reconnaitre quelle est la technologie employée à la structure des répertoires, mais c’est déjà mieux !
After some tests I realized that the plugin sfFacebookConnectPlugin created by fabriceb was no longer functional or maintained. I tried to correct some bugs but it’s a pain: the plugin is not adapted to the new version of the Facebook SDK.
So I have created new plugin called kdDoctrineGuardFacebookConnectPlugin available on GitHub or in the symfony 1 plugins repository. It provides a simple an easy way to add Facebook Connect support to your symfony 1 app and it works ! The code base is very small, easy to understand and has a voluntary limitation: only with sfDoctrineGuard auth method is supported (no Propel backend).
kdDoctrineGuardFacebookConnectPlugin adds a “Login with Facebook” button to the sfGuard signin form, automatically creates a sfGuard user and populates it with Facebook provided data (first name, last name, gender, location, hometown, Facebook profile link, …), and updates the profile if some data are changed on Facebook and provides a clean logout mechanism (from your app and from Facebook).
It is designed to create autonomous communities where users can directly create and manage content.
It is a mix between blogs and blogs platforms, digg-likes and open publishing websites such as (the Indymedia network)[http://www.indymedia.org].
It allows to publish and promote rich text articles and news. It includes many features: tagging with (triple tags)[http://en.wikipedia.org/wiki/Triple_tag#Triple_tags] support, comments, spam protection, themes, interface translation, registration system, peronnal users pages, Atom feeds, microformats, and more!
Every pages are optimized for search engines, including expressives URLs and uniques titles.
It is wrote in PHP using the (symfony framework)[http://www.symfony-project.org]. It is modular and object oriented.
The Javascript part of the code uses (jQuery)[http://www.jquery.com], the built-in theme is (x)HTML 5 compliant.
This software is still in an early stage of developpement.
_Publish It Yourself_ is a free software covered by the (GNU Affero General Public License version 3)[http://www.fsf.org/licensing/licenses/agpl-3.0.html]. See the “LICENSE.txt“ file for futher informations.
For installation instructions, see the “INSTALL.markdown“ file.
Publish It Yourself is a self-managed CMS. It is designed to create autonomous communities where users can directly create and manage content.
It is a mix between blogs and blogs platforms, digg-likes and open publishing websites such as the Indymedia network.
It allows to publish and promote rich text articles and news. It includes many features: tagging with triple tags support, comments, spam protection, themes, interface translation, registration system, peronnal users pages, Atom feeds, microformats, and more! Every pages are optimized for search engines, including expressives URLs and uniques titles.
It is written in PHP using the symfony framework. It is modular and object oriented. The Javascript part of the code uses jQuery, the built-in theme is (x)HTML 5 compliant.
This software is still in an early stage of development and probably has many bugs, please report them! It is a free software covered by the GNU Affero General Public License version 3.
You can try it online (database cleared periodically) or download it on GitHub. Contributions are welcome (see the TODO file inside the project root directory) and can be submitted directly on GitHub.
You must have sfFormExtraPlugin with my patch and sfPropelActAsTaggableBehaviorPlugin properly installed and working. We consider that you have a model called Article with the taggable behavior.
Add jQuery to your javascripts
Like many others sfFormExtraPlugin widgets, the sfWidgetFormJqueryTagSuggestion requires jQuery to work. If you already have it installed, you can skip this step. Either, download jQuery to the web/js/
directory of your project, open the config/view.yml
file of your application and set it like that:
1
2
<code class="language-yaml">default:
javascripts:[jquery-1.3.2.min.js]</code>
Of course, change the filename if needed.
Put Javascripts and CSS into your web directory
sfFormExtraPlugin need some CSS and Javascripts to work properly, run the symfony plugin:publish-assets command to put them into corrects directories.
Create a static function to retrieve matching tags
Its time to extend the TagPeer model class to add it a method allowing to retrieve tags corresponding to a query. Creates a new file called MyTagPeer.class.php into the lib/model/
directory of your project containing the following code:
Do not forget to run symfony cc to clear the cache after that.
Create a controller method to send the result as JSON
We have the model, we need the controller. Create a new module called tag by running symfony generate:module yourapp tag and add the following method to the tagActions class:
HTML Purifier is a awesome PHP filter library designed to secure and add standard compliance to HTML. In websites including user generated content, this library allow to have mutlimedia pages including image, text formating and YouTube videos in a secure and SEO proof way thanks to rich text editors like Tiny MCE or FCK Editor and HTML purifier.
A plugin called sfXssSafePlugin is designed to integrate this library as an escapement strategy in symfony. If you have tried it with symfony 1.2 you can see this message:
HTML Purifier autoloader registrar is not compatible
with non-static object methods due to PHP Bug #44144;
Please do not use HTMLPurifier.autoload.php (or any
file that includes this file); instead, place the code:
spl_autoload_register(array(‘HTMLPurifier_Bootstrap’, ‘autoload’))
after your own autoloaders.
There are also some strict standards and constants compatibility problems. I’ve just wrote a patch to get this plugin working with symfony 1.2.