Programmation PHP avec Symfony/Composant
Description
modifierLe framework Symfony permet nativement les fonctionnalités minimum dans un souci de performances, à l'instar d'un micro-framework. Par exemple son compilateur permet d'utiliser plusieurs patrons de conception (design patterns) via des mots réservés dans services.yaml :
- arguments : Injection de dépendance
- decorator : Décorateur.
- shared : Singleton.
- factory : Fabrique[1].
Toutefois, on peut lui ajouter des composants[2], dont il convient de connaitre les fonctionnalités pour ne pas réinventer la roue. Pour les installer :
composer require symfony/nom_du_composant
Les quatre premiers ci-dessous sont inclus par défaut dans le microframework symfony/skeleton
.
framework-bundle
modifierStructure la configuration principale du framework sans laquelle aucun composant n'est installable[3].
console
modifierPatrons de conception "Commande".
Fournit la possibilité d'exécuter le framework avec des commandes shell[4]. Par exemple pour obtenir la liste de toutes les commandes disponibles dans un projet :
php bin/console help list
dotenv
modifierGère les variables d'environnement non versionnées, contenues dans un fichier .env[5]. Elles peuvent aussi bénéficier de type checking en préfixant les types avec ":". Ex de .env :
IS_DEV_SERVER=1
Le services.yaml, parameters: récupère ensuite cette valeur et vérifie qu'il s'agit d'un booléen (via le processeur de variable d'environnement "bool") :
is_dev_server: '%env(bool:IS_DEV_SERVER)%'
Il existe plusieurs processeurs de variable d'environnement (en plus de "bool" et des autres types)[6] :
base64:
encode en base64.default:
remplace le deuxième paramètre par le premier si absent. Ex :$addTestValues: '%env(bool:default::ADD_TEST_VALUES)%'
injecte "null" si ADD_TEST_VALUES n'est pas défini.$addTestValues: '%env(bool:default:ADD_TEST_VALUES2:ADD_TEST_VALUES1)%'
injecte le contenu de ADD_TEST_VALUES2 si ADD_TEST_VALUES1 n'est pas défini.
file:
remplace le chemin d'un fichier par son contenu.not:
renvoie l'inverse.require:
fait un require() PHP.resolve:
remplace le nom d'une variable par sa valeur.trim:
fait un trim() PHP.
Pour définir une valeur par défaut en cas de variable d'environnement manquante (sans utiliser default:
), dans services.yaml, parameters: :
env(MY_MISSING_CONSTANT): '0'
yaml
modifierAjoute la conversion de fichier YAML en tableau PHP[7]. Ce format de données constitue une alternative plus lisible au XML pour renseigner la configuration des services. Par défaut le framework se configure avec config.yaml.
routing
modifierpatron de conception "Façade".
Installe les annotations permettant de router des URLs vers les classes des contrôleurs MVC.
- Pour plus de détails voir : Programmation PHP avec Symfony/Contrôleur#Routing.
serializer
modifierPermet de convertir des objets en tableaux ou dans les principaux formats de notation : JSON, XML, YAML et CSV[8].
composer require symfony/serializer
Ce composant est notamment utilisé pour créer des APIs.
form
modifierConstruit des formulaires HTML.
- Pour plus de détails voir : Programmation PHP avec Symfony/Formulaire.
validator
modifierFournit des règles de validation pour les données telles que les adresses emails ou les codes postaux. Utile à coupler avec les formulaires pour contrôler les saisies.
Ces règles peuvent porter sur les propriétés ou les getters.
Il permet aussi de créer des groupes de validateurs, et de les ordonner par séquences. Par défaut chaque classe a automatiquement deux groupes de validateurs : "default" et celui de son nom. Si une séquence est définie, le groupe "default" n'est plus égal au groupe de la classe (celui par défaut) mais à la séquence par défaut[9].
Exemples
modifier- Dans une entité :
use Symfony\Component\Validator\Constraints as Assert; ... #[Assert\Email] private ?string $email = null;
- Dans un formulaire (inutile à faire si c'est déjà dans l'entité) :
use Symfony\Component\Validator\Constraints\Email; ... $builder->add('email', EmailType::class, [ 'required' => false, 'constraints' => [new Email()], ])
translation
modifierLes traductions sont stockées dans un fichier différent par domaine et par langue (code ISO 639). Les formats acceptés sont YAML, XML, PHP[10].
On peut ensuite récupérer ces dictionnaires en Twig (via le filtre "trans"), ou en PHP (via le service "translator").
Par exemple, le domaine par défaut étant "messages", le français se trouve donc dans translations/messages.fr.yml
ou translations/messages.fr-FR.yml
.
Installation
modifiercomposer require symfony/translation
Pour avoir les traductions inutilisées en anglais :
bin/console debug:translation en --only-unused
Pour les traductions manquantes en anglais :
bin/console debug:translation en --only-missing
On peut restreindre à un seul domaine avec une option : --domain=mon_domaine
Traduction en PHP
modifierLe domaine et la langue sont facultatifs (car ils ont des valeurs par défaut) :
$translator->trans('Hello World', domain: 'login', locale: 'fr_FR');
Traduction en Twig
modifierLes traductions en Twig sont appelées par le filtre "trans" :
{% trans_default_domain 'login' %} {{ 'Hello World' |trans }}
Ou :
{{ 'Hello World' |trans({}, 'login', 'fr-FR') }}
Variables
modifierHello World: 'Hello World name!'
- Twig :
{{ Hello World |trans({"name": userName}) }}
- PHP
$translator->trans('Hello World', ['name' => $userName]);
Dans un formulaire Symfony :
$builder ->add('hello', TextType::class,([ 'label' => 'Hello World', 'label_translation_parameters' => [ 'name' => $userName, ] ])) ;
Par défaut le domaine de traduction est "message" mais on peut désactiver ces dernières avec : choice_translation_domain => false
.
event-dispatcher
modifierPatrons de conception "Observateur"[12] et "Médiateur"[13].
Assure la possibilité d'écouter des évènements pour qu'ils déclenchent des actions.
- Pour plus de détails voir : Programmation PHP avec Symfony/Évènement.
process
modifierPermet de lancer des sous-processus en parallèle[14]. Exemple qui lance une commande shell :
$process = new Process(['ls']);
$process->run();
En l'absence de $process->stop()
ou de timeout, le sous-processus peut être stoppé en redémarrant le serveur PHP.
Exemple de requête SQL asynchrone[15] :
$sql = 'SELECT * FROM ma_table LIMIT 1';
$process = Process::fromShellCommandline(sprintf('../bin/console doctrine:query:sql "%s"', $sql));
$process->setTimeout(3600);
$process->start();
cache
modifierGère les connexions, lectures et écritures vers des serveurs de mémoire caches tels que Redis ou Memcached.
Il fournit une classe cacheItem conforme à la PSR, instanciable par plusieurs adaptateurs.
Le cache ne sert qu'à accélérer l'application donc une panne sur celui-ci ne doit pas la bloquer. C'est pourquoi il vaut mieux avoir un ou plusieurs caches de secours, même moins rapides, pour prendre le relais dans une chaine de caches.
Pour mettre cela en place sur Symfony, définir le chaine et ses composants dans cache.yaml.
- Pour plus de détails voir : Programmation PHP/Redis#Dans Symfony.
asset
modifierAjoute la fonction Twig asset()
pour accéder aux fichiers CSS, JS ou images selon leurs versions[16].
webpack-encore
modifierIntégration de Webpack pour gérer la partie front end (ex : minifications des CSS et JS).
composer require symfony/webpack-encore-bundle yarn install yarn build
NB : si Yarn n'est pas installé, le faire avec npm : apt install nodejs npm; npm install --global yarn
.
Cela crée les fichiers package.json et yarn.lock contenant les dépendances JavaScript, le dossier assets/ contenant les JS et CSS versionnés, et le fichier webpack.config.js dans lequel ils sont appelés.
De plus, des fonctions Twig permettent d'y accéder depuis les templates : encore_entry_link_tags()
et encore_entry_script_tags()
.
Par ailleurs, cela installe le framework JS Stimulus, et interprète les attributs de données pour appeler ses contrôleurs ou méthodes.
Rebuild
modifierPour que le code se build en cours de frappe, deux solutions[18] :
- Avec Yarn :
- yarn watch
- yarn dev-server
- Avec npm :
- npm watch
- npm run dev-server
La différence entre les deux est que le dev-server peut mettre à jour la page sans même la rafraichir.
messenger
modifierPatrons de conception "Chaîne de responsabilité".
Messenger permet d'utiliser des queues au protocole AMQP. En résumé, il gère l'envoi de messages dans des bus, ces messages transitent par d'éventuels middlewares puis arrivent à destination dans des handlers[19]. On peut aussi persister ces messages en les envoyant dans des transports via un DSN, par exemple dans RabbitMQ, Redis ou Doctrine (donc une table des SGBD les plus populaires).
php bin/console debug:messenger
Chaque middleware doit passer le relais au suivant ainsi :
return $stack->next()->handle($envelope, $stack);
Pour stopper le message dans un middleware sans qu'il arrive aux handlers :
return $envelope;
workflow
modifierCe composant nécessite de créer (en YAML, XML ou PHP) la configuration d'un automate fini[20], c'est-à-dire la liste de ses transitions et états (appelés "places").
Ces graphes sont ensuite visualisables en image ainsi :
use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper;
class WorkflowDisplayer
...
$definition = new Definition($places, $transitions);
echo (new StateMachineGraphvizDumper())->dump($definition);
sudo apt install graphviz
php WorkflowDisplayer.php | dot -Tpng -o workflow.png
browser-kit
modifierSimule un navigateur pour les tests d'intégration.
config
modifierPermet de manipuler des fichiers de configurations.
contracts
modifierPour la programmation par contrat.
css-selector
modifierPour utiliser XPath.
debug
modifierFournit des méthodes statiques pour déboguer le PHP.
dependency-injection
modifierNormalise l'utilisation du container de services.
Permet aussi d'exécuter du code pendant la compilation via un compiler pass, en implémentant l'interface CompilerPassInterface avec sa méthode process[21].
dom-crawler
modifierFournit des méthodes pour parcourir le DOM.
expression-language
modifierPatrons de conception "Interpréteur".
Expression language sert à évaluer des expressions, ce qui peut permettre de définir des règles métier[22].
Installation :
composer require symfony/expression-language
Exemple :
$el = new ExpressionLanguage();
$operation = '1 + 2';
echo(
sprintf(
"L'opération %s vaut %s",
$el->compile($operation));
$el->evaluate($operation));
)
);
// Affiche : L'opération 1 + 2 vaut 3
filesystem
modifierMéthodes de lecture et écriture dans les dossiers et fichiers.
finder
modifierRecherche dans les dossiers et fichiers.
security
modifierEnsemble de sous-composants assurant la sécurité d'un site. Ex : authentification, anti-CSRF ou droit des utilisateurs d'accéder à une page.
Dans security.yaml, on peut par exemple définir les classes qui vont assurer l'authentification (guard), ou celle User qui sera instanciée après.
Pour obtenir l'utilisateur ou son token, on peut injecter :
TokenStorageInterface $tokenStorage
pour avoir l'utilisateur courant avec $this->tokenStorage->getToken()->getUser()
.
guard
modifierExtension de sécurité pour des authentifications complexes.
http-client
modifierPour lancer des requêtes HTTP depuis l'application.
- Pour plus de détails voir : Programmation PHP avec Symfony/HttpClient.
http-foundation
modifierFournit des classes pour manipuler les requêtes HTTP, comme Request et Response que l'on retrouve dans les contrôleurs.
Par exemple :
use Symfony\Component\HttpFoundation\Response;
//...
echo Response::HTTP_OK; // 200
echo Response::HTTP_NOT_FOUND; // 404
http-kernel
modifierPermet d'utiliser des évènements lors des transformations des requêtes HTTP en réponses.
inflector
modifierDeprecated depuis Symfony 5.
Accorde les mots anglais au pluriel à partir de leurs singuliers.
intl
modifierInternationalisation, comme par exemple la classe "Locale" pour gérer une langue.
ldap
modifierConnexion aux serveur LDAP.
lock
modifierPour verrouiller les accès aux ressources[23].
Par exemple, pour ne pas qu'une commande soit lancée deux fois simultanément, bien que le composant console aie aussi cette fonctionnalité :
use Symfony\Component\Console\Command\LockableTrait; ... protected function execute(InputInterface $input, OutputInterface $output): int { if ($this->lock() === false) { return Command::SUCCESS; } ... $this->release(); return Command::SUCCESS; }
Maker bundle
modifierPour créer ou recréer des classes à partir de déductions[24].
composer require --dev symfony/maker-bundle
NB : ce composant ne permet pas de générer des entités à partir d'une base de données.
mailer
modifierPour envoyer des emails.
mime
modifierManipulation des messages MIME.
notifier
modifierPour envoyer des notifications telles que des emails, des SMS, des messages instantanés, etc.
options-resolver
modifierGère les remplacements de propriétés par d'autres, avec certaines par défaut.
phpunit-bridge
modifierPatron de conception "Pont" qui apporte plusieurs fonctionnalités liées aux tests unitaires, telles que la liste des tests désuets ou des mocks de fonctions PHP natif.
property-access
modifierPour lire les attributs de classe à partir de leurs getters, ou des tableaux.
property-info
modifierPour lire les métadonnées des attributs de classe.
stopwatch
modifierChronomètre pour mesurer des temps d'exécution.
string
modifierAPI convertissant certains objets en chaine de caractères. Ex :
use Symfony\Component\String\Slugger\AsciiSlugger;
$slugger = new AsciiSlugger();
echo $slugger->slug('caractères spéciaux € $');
Résultat :
caracteres-speciaux-EUR
templating
modifierExtension de construction de templates.
- Pour plus de détails voir : Programmation PHP avec Symfony/Templating.
var-dumper
modifierAjoute une fonction globale dump()
pour déboguer des objets en les affichant avec une coloration syntaxique et des menus déroulant.
Ajoute aussi dd()
pour dump() and die().
var-exporter
modifierPermet d'instancier une classe sans utiliser son constructeur.
polyfill*
modifierOn trouve aussi une vingtaine de composants polyfill, fournissant des fonctions PHP retirées dans les versions les plus récentes.
Composants désuets
modifierlocale (<= v2.3)
modifierArrêté en 2011, car remplacé par le composant intl[25].
icu (<= v2.6)
modifierArrêté en 2014, car remplacé par le composant intl[26].
class-loader (<= v3.3)
modifierArrêté en 2011, car remplacé par composer.json[27].
Ajoutés en 2020
modifierUid (sic) (>= v5.1)
modifierRateLimiter (>= v5.2)
modifierPatron de conception "Proxy", qui permet de limiter la consommation de ressources du serveur par les clients[29]
Semaphore (>= v5.2)
modifierPour donner l'exclusivité d'accès à une ressource[30].
Ajoutés en 2021
modifierPasswordHasher (>= v5.3)
modifierPour gérer les chiffrements[31].
Runtime (>= v5.3)
modifierPour le démarrage (bootstrap) : permettre de découpler l'application de son code de retour. [32].
Ajoutés en 2022
modifierHtmlSanitizer (>= v6.1)
modifierClock (>= v6.2)
modifierSymfony UX (>= v5.4)
modifierux-autocomplete
modifierux-chartjs
modifierUtilise Chart.js via Stimulus pour afficher des graphiques, via la fonction Twig render_chart()
[33].
ux-react
modifierAjoute le framework React.js.
- Pour plus de détails voir : Programmation PHP avec Symfony/Stimulus.
ux-vue
modifierAjoute le framework Vue.js.
Ajoutés en 2023
modifierWebhook et RemoteEvent (>= v6.3)
modifierAssetMapper (>= v6.3)
modifierScheduler (>= v6.3)
modifierComposants non listés comme tels
modifierapache-pack
modifierPour faire tourner le site sans passer par le serveur symfony server:start
.
Références
modifier- ↑ https://symfony.com/doc/current/service_container/factories.html
- ↑ https://symfony.com/components
- ↑ https://symfony.com/doc/current/reference/configuration/framework.html
- ↑ https://symfony.com/doc/current/components/console.html
- ↑ https://symfony.com/doc/current/components/dotenv.html
- ↑ https://symfony.com/doc/current/configuration/env_var_processors.html
- ↑ https://symfony.com/doc/current/components/yaml.html
- ↑ https://symfony.com/doc/current/components/serializer.html
- ↑ https://symfony.com/doc/current/validation/sequence_provider.html
- ↑ https://symfony.com/doc/current/translation.html
- ↑ https://symfony.com/doc/current/reference/formats/message_format.html
- ↑ http://www.jpsymfony.com/design_patterns/le-design-pattern-observer-avec-symfony2
- ↑ https://github.com/certificationy/symfony-pack/blob/babd3fee68a7e793767f67c6df140630f52e7f8d/data/architecture.yml#L13
- ↑ https://symfony.com/doc/current/components/process.html
- ↑ https://gist.github.com/appaydin/42eaf953172fc7ea6a8b193694645324
- ↑ https://symfony.com/doc/current/components/asset.html
- ↑ https://symfonycasts.com/screencast/stimulus/encore
- ↑ https://symfony.com/doc/current/frontend/encore/simple-example.html
- ↑ https://vria.eu/delve_into_the_heart_of_the_symfony_messenger/
- ↑ https://symfony.com/doc/current/workflow.html
- ↑ https://symfony.com/doc/current/components/dependency_injection/compilation.html
- ↑ https://symfony.com/doc/current/components/expression_language.html
- ↑ https://symfony.com/doc/current/components/lock.html
- ↑ https://symfony.com/bundles/SymfonyMakerBundle/current/index.html
- ↑ https://symfony.com/components/Locale
- ↑ https://symfony.com/components/Icu
- ↑ https://symfony.com/components/ClassLoader
- ↑ https://symfony.com/doc/current/components/uid.html
- ↑ https://symfony.com/doc/current/rate_limiter.html
- ↑ https://symfony.com/doc/current/components/semaphore.html
- ↑ https://symfony.com/blog/new-in-symfony-5-3-passwordhasher-component
- ↑ https://symfony.com/blog/new-in-symfony-5-3-runtime-component
- ↑ https://symfony.com/bundles/ux-chartjs/current/index.html
- ↑ https://symfony.com/blog/new-in-symfony-6-3-webhook-and-remoteevent-components
- ↑ https://symfony.com/blog/new-in-symfony-6-3-assetmapper-component
- ↑ https://symfony.com/blog/new-in-symfony-6-3-scheduler-component