Application, requête, réponse
L’application
Silex (PHP)
require_once 'vendor/autoload.php';
$app = new Silex\Application();
$app->get(); // Le router
$app->post();
$app->match();
$app->run(); // Exécution
Express (Node.js)
var express = require('express');
var app = express();
app.get(); // Le router
app.post();
app.use();
app.listen(80); // Exécution
L’objet requête
Silex
use Symfony\Component\HttpFoundation\Request;
$app->get('/', function(Request $req) {
$req->query; // Query string
$req->request; // corps de la requête
$req->headers; // entêtes HTTP
$req->cookies; // cookies
});
Express
app.use(express.query()).use(express.bodyParser()); // config
app.get('/', function(req, res) {
req.query; // query string
req.body; // corps de la requête
req.headers; // entêtes HTTP
req.cookies; // cookies
});
L’objet réponse (Silex)
use Symfony\Component\HttpFoundation\Response;
Écrire une réponse simple
return 'Hello world';
Envoyer un code d’état et des entêtes
return new Response(404, 'Not Found', headers);
Envoyer un fichier statique
return $app->sendFile('static-file.html');
Faire une rédirection
return $app->redirect('/other/path');
Envoyer des données au format JSON
return $app->json( array('a' => 'b') );
L’objet réponse (Node.js)
Écrire une réponse simple
res.send('Hello world');
Envoyer un code d’état et des entêtes
res.setHeader('Content-Type', 'text/plain');
res.send(404, 'Not Found');
Envoyer un fichier statique
res.sendfile('static-file.html');
res.download('static-attachment.mp3');
Faire une rédirection
res.redirect('/other/path');
Envoyer des données au format JSON
res.json({ 'a' : 'b' });
Anatomie de l’application
Le router
Le router fait l’association: méthode+URL → code à exécuter
$app->get('/url', function() {...});
Il peut aussi traduire une partie de l’URL en arguments de la fonction
$app->get('/url/{a1}/{a2}', function($a1, $a2) {
...
});
En Express
app.get('/url/:a1/:a2', function(req, res) {
console.log(req.params.a1);
});
Séparation des vues
Le problème : considérez ce gestionnaire
$res = '<html><head><title>Bla</title><body><table>';
foreach ($array as $k => $v) {
$res .= "<tr><td>$k</td><td>$v</td></tr>";
}
return $res . '</table></body></html>';
- Confusion entre logique et présentation,
- Code difficile à lire et à organiser,
- Syntaxe très lourde (répétition de la variable
$res
), - Pas possible de colorier la syntaxe HTML dans un éditeur,
- Risques de sécurité…
Les templates naissent pour résoudre ces problèmes.
Templates
Templates
Un exemple de template
<!DOCTYPE html>
<html>
<head>
<title>Blabla</title>
</head>
<body>
<h1>Bonjour {{ user }}</h1>
{% include 'content.html' %}
</body>
</html>
- La valeur de la variable
user
est remplacée pour{{ user }}
; - Le contenu de
content.html
est inséré dans la sortie ; - Tout le reste est renvoyé à l’identique.
Langages de templating
Les langanges de templating permettent, en général, de
- Remplacer des variables (
{{ var }}
) ; - Exécuter des tests (
{% if %}
) ; - Boucler sur des tableaux (
{% for %}
) ; - Inclure d’autres templates (
{% include %}
,{% block %}
,{% extends %}
) ; - Chaîner des transformations (
{{ var | upper | strip }}
) ; - Appliquer des opérateurs simples (mathématiques, logiques, comparaisons).
Quelques langages de templating
Twig
Substitution de variables, filtres
Hello {{ nom }}
Filtres
En majuscules : {{ nom | upper }}
Une liste : {{ list | join(', ') }}
{% filter upper %}
{{ nom }}
{% endfilter %}
Contrôle
Conditionnel
{% if nom == 'toto' %}
...
{% endif %}
Boucle
{% for i in range(0, 10) %}
Utilisateur : {{ users[i] }}
{% endfor %}
{% for u in users %}
Utilisateur : {{ u }}
{% endfor %}
Modularité
Inclusion
{% include 'autre_template.html' %}
Macros
{% macro greet(nom) %}
Bonjour Mr {{ nom }}
{% endmacro %}
{% from "macros.html" import greet %}
{{ greet('toto') }}
Héritage
Voici le template `main.html`
Le contenu de ces blocs est affiché tel quel
{% block titre %}
Un titre quelconque
{% endblock %}
{% block pied %}
Copyright Pinco Pallino
{% endblock %}
{% extends 'main.html' %}
Ce bloc va remplacer le bloc titre de `main.html`
{% block titre %}
Commen hériter
{% endblock %}
Utiliser Twig: render
dans Silex
$app->register(new Silex\Provider\TwigServiceProvider(),
array('twig.path' => 'templates'));
$app->get('/', function(Application $app) {
return $app['twig']->render('hello.html', array(
'nom' => 'Toto'
));
});
dans Express (s’applique aussi à d’autres langages de templating)
var twig = require('twig');
app.set('views', 'templates'); // où trouver les templates
app.set('view engine', 'html'); // à quelle extension
app.engine('html', twig.__express); // associer twig
app.get('/', function(req, res) {
res.render('hello.html', { 'nom' : 'Toto' });
});
Échappement
Échappement
- La programmation web comporte le melange de plusieurs langages de programmation : HTML, CSS, JavaScript, PHP, templates, SQL, …
- Chaque langange à ses caractères spéciaux. Par ex.:
<
,>
,&
,'
,"
Considérez ce gestionnaire
function(Request $req) {
return '<h1>' . $req->query->get('nom') . '</h1>';
}
Nom :
Les caractères <U , Z>
sont interprétés comme la balise <U>
.
Échappement HTML
HTML définit des séquences d’échappement pour ses caractères spéciaux, appelées character entities.
< |
> |
& |
" |
' |
< |
> |
& |
" |
' |
Ces remplacements sont appliqués automatiquement par
- La fonction
htmlspecialchars()
de PHP, - La fonction
$app->escape()
de Silex, - Twig et la majorité des autres moteurs de templates.
ATTENTION : n’utiliser que pour du HTML !
- JSON : remplacer
'
→\'
,"
→\"
, - JavaScript : comme JSON, mais avec beaucoup de soin !
Échappement dans Twig
Les remplacements {{ var }}
sont échappés par défaut.
Désactiver l’échappement :
{% autoescape false %} {{ nom }} {% endautoescape %}
{{ nom | raw }}
Réactiver l’échappement :
{% autoescape 'html' %}{{ nom }}{% endautoescape %}
{% autoescape 'css' %}{{ nom }}{% endautoescape %}
{{ nom | escape }}
{{ nom | e }}
Nom :
Lectures
Silex
- La doc officielle (en anglais),
- Le Book de Symfony (disponible aussi en anglais),
- La référence de Symfony (en anglais),
Express
- La référence de Node.js,
- Les aides de NodeJitsu,
- Le guide de Express,
- La référence de Express,
Twig
- La doc officielle (en anglais),
- L’introduction pour les designers (en anglais),
- Le tutoriel de Symfony (en français).