Files
formations/developpement/symfony3/presentation/slides.md

706 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<style>pre { font-size: 0.7em !important; }</style>
# Remise à niveau Symfony3
## William Petit - S.C.O.P. Cadoles
---
<!-- page_number:true -->
# Les principales nouveautés de Symfony 3
- Simplification de l'authentification avec le système de "Guard"
- Composant LDAP pour l'authentification (compatible Active Directory)
- Amélioration des mécanismes d'injection de dépendances: "auto-wiring", services dépréciés...
- Un "MicroKernel" pour créer des applications minimalistes basées sur Symfony3
- Et beaucoup d'autres améliorations et composants mineurs...
---
# Structure d'un projet, générateurs et "bundles"
## Amorçage d'un projet
## Notion de "bundle"
## Structuration d'un projet
## La console, les commandes et les générateurs
---
## Amorçage d'un projet
### Récupération de l'installeur Symfony
```bash
sudo mkdir -p /usr/local/bin
sudo curl -LsS https://symfony.com/installer \
-o /usr/local/bin/symfony
sudo chmod a+x /usr/local/bin/symfony
```
### Création du projet (avec la dernière LTS)
```bash
symfony new <my_project_name> 3.4
```
---
## Notion de "bundle"
> Un "bundle" est un ensemble de fichiers (code, templates, etc) représentant une unité fonctionnelle dans le framework Symfony.
**Avant Symfony 3** Les "bundles" étaient le moyen utilisé pour structurer le code d'une application. Une application pouvait donc avoir plusieurs bundles "internes", i.e. ne provenant pas d'un développeur tiers.
**Après Symfony 3** Les bundles ne sont plus considérés à titre organisationnel mais uniquement comme un moyen de diffuser le code sous forme d'unité réutilisable. Une application ne devrait donc plus qu'avoir un seul bundle interne: `AppBundle`.
---
## Structuration d'un projet (1)
### Les principaux répertoires et leur rôle
|Répertoire|Rôle|
|:-:|:-:|
|`app/config/`|Configuration de l'application|
|`app/Resources/`|Depuis Symfony3, répertoire contenant les vues ainsi les "assets" de l'application|
|`src/AppBundle/`|Sources de l'application|
---
## Structuration d'un projet (2)
|Répertoire|Rôle|
|:-:|:-:|
|`tests/`|Répertoire contenant les tests de l'application (unitaire comme fonctionnels)|
|`var/`|Répertoire contenant toutes les données "vivantes" de l'application|
|`vendor/`| Dépendances Composer
|`web/`| Répertoire des ressources publiques de l'application
---
## La console, les commandes et les générateurs (1)
### Quelques commandes (très) utiles
|Commande|Description|
|:-:|:-:|
|`server:run`|Exécuter l'application avec le serveur HTTP PHP|
|`security:check`|Vérifier que les dépendances du projet ne comportent pas de vulnérabilités connues|
|`debug:container`|Retrouver le mapping services <-> classe PHP|
|`router:match`|Vérifier quelle controleur/action sera utilisée pour un chemin donné|
---
## La console, les commandes et les générateurs (2)
### Les générateurs par défaut
|Commande|Description|
|:-:|:-:|
|`generate:bundle`|Créer un nouveau bundle|
|`generate:controller`|Créer un nouveau contrôleur|
|`generate:command`|Créer une nouvelle commande|
|`doctrine:generate:entity`|Créer une nouvelle entité Doctrine|
---
# Le routage et les contrôleurs
## Création d'un nouveau contrôleur
## Déclaration des contrôleurs
## Actions, routes et verbes HTTP avec les annotations
---
## Création d'un nouveau contrôleur
```bash
bin/console generate:controller
```
---
## Déclaration des contrôleurs
---
## Actions, routes et verbes HTTP avec les annotations (1)
### Action annotée basique
```php
class DemoController extends Controller
{
/**
* @Route("/demo")
*/
public function demoAction()
{
// ...
}
}
```
---
## Actions, routes et verbes HTTP avec les annotations (2)
### Action avec méthodes HTTP contraintes
```php
class DemoController extends Controller
{
/**
* @Route(
* "/demo",
* methods = { "POST", "PUT" }
* )
*/
public function demoAction()
{
// ...
}
}
```
---
## Actions, routes et verbes HTTP avec les annotations (3)
### Action nommée
```php
class DemoController extends Controller
{
/**
* @Route("/demo-named", name="my_demo_action")
*/
public function demoAction()
{
// ...
}
}
```
---
## Actions, routes et verbes HTTP avec les annotations (4)
### Action avec paramètres
```php
class DemoController extends Controller
{
/**
* @Route("/demo/{myParam}")
*/
public function demoAction($myParam)
{
// ...
}
/**
* @Route("/demo/{paramWithDefaultVal}")
*/
public function demoAction($paramWithDefaultVal = 1)
{
// ...
}
}
```
---
## Actions, routes et verbes HTTP avec les annotations (5)
### Action avec paramètres contraints
```php
class DemoController extends Controller
{
/**
* @Route(
* "/demo/{myParam}",
* requirements = { "myParam"="^\d+$" }
* )
*/
public function demoAction($myParam)
{
// ...
}
}
```
---
## Actions, routes et verbes HTTP avec les annotations (6)
### Action avec paramètres contraints
```php
class DemoController extends Controller
{
/**
* @Route(
* "/demo/{myParam}",
* requirements = { "myParam"="^\d+$" }
* )
*/
public function demoAction($myParam)
{
// ...
}
}
```
---
## Actions, routes et verbes HTTP avec les annotations (7)
### Paramètres spéciaux
|Paramètre|Description|
|:-:|:-:|
|`_locale`| La "locale" utilisé par l'application pour la requête en cours |
|`_format`| Le "format" utilisé par l'application pour la requête en cours |
|`_controller`| L'identifiant du contrôleur et son action utilisés pour traiter la requête en cours|
---
## Actions, routes et verbes HTTP avec les annotations (8)
### Générer une URL pour une route nommée
```php
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
$this->generateUrl(
'demo', // Nom de la route
['myParam' => 'my-value'], // Paramètres à injecter
// L'URL générée doit elle être absolue ou non ?
UrlGeneratorInterface::ABSOLUTE_URL
);
```
---
# Services
## Utilisation des services
## Création de nouveaux services
---
## Utilisation des services (1)
### Lister les services existants
```bash
bin/console debug:container
```
---
## Utilisation des services (2)
### Utiliser un service (méthode classique)
```php
class DemoController extends Controller
{
/**
* @Route("/demo")
*/
public function demoAction()
{
$logger = $this->get('logger');
$logger->info('Hello world !');
}
}
```
---
## Utilisation des services (3)
### Utiliser un service (Via le "type hint")
```php
use Psr\Log\LoggerInterface;
class DemoController extends Controller
{
/**
* @Route("/demo")
*/
public function demoAction(LoggerInterface $logger)
{
$logger->info('Hello world !');
}
}
```
**Tip** Pour identifier les différentes interfaces disponibles, utilisez la commande `bin/console debug:autowiring`
---
## Création d'un service (1)
### Création de la classe PHP
```php
namespace AppBundle\Service;
class MyService {
public function doNothing() {}
}
```
**Tip** On peut vérifier que le service est bien détecté par l'application avec la commande `bin/console debug:autowiring`
---
## Création d'un service (2)
### Utilisation du service dans un contrôleur
```php
use AppBundle\Service\MyService;
class DemoController extends Controller
{
/**
* @Route("/demo")
*/
public function demoAction(MyService $my)
{
$my->doNothing();
}
}
```
---
## Création d'un service (3)
### Déclaration de dépendances inter-services
```php
namespace AppBundle\Service;
use Psr\Log\LoggerInterface;
class MyService {
private $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function log($message) {
$this->logger->info($message);
}
}
```
---
## Création d'un service (4)
### Déclaration de dépendances vers des valeurs de configuration
```php
namespace AppBundle\Service;
class MyService {
private $myCustomParameter;
public function __construct($myCustomParameter) {
$this->myCustomParameter = $myCustomParameter;
}
}
```
---
## Création d'un service (5)
### Déclaration explicite de la dépendance
Dans `app/config/services.yml`, déclarer la dépendance explicitement:
```yaml
services:
AppBundle\Service\MyService:
arguments:
$myCustomParameter: 'test'
```
---
# Authentification et autorisation
## Le fichier `app/config/security.yml`
## Firewalls, providers et encoders
## Gestion des rôles et contrôle des accès
## Méthode d'authentification personnalisée
---
## Le fichier `app/config/security.yml`
### Authentifications et autorisations
---
## Firewalls (1)
### Déclarer une nouvelle méthode d'authentification dans un firewall
```yaml
security:
firewalls:
main:
anonymous: ~
http_basic: ~
```
---
## Firewalls (2)
### Multiple firewalls
```yaml
security:
firewalls:
authenticated_area:
pattern: ^/secured
http_basic: ~
public_area:
anonymous: ~
```
---
## Providers (1)
### Utilisation du provider `memory`
```yaml
security:
providers:
in_memory:
memory:
users:
bob:
password: bob
roles: 'ROLE_USER'
admin:
password: 123456
roles: 'ROLE_ADMIN'
```
---
## Providers (2)
### Déclaration de l'`encoder` pour la gestion des mots de passe
```yaml
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
```
---
## Providers (3)
### Utilisation d'un `encoder` apportant un meilleur niveau de sécurité
```yaml
security:
encoders:
Symfony\Component\Security\Core\User\User:
algorithm: bcrypt
cost: 12
```
#### Calcul de l'empreinte d'un mot de passe
```bash
bin/console security:encode-password
```
---
## Gestion des rôles et contrôle des accès (1)
## Définition de rôles
```yaml
security:
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
```
---
## Gestion des rôles et contrôle des accès (2)
## Restriction d'accès par adresse IP
```yaml
security:
access_control:
- path: ^/local-api
roles: ROLE_API_USER
ips: [127.0.0.1]
```
---
## Gestion des rôles et contrôle des accès (3)
## Définition de règles d'accès pour les actions
```php
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
class DemoController extends Controller
{
/**
* @Route("/demo")
* @Security("has_role('ROLE_ADMIN')")
*/
public function demoAction()
{
// ...
}
}
```
---
## Méthode d'authentification personnalisée
### Exercice
Implémenter une classe `Guard` pour créer un firewall pour un serveur d'authentification "passwordless" basé sur JWT.
**Ressources**
- Tutoriel Symfony3 sur l'utilisation de la classe Guard https://symfony.com/doc/3.4/security/guard_authentication.html
- Instance de démonstration du serveur d'authentification: https://forge.cadoles.com/wpetit/ciku
- Sources du serveur d'authentification: https://forge.cadoles.com/wpetit/ciku
---
# Les vues et le moteur de templating Twig
## Organisation des vues
## Syntaxe Twig
## Héritage et composition
## Étendre Twig
---
## Organisation des vues dans le projet
---
## Syntaxe Twig
```twig
<html>
<body>
<p>{{ myVar }}</p>
<ul>
{% for i in items %}
<li>{{ i.text }}</li>
{% endfor %}
</ul>
</body>
</html>
```
---
## Héritage et composition (1)
### Héritage
```twig
// parent.html.twig
<html>
<body>
{% block body %}
<div>
Default content
</div>
{% endblock %}
</body>
</html>
```
```twig
// child.html.twig
{% extends 'parent.html.twig' %}
{% block body %}
<div>
Child content
</div>
{% endblock %}
```
---
## Héritage et composition (21)
### Composition
```twig
// layout.html.twig
<html>
<body>
{% for i in items %}
{{ include('_partial.html.twig', { 'item': i }) }}
{% endfor %}
</body>
</html>
```
```twig
// _partial.html.twig
<div>
Item #{{ item.id }}
</div>
```
---
## Étendre Twig
---
# Les formulaires
## Création et traitement de formulaires
## Validation des données
## Les évènements
---
# L'ORM Doctrine et le modèle de données
## Concept d'ORM
## Entité et Dépôt
## Les évènements
---
# Mise en production
## Gestion des environnements
## Cache applicatif
---
# Licence
## CC BY-NC-SA 3.0 FR
[Creative Commons - Attribution - Pas dUtilisation Commerciale - Partage dans les Mêmes Conditions 3.0 France](https://creativecommons.org/licenses/by-nc-sa/3.0/fr/)