/doctrine-entity — Création et modification d'entités Doctrine
Tu aides à concevoir une entité Doctrine propre dans un projet Symfony ou Sylius. Tu ne ré-implémentes pas à la main ce que make:entity fait : tu t'appuies sur le générateur, puis tu complètes ce qui lui manque (colonnes nommées, index, contraintes, validation).
Détection préalable (obligatoire)
- Lire
composer.json à la racine du projet.
- Vérifier
symfony/framework-bundle dans les dépendances.
- Présent → OK, continuer.
- Absent → afficher : « Ce skill cible Symfony/Sylius, je ne trouve pas
symfony/framework-bundle dans composer.json. On continue quand même ou on change d'approche ? » et attendre la réponse.
- Si
sylius/sylius est aussi présent → mentionner en une ligne que les règles Sylius s'appliquent en plus (héritage des Resources, groupes de validation sylius, multi-channel).
Règles fondamentales
make:entity d'abord : symfony console make:entity (ou php bin/console make:entity). Ne jamais écrire une entité from scratch si le générateur peut la produire.
- Snake_case en BDD : chaque champ ou relation doit avoir
#[ORM\Column(name: 'mon_champ')] / #[ORM\JoinColumn(name: 'ma_relation_id')]. Sans ça, Doctrine crée la colonne en camelCase et l'écart avec la convention SQL projet passe silencieusement.
- Types financiers : stocker les montants en
integer (cents), jamais en float. Les arrondis flottants corrompent les totaux.
- Mots réservés SQL (
user, group, order) : #[ORM\Table(name: 'users')] ou variante pluralisée, sinon la DDL casse selon le SGBD.
- Strings uniques en MySQL < 8 :
length: 190 sur les colonnes avec unique: true, sinon l'index dépasse 767 bytes InnoDB.
- Validation auto-mappée :
nullable: false → NotNull, unique: true → UniqueEntity, length → Length. Pas besoin de re-déclarer sauf contrainte métier (Email, Regex, Range).
Déroulement
1 — Cadrer le besoin
Demander (ou confirmer si l'utilisateur a déjà donné les infos) :
- Nom de l'entité (PascalCase, singulier).
- Champs : nom, type, nullable, unique.
- Relations : autre entité, cardinalité, côté propriétaire, cascade.
- Héritage : entité Sylius à étendre ? → ajouter la config
sylius_<bundle>.resources dans _sylius.yaml.
2 — Exécuter make:entity
Lancer la commande. Si l'entité existe déjà, make:entity <Nom> permet d'ajouter des champs de façon interactive.
3 — Compléter le générateur
Pour chaque champ généré :
- Ajouter
name: 'snake_case' si le nom PHP est camelCase.
- Préciser
length, precision, scale, options selon le besoin.
- Ajouter les contraintes métier (
#[Assert\Email], #[Assert\Range], etc.).
Pour chaque relation :
- Préciser
JoinColumn(name: '…_id', nullable: …, onDelete: …).
- Choisir
cascade avec parcimonie — ['persist'] est le cas courant ; ['remove'] uniquement si la suppression en cascade est métier-désirée.
- Documenter le côté propriétaire (relation
ManyToMany : le côté inverse ne doit pas être persisté).
4 — Index et contraintes
Ajouter #[ORM\Index(columns: ['colonne'])] sur toute colonne utilisée en WHERE/JOIN/ORDER BY récurrent.
Ajouter #[ORM\UniqueConstraint(...)] pour les unicités composites.
5 — Vérifications
symfony console doctrine:schema:validate # cohérence mapping/BDD
vendor/bin/phpstan analyse src/Entity # types et nullabilité
Générer la migration associée via /symfony:doctrine-migration — ne pas lancer make:migration dans cette skill.
6 — Clôture
Afficher :
- Fichier(s) créé(s)/modifié(s).
- Champs et relations ajoutés.
- Ce qui reste : migration à générer, repository à compléter (→
/symfony:doctrine-query), fixtures à mettre à jour.
Cas Sylius (delta)
Si le stack est Sylius et qu'on étend une entité du vendor :
- Hériter de la classe de base (
Sylius\Component\Core\Model\Product, etc.) et implémenter l'interface (ProductInterface).
- Déclarer la classe custom dans
config/packages/_sylius.yaml sous sylius_<bundle>.resources.<resource>.classes.model.
- Ajouter les contraintes custom avec
groups: ['Default', 'sylius'], sinon elles sont ignorées par les forms Sylius.
- Pour un champ traduisible : entité
*Translation + TranslatableInterface sur l'entité principale + createTranslation().
Argument optionnel
/symfony:doctrine-entity Product — cadre et génère pour l'entité nommée.
/symfony:doctrine-entity src/Entity/Order.php — audite et complète une entité existante (noms de colonnes, index, contraintes).
/symfony:doctrine-entity sans argument — demande le nom et les champs à l'utilisateur.
1---2name: doctrine-entity3description: Crée ou modifie une entité Doctrine (Symfony/Sylius) — ORM, champs, relations, types custom. Déclenche sur "créer entité", "relation ManyToOne", "UniqueEntity", "mapping Doctrine". Impose make:entity et snake_case BDD.4---56# /doctrine-entity — Création et modification d'entités Doctrine78Tu aides à concevoir une entité Doctrine propre dans un projet Symfony ou Sylius. Tu ne ré-implémentes pas à la main ce que `make:entity` fait : tu t'appuies sur le générateur, puis tu complètes ce qui lui manque (colonnes nommées, index, contraintes, validation).910## Détection préalable (obligatoire)11121. Lire `composer.json` à la racine du projet.132. Vérifier `symfony/framework-bundle` dans les dépendances.14 - Présent → OK, continuer.15 - Absent → afficher : *« Ce skill cible Symfony/Sylius, je ne trouve pas `symfony/framework-bundle` dans composer.json. On continue quand même ou on change d'approche ? »* et attendre la réponse.163. Si `sylius/sylius` est aussi présent → mentionner en une ligne que les règles Sylius s'appliquent en plus (héritage des Resources, groupes de validation `sylius`, multi-channel).1718## Règles fondamentales1920- **`make:entity` d'abord** : `symfony console make:entity` (ou `php bin/console make:entity`). Ne jamais écrire une entité from scratch si le générateur peut la produire.21- **Snake_case en BDD** : chaque champ ou relation doit avoir `#[ORM\Column(name: 'mon_champ')]` / `#[ORM\JoinColumn(name: 'ma_relation_id')]`. Sans ça, Doctrine crée la colonne en camelCase et l'écart avec la convention SQL projet passe silencieusement.22- **Types financiers** : stocker les montants en `integer` (cents), jamais en `float`. Les arrondis flottants corrompent les totaux.23- **Mots réservés SQL** (`user`, `group`, `order`) : `#[ORM\Table(name: 'users')]` ou variante pluralisée, sinon la DDL casse selon le SGBD.24- **Strings uniques en MySQL < 8** : `length: 190` sur les colonnes avec `unique: true`, sinon l'index dépasse 767 bytes InnoDB.25- **Validation auto-mappée** : `nullable: false` → `NotNull`, `unique: true` → `UniqueEntity`, `length` → `Length`. Pas besoin de re-déclarer sauf contrainte métier (`Email`, `Regex`, `Range`).2627## Déroulement2829### 1 — Cadrer le besoin3031Demander (ou confirmer si l'utilisateur a déjà donné les infos) :3233- Nom de l'entité (PascalCase, singulier).34- Champs : nom, type, nullable, unique.35- Relations : autre entité, cardinalité, côté propriétaire, cascade.36- Héritage : entité Sylius à étendre ? → ajouter la config `sylius_<bundle>.resources` dans `_sylius.yaml`.3738### 2 — Exécuter `make:entity`3940Lancer la commande. Si l'entité existe déjà, `make:entity <Nom>` permet d'ajouter des champs de façon interactive.4142### 3 — Compléter le générateur4344Pour chaque champ généré :4546- Ajouter `name: 'snake_case'` si le nom PHP est camelCase.47- Préciser `length`, `precision`, `scale`, `options` selon le besoin.48- Ajouter les contraintes métier (`#[Assert\Email]`, `#[Assert\Range]`, etc.).4950Pour chaque relation :5152- Préciser `JoinColumn(name: '…_id', nullable: …, onDelete: …)`.53- Choisir `cascade` avec parcimonie — `['persist']` est le cas courant ; `['remove']` uniquement si la suppression en cascade est métier-désirée.54- Documenter le côté propriétaire (relation `ManyToMany` : le côté inverse ne doit pas être persisté).5556### 4 — Index et contraintes5758Ajouter `#[ORM\Index(columns: ['colonne'])]` sur toute colonne utilisée en WHERE/JOIN/ORDER BY récurrent.5960Ajouter `#[ORM\UniqueConstraint(...)]` pour les unicités composites.6162### 5 — Vérifications6364```bash65symfony console doctrine:schema:validate # cohérence mapping/BDD66vendor/bin/phpstan analyse src/Entity # types et nullabilité67```6869Générer la migration associée via **`/symfony:doctrine-migration`** — ne pas lancer `make:migration` dans cette skill.7071### 6 — Clôture7273Afficher :7475- Fichier(s) créé(s)/modifié(s).76- Champs et relations ajoutés.77- Ce qui reste : migration à générer, repository à compléter (→ `/symfony:doctrine-query`), fixtures à mettre à jour.7879## Cas Sylius (delta)8081Si le stack est Sylius et qu'on étend une entité du vendor :8283- Hériter de la classe de base (`Sylius\Component\Core\Model\Product`, etc.) et implémenter l'interface (`ProductInterface`).84- Déclarer la classe custom dans `config/packages/_sylius.yaml` sous `sylius_<bundle>.resources.<resource>.classes.model`.85- Ajouter les contraintes custom avec `groups: ['Default', 'sylius']`, sinon elles sont ignorées par les forms Sylius.86- Pour un champ traduisible : entité `*Translation` + `TranslatableInterface` sur l'entité principale + `createTranslation()`.8788## Argument optionnel8990`/symfony:doctrine-entity Product` — cadre et génère pour l'entité nommée.9192`/symfony:doctrine-entity src/Entity/Order.php` — audite et complète une entité existante (noms de colonnes, index, contraintes).9394`/symfony:doctrine-entity` sans argument — demande le nom et les champs à l'utilisateur.