akyos/ux-forms

Administrable contact forms and email templates for Symfony admin

Maintainers

Package info

github.com/akyoscommunication/ux-forms

Type:symfony-bundle

pkg:composer/akyos/ux-forms

Transparency log

Statistics

Installs: 11

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.1 2026-08-18 07:58 UTC

This package is auto-updated.

Last update: 2026-08-18 08:02:19 UTC


README

Bundle Symfony pour gérer des formulaires de contact administrables : création de champs en back-office, affichage public, envoi d'e-mails de notification, historique des soumissions.

Sommaire

  1. Prérequis
  2. Installation
  3. Configuration
  4. Routes
  5. Utilisation
  6. Architecture
  7. Personnalisation (override)
  8. Modèle de données
  9. Variables d'e-mail
  10. Traductions
  11. Tests & fixtures

Prérequis

Dépendance Rôle
PHP ≥ 8.4
Symfony 7 ou 8 Framework
Doctrine ORM 3 Entités & migrations
Symfony Mailer Notifications
symfony/ux-live-component Formulaires admin & public réactifs
symfony/ux-twig-component Composants Twig (twig:Admin:ContactForm:…)
akyos/ux-filters Filtres des listes admin
akyos/ux-table Tableaux paginés admin

Côté application hôte, les templates du bundle s'appuient aussi sur :

  • symfony/ux-toolkit (Button, Card, Tabs, Dialog, Badge, Breadcrumb, Sidebar…)
  • symfony/ux-icons (twig:ux:icon)
  • Tailwind CSS (classes utilitaires dans les templates)

Installation

1. Composer

Depuis un dépôt path (monorepo) :

{
    "repositories": [
        { "type": "path", "url": "lib/ux-forms" }
    ],
    "require": {
        "akyos/ux-forms": "@dev"
    }
}

Depuis un dépôt Git : adapter l'URL selon votre forge.

composer require akyos/ux-forms

2. Enregistrer le bundle

// config/bundles.php
Akyos\UXForms\UXFormsBundle::class => ['all' => true],

Le bundle enregistre automatiquement :

  • le mapping Doctrine ORM (Akyos\UXForms\Entity)
  • les migrations (Akyos\UXForms\Migrations)
  • les traductions (lib/ux-forms/translations)
  • le namespace Twig @UXForms
  • les Twig Components Akyos\UXForms\Twig\Components\
  • le chemin Asset Mapper ux-forms/lib/ux-forms/assets

3. Configuration

# config/packages/ux_forms.yaml
ux_forms:
    admin_layout: admin/layouts/layout.html.twig
    allowed_roles:
        - ROLE_ADMIN
        - ROLE_SUPER_ADMIN
    sender_email: '%env(UX_FORMS_SENDER_EMAIL)%'
    sender_name: '%env(UX_FORMS_SENDER_NAME)%'
    public_base_url: '%env(DEFAULT_URI)%'
    email_layout_template: '@UXForms/email/layout.html.twig'
    email_notification_template: '@UXForms/email/contact_form_notification.html.twig'
    email_logo_directory: '%kernel.project_dir%/public/ux-forms/email'
    email_logo_uri_prefix: '/ux-forms/email'

Variables d'environnement typiques :

UX_FORMS_SENDER_EMAIL=noreply@example.com
UX_FORMS_SENDER_NAME="Mon application"
DEFAULT_URI=https://www.example.com

4. Mailer Symfony

Configurer un transport SMTP (ou autre) :

# config/packages/mailer.yaml
framework:
    mailer:
        dsn: '%env(MAILER_DSN)%'

5. Routes

# config/routes/ux_forms.yaml
ux_forms:
    resource: ../../vendor/akyos/ux-forms/config/routes.php
    type: php
    prefix: /admin
    name_prefix: admin_

# config/routes/ux_forms_public.yaml
ux_forms_public:
    resource: ../../vendor/akyos/ux-forms/config/routes_public.php
    type: php

En monorepo, remplacer vendor/akyos/ux-forms par lib/ux-forms.

6. Sécurité

Les contrôleurs admin utilisent ContactFormVoter (CONTACT_FORM_VIEW, EDIT, CREATE) et les rôles définis dans allowed_roles.

Exemple d'accès public au formulaire front :

# config/packages/security.yaml
security:
    access_control:
        - { path: ^/contact-form, roles: PUBLIC_ACCESS }
        - { path: ^/admin, roles: ROLE_ADMIN }

Adapter selon votre modèle de rôles.

7. Sidebar admin (optionnel)

Inclure le fragment de navigation fourni :

{# templates/admin/layouts/sidebar.html.twig #}
{{ include('@UXForms/admin/_sidebar.html.twig') }}

8. Stimulus (éditeur de champs admin)

Le drag-and-drop de l'éditeur de champs nécessite le contrôleur field_sortable :

# config/packages/stimulus.yaml
stimulus:
    controller_paths:
        - '%kernel.project_dir%/assets/controllers'
        - '%kernel.project_dir%/vendor/akyos/ux-forms/assets/controllers'

9. Migrations

php bin/console doctrine:migrations:migrate

Les migrations du bundle créent notamment :

  • contact_form, contact_form_field, contact_form_recipient
  • email_template, email_layout
  • contact_form_submission

10. Données de démo (optionnel)

php bin/console doctrine:fixtures:load --group=default
# ou charger Akyos\UXForms\DataFixtures\UXFormsFixtures manuellement

Configuration

Clé Défaut Description
admin_layout admin/layouts/layout.html.twig Layout Twig des pages admin du bundle. Exposé en global ux_forms_admin_layout.
allowed_roles ROLE_ADMIN, ROLE_SUPER_ADMIN Rôles autorisés sur les écrans admin (via ContactFormVoter).
sender_email noreply@localhost Expéditeur des e-mails de notification.
sender_name SEFCA Nom affiché de l'expéditeur.
public_base_url http://localhost URL publique pour les assets e-mail (logo).
email_layout_template @UXForms/email/layout.html.twig Layout HTML des e-mails.
email_notification_template @UXForms/email/contact_form_notification.html.twig Corps HTML de la notification.
email_logo_directory public/ux-forms/email Répertoire d'upload du logo (admin).
email_logo_uri_prefix /ux-forms/email Préfixe URI public du logo.

Routes

Admin (préfixe /admin, noms admin_*)

Nom URL Description
admin_formulaires_index /admin/formulaires Liste des formulaires
admin_formulaires_new /admin/formulaires/new Création
admin_formulaires_edit /admin/formulaires/{id} Édition
admin_formulaires_soumissions_index /admin/formulaires/soumissions Liste des soumissions
admin_formulaires_soumissions_show /admin/formulaires/soumissions/{id} Détail d'une soumission
admin_formulaires_modele_email /admin/formulaires/modele-email Modèle e-mail (logo, couleurs, pied de page)

Front

Nom URL Description
contact_form_show /contact-form/{id} Page publique d'un formulaire

Utilisation

Afficher un formulaire sur le front

Option A — route dédiée (déjà fournie) :

/contact-form/1

Option B — intégrer le LiveComponent dans n'importe quelle page :

{# Par entité #}
<twig:Front:PublicForm :contactForm="contactForm" />

{# Ou par ID #}
<twig:Front:PublicForm :contactFormId="1" />

Le composant gère validation, message de confirmation et soumission AJAX (LiveComponent).

Flux de soumission

Visiteur submit
    → PublicForm (LiveComponent)
    → ContactFormSubmissionHandlerInterface::handle()
    → ContactFormSubmissionService::submit()
        1. Snapshot des champs en BDD (contact_form_submission)
        2. Envoi e-mail via ContactFormMailer
        3. Mise à jour du statut (sent / failed)

L'utilisateur voit le message de confirmation même si l'e-mail échoue ; l'échec est visible dans l'admin (liste + détail des soumissions).

Architecture

lib/ux-forms/
├── config/
│   ├── routes.php              # Routes admin
│   ├── routes_public.php       # Route front
│   └── services.yaml           # Wiring DI
├── migrations/                 # Migrations Doctrine
├── src/
│   ├── Contract/               # Points d'extension publics
│   ├── Controller/             # Admin + Front
│   ├── Entity/
│   ├── Mailer/
│   ├── Security/Voter/
│   ├── Service/
│   └── Twig/Components/        # LiveComponents admin & front
├── templates/                  # Namespace @UXForms
├── translations/
└── assets/controllers/         # Stimulus (field-sortable)

Personnalisation (override)

1. Handler de soumission ⭐ (extension principale)

Interface :

// src/Contract/ContactFormSubmissionHandlerInterface.php
public function handle(ContactForm $contactForm, array $values): void;

Implémentation par défaut : persistance + envoi e-mail + statut.

Override complet — remplacer le service :

// src/Contact/MySubmissionHandler.php
namespace App\Contact;

use Akyos\UXForms\Contract\ContactFormSubmissionHandlerInterface;
use Akyos\UXForms\Entity\ContactForm;

final class MySubmissionHandler implements ContactFormSubmissionHandlerInterface
{
    public function handle(ContactForm $contactForm, array $values): void
    {
        // CRM, webhook, persistance custom…
    }
}
# config/services.yaml
Akyos\UXForms\Contract\ContactFormSubmissionHandlerInterface:
    class: App\Contact\MySubmissionHandler

Override partiel — décorateur autour du service bundle :

final class LoggingSubmissionHandler implements ContactFormSubmissionHandlerInterface
{
    public function __construct(
        private ContactFormSubmissionHandler $inner,
        private LoggerInterface $logger,
    ) {}

    public function handle(ContactForm $contactForm, array $values): void
    {
        $this->inner->handle($contactForm, $values);
        $this->logger->info('Contact form submitted', ['id' => $contactForm->getId()]);
    }
}
Akyos\UXForms\Service\ContactFormSubmissionHandler:
    class: App\Contact\LoggingSubmissionHandler
    arguments:
        $inner: '@Akyos\UXForms\Service\ContactFormSubmissionHandler.inner'

Akyos\UXForms\Service\ContactFormSubmissionHandler.inner:
    class: Akyos\UXForms\Service\ContactFormSubmissionHandler

Réutiliser la logique bundle sans l'interface :

// Injection directe si besoin (CLI, listener…)
public function __construct(
    private ContactFormSubmissionService $submissionService,
) {}

2. Templates Twig

Namespace : @UXForms/…

Copier un template dans votre app et surcharger via la convention Symfony :

templates/bundles/UXFormsBundle/
└── admin/contact_form/index.html.twig

Ou redéclarer un chemin Twig prioritaire. Templates couramment surchargés :

Template Usage
@UXForms/admin/contact_form/*.html.twig Pages admin formulaires
@UXForms/admin/contact_form_submission/*.html.twig Soumissions
@UXForms/components/Front/PublicForm.html.twig Rendu public
@UXForms/email/layout.html.twig Layout e-mail
@UXForms/email/contact_form_notification.html.twig Corps notification
@UXForms/admin/_sidebar.html.twig Navigation admin

Config des templates e-mail sans copier les fichiers :

ux_forms:
    email_layout_template: 'email/my_layout.html.twig'
    email_notification_template: 'email/my_contact_notification.html.twig'

3. Layout admin

ux_forms:
    admin_layout: 'admin/my_layout.html.twig'

Le layout doit définir les blocs utilisés par les pages bundle (title, admin_breadcrumb, content). Les templates bundle étendent la variable globale ux_forms_admin_layout :

{% extends ux_forms_admin_layout %}

4. Sécurité & rôles

ux_forms:
    allowed_roles:
        - ROLE_GESTIONNAIRE
        - ROLE_ADMIN

Le voter ContactFormVoter accorde VIEW, EDIT, CREATE si l'utilisateur possède l'un de ces rôles.

Pour une logique plus fine, créer votre propre voter ou décorer le service existant (non prévu nativement — copier/étendre ContactFormVoter et remplacer le service).

5. Expéditeur & branding e-mail

Via config :

ux_forms:
    sender_email: 'contact@monapp.fr'
    sender_name: 'Mon App'
    public_base_url: 'https://monapp.fr'
    email_logo_directory: '%kernel.project_dir%/public/media/email'
    email_logo_uri_prefix: '/media/email'

Le logo et les couleurs se paramètrent aussi dans l'admin (/admin/formulaires/modele-email).

6. Traductions

Domaines fournis (fichiers *.fr.yaml) :

Domaine Contenu
contact_form Admin formulaires
contact_form_submission Admin soumissions
email_template Modèle e-mail admin
public_contact_form Formulaire public
validators Contraintes

Surcharge dans translations/ de l'app :

translations/contact_form.fr.yaml
translations/public_contact_form.fr.yaml

7. Routes

Les fichiers config/routes.php et config/routes_public.php du bundle peuvent être copiés dans l'app pour changer les URLs ou les noms, ou importés tels quels avec prefix / name_prefix.

Exemple — préfixer l'admin différemment :

ux_forms:
    resource: '@AkyosUXForms/config/routes.php'
    prefix: /backoffice
    name_prefix: backoffice_

8. Services internes (override avancé)

Service Rôle Override
ContactFormSubmissionHandlerInterface Point d'entrée soumission ✅ Recommandé
ContactFormSubmissionService Persistance + mail + statut Via handler custom ou alias DI
ContactFormMailer Envoi notification HTML/text Alias + classe custom
ContactFormEmailVariableResolver Variables {{prenom}}, {{contenu}} Alias si logique custom
EmailLogoStorage Upload logo e-mail Paramètres config ou service custom

Exemple — mailer custom :

Akyos\UXForms\Mailer\ContactFormMailer:
    class: App\Mailer\BrandedContactFormMailer
    arguments:
        $senderEmail: '%akyos_ux_forms.sender_email%'
        $senderName: '%akyos_ux_forms.sender_name%'
        # … autres dépendances autowirées

9. Composants Twig / LiveComponents

Enregistrés sous le préfixe :

twig:Admin:ContactForm:Index
twig:Admin:ContactForm:Edit
twig:Admin:ContactForm:Delete
twig:Admin:ContactFormSubmission:Index
twig:Admin:EmailLayout:Edit
twig:Front:PublicForm

Pour surcharger un composant, créer une classe dans votre namespace avec le même nom n'est pas supporté directement ; préférer :

  • surcharger le template @UXForms/components/…
  • ou remplacer l'include dans vos propres pages admin

10. Ce qui n'est pas prévu pour override

Élément Alternative
Entités Doctrine Ne pas modifier ; étendre via handler ou tables annexes
Migrations bundle Ne pas éditer ; ajouter vos propres migrations
Enum ContactFormFieldType Demander une évolution bundle ou champs custom via handler

Modèle de données

Entité Description
ContactForm Formulaire (libellé, actif, message confirmation, sujet/corps e-mail)
ContactFormField Champ (type, libellé, position, layout ligne/colonne)
ContactFormRecipient Destinataire notification
EmailTemplate Modèle e-mail réutilisable (legacy / référentiel)
EmailLayout Branding global (logo, couleur, pied de page) — singleton
ContactFormSubmission Soumission persistée (sans FK vers ContactForm)

ContactFormSubmission stocke un snapshot (contactFormLabel, fields JSON, submitterEmail, statut e-mail) pour conserver l'historique même après suppression du formulaire.

Types de champs : text, email, phone, date, select, textarea, checkbox.

Variables d'e-mail

Dans l'objet et le corps configurés en admin, syntaxe {{variable}} :

  • Une variable par champ actif, dérivée du libellé (Prénom{{prenom}}, collision → {{prenom_12}})
  • {{contenu}} — récapitulatif textuel de tous les champs

Résolution : ContactFormEmailVariableResolver.

Traductions

Le bundle shippe du français uniquement (*.fr.yaml). L'app hôte peut ajouter d'autres locales en miroir.

Textes UI : ne jamais les hardcoder — toujours passer par les domaines ci-dessus.

Tests & fixtures

# Tests unitaires du bundle
php vendor/bin/phpunit lib/ux-forms/tests/

# Tests d'intégration app hôte (exemple)
php vendor/bin/phpunit tests/Controller/Admin/UXForms/

Fixtures : Akyos\UXForms\DataFixtures\UXFormsFixtures (formulaire démo + modèle e-mail + layout).

Checklist d'intégration rapide

  • composer require akyos/ux-forms
  • Bundle enregistré dans bundles.php
  • config/packages/ux_forms.yaml
  • Routes admin + public importées
  • Mailer configuré (MAILER_DSN)
  • doctrine:migrations:migrate
  • Accès public /contact-form dans security.yaml
  • Sidebar : include('@UXForms/admin/_sidebar.html.twig')
  • Stimulus : chemin assets/controllers du bundle
  • UX Toolkit + UX Icons disponibles dans l'app