Symfony : – Extensions Doctrine

Symfony : – Extensions Doctrine

Doctrine offre des fonctionnalités avancées permettant d’étendre et de personnaliser les comportements des entités. Les extensions Doctrine, comme les slugs, les traductions ou les dates automatiques (création et mise à jour), apportent des fonctionnalités puissantes et souvent nécessaires dans des applications modernes.

Les extensions Doctrine ajoutent des comportements pré-configurés aux entités, ce qui simplifie grandement le développement tout en offrant des fonctionnalités avancées telles que :

  • Slug : Crée un identifiant lisible pour les URL basé sur une ou plusieurs propriétés de l’entité.
  • Traductions : Gère des contenus traduits dans plusieurs langues.
  • Timestamps : Ajoute automatiquement les dates de création et de mise à jour des entités.

Ces fonctionnalités, parmi d’autres, sont fournies par le DoctrineExtensionsBundle, un composant tiers compatible avec Symfony.

a. Installation des Extensions

Pour utiliser ces extensions, commencez par installer le bundle DoctrineExtensionsBundle via Composer :

composer require stof/doctrine-extensions-bundle
Une fois installé, configurez le bundle pour activer les extensions nécessaires. Par exemple, pour activer l’extension sluggable : # config/packages/stof_doctrine_extensions.yaml stof_doctrine_extensions: orm: default: sluggable: true b. Exemple : Ajouter un Slug à une Entité Un slug est une version lisible et optimisée pour les URL d'une chaîne de caractères. Il est souvent utilisé pour remplacer les identifiants numériques dans les routes, offrant une meilleure lisibilité et un impact positif sur le SEO (Search Engine Optimization). Étape 1 : Modifier l’Entité Ajoutez une propriété slug à votre entité en configurant l’extension sluggable : namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Gedmo\Mapping\Annotation as Gedmo; #[ORM\Entity] class Livre { #[ORM\Column(name: 'titre', length: 250)] private string $titre; #[Gedmo\Slug(fields: ['titre'])] #[ORM\Column(length: 250, unique: true)] private ?string $slug = null; public function getTitre(): string { return $this->titre; } public function setTitre(string $titre): self { $this->titre = $titre; return $this; } public function getSlug(): ?string { return $this->slug; } } Étape 2 : Mettre à Jour la Base de Données Une fois la propriété slug ajoutée, synchronisez la structure de la base de données avec la commande suivante : php bin/console doctrine:schema:update --force Chaque fois qu’un nouvel objet Livre sera persisté, la propriété slug sera automatiquement générée à partir du titre. Par exemple, pour un titre "La ferme des animaux", le slug correspondant sera "la-ferme-des-animaux". Problème Courant : Données Existant Déjà en Base Si des entités existent déjà dans la base, vous pourriez rencontrer une erreur lors de la création d’un index unique sur la colonne slug. Cela se produit car les valeurs initiales du champ slug sont nulles et ne respectent pas la contrainte d'unicité. Solution : Générer les Slugs Manuellement Pour résoudre ce problème, mettez à jour les slugs des entités existantes avant de relancer la commande de mise à jour du schéma. $livres = $this->em->getRepository(Livre::class)->findAll(); foreach ($livres as $livre) { $livre->setSlug(null); // Forcer la régénération $this->em->persist($livre); } $this->em->flush(); Ensuite, relancez la commande pour créer la contrainte unique : php bin/console doctrine:schema:update --force Autres Extensions Utiles a. Traductions L’extension translatable permet de traduire les contenus de vos entités. Chaque propriété traduite peut avoir plusieurs versions, une par langue. Pour activer cette extension, configurez-la dans le fichier de configuration et ajoutez les annotations appropriées aux propriétés traduisibles. Consultez la documentation officielle pour un guide complet : Translatable Extension Documentation. b. Timestamps Ajoutez automatiquement des propriétés created et updated à vos entités pour suivre les dates de création et de mise à jour. Exemple : use Gedmo\Mapping\Annotation as Gedmo; #[ORM\Entity] class Livre { #[Gedmo\Timestampable(on: 'create')] #[ORM\Column(type: 'datetime')] private \DateTime $created; #[Gedmo\Timestampable(on: 'update')] #[ORM\Column(type: 'datetime')] private \DateTime $updated; public function getCreated(): \DateTime { return $this->created; } public function getUpdated(): \DateTime { return $this->updated; } } Bonnes Pratiques Mettez à jour les extensions régulièrement : Les extensions Doctrine évoluent avec de nouvelles fonctionnalités et correctifs. Assurez-vous de maintenir le bundle à jour en utilisant Composer. Gérez les exceptions lors de la mise à jour du schéma : Utilisez l’option --dump-sql pour vérifier les requêtes SQL générées avant de les exécuter : php bin/console doctrine:schema:update --dump-sql Combinez les extensions pour maximiser l’efficacité : Les extensions telles que translatable et sluggablepeuvent être utilisées ensemble pour gérer des entités traduites avec des slugs spécifiques par langue. Documentation DoctrineExtensionsBundle : https://github.com/stof/StofDoctrineExtensionsBundle Documentation Doctrine Extensions (Gedmo) : https://github.com/doctrine-extensions/DoctrineExtensions Documentation Doctrine ORM : https://www.doctrine-project.org/projects/orm.html Les extensions Doctrine apportent des fonctionnalités avancées prêtes à l’emploi, permettant de réduire le code boilerplate tout en enrichissant les capacités des entités. Qu'il s'agisse de slugs, de traductions ou de gestion de timestamps, ces outils sont indispensables pour construire des applications modernes et évolutives. Leur intégration est simple et leur configuration flexible, en faisant des atouts majeurs pour les développeurs Symfony.
par admin4460
Symfony
DéveloppementSystèmes & Réseaux Tests, Sécurité et CI/CDTests, Sécurité et CI/CDCet article présente une stratégie pour assurer la qualité, la sécurité et le déploiement continu d'une application basée sur Laravel 11 et React 18. La stratégie s'articule autour de quatre piliers fondamentaux : Tests complets et modernes : Une approche... 📍 Voir Plus ... DéveloppementSystèmes & Réseaux Déploiement étape par étape d’une application web sur O2SwitchDéploiement étape par étape d’une application web sur O2SwitchJe vais vous expliquer de façon détaillée comment déployer votre application développée localement (Laravel 11 + React 19 + Axios + MySQL + Bootstrap) sur un hébergement O2Switch. Suivez ces étapes dans l'ordre pour un déploiement réussi. Étape 1: Préparation de... 📍 Voir Plus ... DéveloppementSystèmes & Réseaux Déploiement et Maintenance d’Application WebDéploiement et Maintenance d’Application WebLe processus de mise en production et les mesures de suivi/maintenance pour notre application web (Laravel 11 en backend / React 19 en frontend, avec Axios, Bootstrap, base MySQL, hébergement O2Switch). L’objectif est de garantir un déploiement fluide, sécurisé et... 📍 Voir Plus ... 📍 VOIR PLUS ... 📍 Apple Bureautique CMS Cybersécurité Data Design Développement Angular HTML et CSS Java JavaScript Laravel Bug PHP React JS SQL Symfony E-commerce Gestion de projet L’intelligence artificielle Linux LMS Management Référencement Optimisation Marketing & Communication News et actualité DIGI Pédagogie & Formation Systèmes & Réseaux Windows
© MyCreaNet 2025 – Mentions légales – Plan du site – Gestion des cookies – Accessibilité Nom d'utilisateur Mot de passe Mot de passe oublié? Se connecter  SuivreSuivreSuivreSuivreSuivre window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-L58BSN4YKD');
.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-snippets-library-btns-wrap:before, .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-buttons-wrapper:before { content: "\45"; font-size: 27px; color: #ccffcc; font-family: ETModules; cursor: pointer; width: 28px; height: 27px; border-radius: 3px; padding-top: 1px; background-color: rgb(255, 255, 255, 0.2) !important; } .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-fb-form__group:nth-of-type(4) { display: none; } jQuery(document).ready(function($) { $(document).on('click', '.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-snippets-library-btns-wrap, .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-buttons-wrapper', function(event) { if (event.target !== event.currentTarget) { return; // Exit the function if the click is on a child element } var firstEditor = $('.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .CodeMirror').get(0)?.CodeMirror; if (!firstEditor) { return; } $('.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] textarea[name="code_to_render"]').click(); // Enable hidden codemirror var secondEditor = $('.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .CodeMirror').get(1)?.CodeMirror; if (!secondEditor) { return; } var content = firstEditor.getValue(); // Add a random nonce as the first line of content to prevent caching var nonce = Math.random().toString(36).substring(2, 15); content = '/* nonce:' + nonce + ' */\n' + content; secondEditor.setValue(content); }); }); Ce site utilise des cookies 🍪 Cookies & confidentialitéNous utilisons des cookies pour assurer le bon fonctionnement du site, améliorer la navigation et analyser le trafic. Fonctionnel Fonctionnel Toujours activé Le stockage ou l’accès technique est strictement nécessaire dans la finalité d’intérêt légitime de permettre l’utilisation d’un service spécifique explicitement demandé par l’abonné ou l’utilisateur, ou dans le seul but d’effectuer la transmission d’une communication sur un réseau de communications électroniques. Préférences Préférences Le stockage ou l’accès technique est nécessaire dans la finalité d’intérêt légitime de stocker des préférences qui ne sont pas demandées par l’abonné ou l’utilisateur. Statistiques Statistiques Le stockage ou l’accès technique qui est utilisé exclusivement à des fins statistiques. Le stockage ou l’accès technique qui est utilisé exclusivement dans des finalités statistiques anonymes. En l’absence d’une assignation à comparaître, d’une conformité volontaire de la part de votre fournisseur d’accès à internet ou d’enregistrements supplémentaires provenant d’une tierce partie, les informations stockées ou extraites à cette seule fin ne peuvent généralement pas être utilisées pour vous identifier. Marketing Marketing Le stockage ou l’accès technique est nécessaire pour créer des profils d’utilisateurs afin d’envoyer des publicités, ou pour suivre l’utilisateur sur un site web ou sur plusieurs sites web ayant des finalités marketing similaires. Gérer les options Gérer les services Gérer {vendor_count} fournisseurs En savoir plus sur ces finalités OUI NON Préférences Enregistrer Préférences {title} {title} {title} Ce site utilise des cookies Pour offrir les meilleures expériences, nous utilisons des technologies telles que les cookies pour stocker et/ou accéder aux informations des appareils. Le fait de consentir à ces technologies nous permettra de traiter des données telles que le comportement de navigation ou les ID uniques sur ce site. Le fait de ne pas consentir ou de retirer son consentement peut avoir un effet négatif sur certaines caractéristiques et fonctions. Fonctionnel Fonctionnel Toujours activé Le stockage ou l’accès technique est strictement nécessaire dans la finalité d’intérêt légitime de permettre l’utilisation d’un service spécifique explicitement demandé par l’abonné ou l’utilisateur, ou dans le seul but d’effectuer la transmission d’une communication sur un réseau de communications électroniques. Préférences Préférences Le stockage ou l’accès technique est nécessaire dans la finalité d’intérêt légitime de stocker des préférences qui ne sont pas demandées par l’abonné ou l’utilisateur. Statistiques Statistiques Le stockage ou l’accès technique qui est utilisé exclusivement à des fins statistiques. Le stockage ou l’accès technique qui est utilisé exclusivement dans des finalités statistiques anonymes. En l’absence d’une assignation à comparaître, d’une conformité volontaire de la part de votre fournisseur d’accès à internet ou d’enregistrements supplémentaires provenant d’une tierce partie, les informations stockées ou extraites à cette seule fin ne peuvent généralement pas être utilisées pour vous identifier. Marketing Marketing Le stockage ou l’accès technique est nécessaire pour créer des profils d’utilisateurs afin d’envoyer des publicités, ou pour suivre l’utilisateur sur un site web ou sur plusieurs sites web ayant des finalités marketing similaires. Gérer les options Gérer les services Gérer {vendor_count} fournisseurs En savoir plus sur ces finalités Accepter NON Préférences Enregistrer Préférences {title} {title} {title} Ce site utilise des cookies Ce site utilise des cookies (function() { var file = ["https:\/\/mycreanet.fr\/wp-content\/et-cache\/4977\/et-divi-dynamic-tb-6374-tb-469-tb-6415-4977-late.css"]; var handle = document.getElementById('divi-style-inline-inline-css'); var location = handle.parentNode; if (0===document.querySelectorAll('link[href="' + file + '"]').length) { var link = document.createElement('link'); link.rel = 'stylesheet'; link.id = 'et-dynamic-late-css'; link.href = file; location.insertBefore(link, handle.nextSibling); } })(); var et_link_options_data = [{"class":"et_pb_row_0_tb_body","url":"https:\/\/mycreanet.fr\/contact\/","target":"_self"}]; /* <![CDATA[ */ var tocplus = {"smooth_scroll":"1","visibility_show":"Afficher","visibility_hide":"Masquer","width":"Auto"}; /* ]]> */ /* <![CDATA[ */ var DIVI = {"item_count":"%d Item","items_count":"%d Items"}; var et_builder_utils_params = {"condition":{"diviTheme":true,"extraTheme":false},"scrollLocations":["app","top"],"builderScrollLocations":{"desktop":"app","tablet":"app","phone":"app"},"onloadScrollLocation":"app","builderType":"fe"}; var et_frontend_scripts = {"builderCssContainerPrefix":"#et-boc","builderCssLayoutPrefix":"#et-boc .et-l"}; var et_pb_custom = {"ajaxurl":"https:\/\/mycreanet.fr\/wp-admin\/admin-ajax.php","images_uri":"https:\/\/mycreanet.fr\/wp-content\/themes\/Divi\/images","builder_images_uri":"https:\/\/mycreanet.fr\/wp-content\/themes\/Divi\/includes\/builder\/images","et_frontend_nonce":"a09614beb4","subscription_failed":"Veuillez v\u00e9rifier les champs ci-dessous pour vous assurer que vous avez entr\u00e9 les informations correctes.","et_ab_log_nonce":"46fb6ab5d3","fill_message":"S'il vous pla\u00eet, remplissez les champs suivants:","contact_error_message":"Veuillez corriger les erreurs suivantes :","invalid":"E-mail non valide","captcha":"Captcha","prev":"Pr\u00e9c\u00e9dent","previous":"Pr\u00e9c\u00e9dente","next":"Prochaine","wrong_captcha":"Vous avez entr\u00e9 le mauvais num\u00e9ro dans le captcha.","wrong_checkbox":"Case \u00e0 cocher","ignore_waypoints":"no","is_divi_theme_used":"1","widget_search_selector":".widget_search","ab_tests":[],"is_ab_testing_active":"","page_id":"4977","unique_test_id":"","ab_bounce_rate":"5","is_cache_plugin_active":"no","is_shortcode_tracking":"","tinymce_uri":"https:\/\/mycreanet.fr\/wp-content\/themes\/Divi\/includes\/builder\/frontend-builder\/assets\/vendors","accent_color":"#006666","waypoints_options":[]}; var et_pb_box_shadow_elements = []; /* ]]> */ /* <![CDATA[ */ var DiviBlogExtrasFrontendData = {"ajaxurl":"https:\/\/mycreanet.fr\/wp-admin\/admin-ajax.php","ajax_nonce":"190cac72c3","et_theme_accent_color":"#006666"}; /* ]]> */ /* <![CDATA[ */ var consent_api = {"consent_type":"optin","waitfor_consent_hook":"1","cookie_expiration":"30","cookie_prefix":"wp_consent"}; /* ]]> */ /* <![CDATA[ */ var complianz = {"prefix":"cmplz_","user_banner_id":"1","set_cookies":[],"block_ajax_content":"","banner_version":"165","version":"7.5.0.1","store_consent":"1","do_not_track_enabled":"1","consenttype":"optin","region":"us","geoip":"1","dismiss_timeout":"","disable_cookiebanner":"","soft_cookiewall":"","dismiss_on_scroll":"","cookie_expiry":"365","url":"https:\/\/mycreanet.fr\/wp-json\/complianz\/v1\/","locale":"lang=fr&locale=fr_FR","set_cookies_on_root":"","cookie_domain":"","current_policy_id":"27","cookie_path":"\/","categories":{"statistics":"statistiques","marketing":"marketing"},"tcf_active":"","placeholdertext":"Cliquez pour accepter les cookies {category} et activer ce contenu","css_file":"https:\/\/mycreanet.fr\/wp-content\/uploads\/complianz\/css\/banner-{banner_id}-{type}.css?v=165","page_links":{"eu":{"cookie-statement":{"title":"Services","url":"https:\/\/mycreanet.fr\/services\/"},"privacy-statement":{"title":"Services","url":"https:\/\/mycreanet.fr\/services\/"}},"ca":{"cookie-statement":{"title":"Services","url":"https:\/\/mycreanet.fr\/services\/"},"privacy-statement":{"title":"Services","url":"https:\/\/mycreanet.fr\/services\/"},"privacy-statement-children":{"title":"","url":"https:\/\/mycreanet.fr\/2-lento-molt-amable-arr-by-carlo-marchione\/"}},"za":{"cookie-statement":{"title":"Services","url":"https:\/\/mycreanet.fr\/services\/"},"privacy-statement":{"title":"Services","url":"https:\/\/mycreanet.fr\/services\/"},"privacy-statement-children":{"title":"","url":"https:\/\/mycreanet.fr\/2-lento-molt-amable-arr-by-carlo-marchione\/"}}},"tm_categories":"1","forceEnableStats":"","preview":"","clean_cookies":"","aria_label":"Cliquez pour accepter les cookies {category} et activer ce contenu"}; /* ]]> */ /* <![CDATA[ */ var mejsL10n = {"language":"fr","strings":{"mejs.download-file":"T\u00e9l\u00e9charger le fichier","mejs.install-flash":"Vous utilisez un navigateur qui n\u2019a pas le lecteur Flash activ\u00e9 ou install\u00e9. Veuillez activer votre extension Flash ou t\u00e9l\u00e9charger la derni\u00e8re version \u00e0 partir de cette adresse\u00a0: https:\/\/get.adobe.com\/flashplayer\/","mejs.fullscreen":"Plein \u00e9cran","mejs.play":"Lecture","mejs.pause":"Pause","mejs.time-slider":"Curseur de temps","mejs.time-help-text":"Utilisez les fl\u00e8ches droite\/gauche pour avancer d\u2019une seconde, haut\/bas pour avancer de dix secondes.","mejs.live-broadcast":"\u00c9mission en direct","mejs.volume-help-text":"Utilisez les fl\u00e8ches haut\/bas pour augmenter ou diminuer le volume.","mejs.unmute":"R\u00e9activer le son","mejs.mute":"Muet","mejs.volume-slider":"Curseur de volume","mejs.video-player":"Lecteur vid\u00e9o","mejs.audio-player":"Lecteur audio","mejs.captions-subtitles":"L\u00e9gendes\/Sous-titres","mejs.captions-chapters":"Chapitres","mejs.none":"Aucun","mejs.afrikaans":"Afrikaans","mejs.albanian":"Albanais","mejs.arabic":"Arabe","mejs.belarusian":"Bi\u00e9lorusse","mejs.bulgarian":"Bulgare","mejs.catalan":"Catalan","mejs.chinese":"Chinois","mejs.chinese-simplified":"Chinois (simplifi\u00e9)","mejs.chinese-traditional":"Chinois (traditionnel)","mejs.croatian":"Croate","mejs.czech":"Tch\u00e8que","mejs.danish":"Danois","mejs.dutch":"N\u00e9erlandais","mejs.english":"Anglais","mejs.estonian":"Estonien","mejs.filipino":"Filipino","mejs.finnish":"Finnois","mejs.french":"Fran\u00e7ais","mejs.galician":"Galicien","mejs.german":"Allemand","mejs.greek":"Grec","mejs.haitian-creole":"Cr\u00e9ole ha\u00eftien","mejs.hebrew":"H\u00e9breu","mejs.hindi":"Hindi","mejs.hungarian":"Hongrois","mejs.icelandic":"Islandais","mejs.indonesian":"Indon\u00e9sien","mejs.irish":"Irlandais","mejs.italian":"Italien","mejs.japanese":"Japonais","mejs.korean":"Cor\u00e9en","mejs.latvian":"Letton","mejs.lithuanian":"Lituanien","mejs.macedonian":"Mac\u00e9donien","mejs.malay":"Malais","mejs.maltese":"Maltais","mejs.norwegian":"Norv\u00e9gien","mejs.persian":"Perse","mejs.polish":"Polonais","mejs.portuguese":"Portugais","mejs.romanian":"Roumain","mejs.russian":"Russe","mejs.serbian":"Serbe","mejs.slovak":"Slovaque","mejs.slovenian":"Slov\u00e9nien","mejs.spanish":"Espagnol","mejs.swahili":"Swahili","mejs.swedish":"Su\u00e9dois","mejs.tagalog":"Tagalog","mejs.thai":"Thai","mejs.turkish":"Turc","mejs.ukrainian":"Ukrainien","mejs.vietnamese":"Vietnamien","mejs.welsh":"Ga\u00e9lique","mejs.yiddish":"Yiddish"}}; /* ]]> */ /* <![CDATA[ */ var _wpmejsSettings = {"pluginPath":"\/wp-includes\/js\/mediaelement\/","classPrefix":"mejs-","stretching":"responsive","audioShortcodeLibrary":"mediaelement","videoShortcodeLibrary":"mediaelement"}; /* ]]> */ (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer',''); .wptpa_song_infrmtn, .wptpa_currenttime, .wptpa_duration, .wptpa_song, .wptpa_dwn_cnt, .wptpa_play_cnt, .wptpa_num, .wptpa_h2, .wptpa_ads{ font-family: 'Roboto', sans-serif; } .wptpa_player { background: #FFFFFF !important; } .wptpa_heading:before, .wptpa_heading:after { background: #000000 !important; } .wptpa_song_infrmtn { color: #000000 !important; } .wptpa_btn .wptpa_icon { fill: #555555; } .wptpa_btn.actv .wptpa_icon, .wptpa_btn:hover .wptpa_icon{ fill: #00D084; } .wptpa_btn:before{ background: #555555 !important; } .wptpa_player .wptpa_seek, .wptpa_player .wptpa_loader { background: #FFDA48 !important; } .wptpa_player .wptpa_seek span, .wptpa_progress { background: #CF2E2E !important; } .wptpa_ads, .wptpa_currenttime, .wptpa_duration { color: #FFFFFF !important; } .wptpa_volume_seek:before { background: #FFDA48 !important; } .wptpa_volume_value { background: #CF2E2E !important; } .wptpa_pllst_itm { border-bottom: 1px solid rgba(255, 255, 255, 0.25) !important; background: #23C5A3 !important; color: #000000 !important; } .wptpa_pllst_itm.crrnt, .wptpa_pllst_itm:hover { background: #FFDA48 !important; color: #000000 !important; } .wptpa_pllst_itm:last-child { border-bottom: 0px solid rgba(255, 255, 255, 0.25) !important; } .wptpa_bars, .wptpa_bars:before, .wptpa_bars:after{ background: #000000 !important; } .wptpa_line { border-color: #000000 !important; } .wptpa_pllst_itm .wptpa_icon { fill: #000000; } .wptpa_dwn_cnt, .wptpa_play_cnt { color: #000000 !important; } .wptpa_scroll_bar { background: #000000 !important; }