Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 17:58:52 +08:00
commit eac17f89fa
40 changed files with 4048 additions and 0 deletions

View File

@@ -0,0 +1,191 @@
# Framework Make Invalide
Génère une classe Invalide pour exceptions métier d'une entité.
## Vue d'ensemble
Cette skill crée une classe Invalide qui encapsule les exceptions métier spécifiques à une entité selon les principes Elegant Objects.
## Caractéristiques
### Classe Invalide générée
- Classe `final`
- Constructeur privé
- Factory statique `new()`
- Encapsule l'entité
- Base pour méthodes factory d'exceptions
## Utilisation
```bash
Use skill framework:make:invalide
```
Vous serez invité à fournir le nom de l'entité.
## Exemple d'utilisation
```bash
EntityName: Product
```
Génère :
```php
// src/Invalide/ProductInvalide.php
final class ProductInvalide
{
private function __construct(
private Product $product,
) {}
public static function new(Product $product): self
{
return new self(product: $product);
}
}
```
## Structure créée
```
src/
└── Invalide/
└── {EntityName}Invalide.php
```
## Prérequis
- L'entité doit exister dans `src/Entity/{EntityName}.php`
## Usage recommandé
### Dans l'entité
```php
final class Product implements InvalideInterface
{
public function invalide(): ProductInvalide
{
return ProductInvalide::new(product: $this);
}
}
```
### Enrichissement avec exceptions métier
```php
final class ProductInvalide
{
private function __construct(
private Product $product,
) {}
public static function new(Product $product): self
{
return new self(product: $product);
}
// Exceptions de validation
public static function carNomVide(): \InvalidArgumentException
{
return new \InvalidArgumentException(
'Le nom du produit ne peut pas être vide'
);
}
public static function carPrixNegatif(): \InvalidArgumentException
{
return new \InvalidArgumentException(
'Le prix ne peut pas être négatif'
);
}
// Exceptions métier
public static function carStockInsuffisant(
int $demande,
int $disponible
): \DomainException {
return new \DomainException(
sprintf(
'Stock insuffisant: %d demandé, %d disponible',
$demande,
$disponible
)
);
}
public static function carProduitInactif(string $id): \DomainException
{
return new \DomainException(
sprintf('Le produit %s est inactif', $id)
);
}
}
```
### Utilisation dans le code
```php
// Validation dans factory
public static function create(
Uuid $id,
string $name,
float $price
): self {
if ('' === $name) {
throw ProductInvalide::carNomVide();
}
if ($price < 0) {
throw ProductInvalide::carPrixNegatif();
}
return new self(id: $id, name: $name, price: $price);
}
// Validation métier
public function decreaseStock(int $quantity): void
{
if (!$this->isActive) {
throw ProductInvalide::carProduitInactif($this->id->toRfc4122());
}
if ($this->stock < $quantity) {
throw ProductInvalide::carStockInsuffisant(
demande: $quantity,
disponible: $this->stock
);
}
$this->stock -= $quantity;
}
```
## Conventions de nommage
### Méthodes factory
- Préfixe : `car` (français)
- Format : `carRaisonDeLErreur`
- Exemples :
- `carNomVide()`
- `carEmailInvalide()`
- `carStockInsuffisant()`
- `carProduitInactif()`
### Messages d'exception
- Pas de point final
- Inclure le contexte maximum
- Une seule phrase sans points internes
- Exemples :
-`'Le nom du produit ne peut pas être vide'`
-`'Stock insuffisant: 5 demandé, 2 disponible'`
-`'Erreur.'`
-`'Le nom est vide. Veuillez le renseigner.'`
## Types d'exceptions recommandés
- `\InvalidArgumentException` - Validation d'arguments
- `\DomainException` - Règles métier
- `\LogicException` - État incohérent
- `\RuntimeException` - Erreur runtime
## Principes Elegant Objects appliqués
- Classe finale
- Constructeur privé
- Factory statiques
- Fail fast
- Messages d'erreur avec contexte
- Exceptions spécifiques au domaine

View File

@@ -0,0 +1,185 @@
---
name: framework:make:invalide
description: Génère classe Invalide (exceptions métier)
license: MIT
version: 1.0.0
---
# Framework Make Invalide Skill
## Description
Génère une classe Invalide pour gérer les exceptions métier d'une entité.
La classe Invalide encapsule l'entité et fournit des factory methods pour créer des exceptions spécifiques au contexte métier.
## Usage
```
Use skill framework:make:invalide
Vous serez invité à fournir :
- Le nom de l'entité (ex: Product, User, Order)
```
## Templates
- `Invalide/UtilisateurInvalide.php` - Template de classe Invalide
## Variables requises
- **{EntityName}** - Nom de l'entité en PascalCase (ex: Utilisateur, Product)
- **{entityName}** - Nom de l'entité en camelCase (ex: utilisateur, product)
- **{namespace}** - Namespace du projet (défaut: App)
## Dépendances
- Requiert que l'entité existe dans `src/Entity/{EntityName}.php`
## Outputs
- `src/Invalide/{EntityName}Invalide.php`
## Workflow
1. Demander le nom de l'entité (EntityName)
2. Vérifier que l'entité existe dans `src/Entity/{EntityName}.php`
- Si non : arrêter et demander de créer l'entité d'abord
3. Générer la classe Invalide depuis le template :
- Remplacer `{EntityName}` par le nom fourni
- Remplacer `{entityName}` par la version camelCase
4. Afficher le fichier créé
## Patterns appliqués
### Classe Invalide
- Classe `final`
- Constructeur privé
- Factory statique `new()` pour instanciation
- Propriété privée de type entité
- Méthodes factory statiques pour exceptions spécifiques
## Exemple
```bash
Use skill framework:make:invalide
# Saisies utilisateur :
EntityName: Product
# Résultat :
✓ src/Invalide/ProductInvalide.php
```
Fichier généré :
```php
<?php
declare(strict_types=1);
namespace App\Invalide;
use App\Entity\Product;
final class ProductInvalide
{
private function __construct(
private Product $product,
) {
}
public static function new(
Product $product,
): self {
return new self(
product: $product,
);
}
}
```
## Usage dans l'entité
L'entité doit implémenter la méthode `invalide()` :
```php
public function invalide(): ProductInvalide
{
return ProductInvalide::new(
product: $this,
);
}
```
## Enrichissement avec exceptions métier
Ajouter des méthodes factory pour les cas d'erreur spécifiques :
```php
final class ProductInvalide
{
private function __construct(
private Product $product,
) {}
public static function new(Product $product): self
{
return new self(product: $product);
}
public static function carPrixNegatif(): \InvalidArgumentException
{
return new \InvalidArgumentException(
'Le prix du produit ne peut pas être négatif'
);
}
public static function carStockInsuffisant(int $demande, int $disponible): \DomainException
{
return new \DomainException(
sprintf(
'Stock insuffisant: %d demandé, %d disponible',
$demande,
$disponible
)
);
}
public static function carNomVide(): \InvalidArgumentException
{
return new \InvalidArgumentException(
'Le nom du produit ne peut pas être vide'
);
}
}
```
## Usage des exceptions
```php
final class Product
{
public static function create(Uuid $id, string $name, float $price): self
{
if ('' === $name) {
throw ProductInvalide::carNomVide();
}
if ($price < 0) {
throw ProductInvalide::carPrixNegatif();
}
return new self(id: $id, name: $name, price: $price);
}
public function decreaseStock(int $quantity): void
{
if ($this->stock < $quantity) {
throw ProductInvalide::carStockInsuffisant(
demande: $quantity,
disponible: $this->stock
);
}
// ...
}
}
```
## Notes
- Les méthodes factory d'exceptions doivent commencer par `car` (convention)
- Les messages d'exception ne doivent pas finir par un point
- Les messages doivent inclure le maximum de contexte
- Privilégier les exceptions standard PHP (\InvalidArgumentException, \DomainException)
- Respecte le principe "fail fast"

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Invalide;
use App\Entity\Utilisateur;
final class UtilisateurInvalide
{
private function __construct(
private Utilisateur $utilisateur,
) {
}
public static function new(
Utilisateur $utilisateur,
): self {
return new self(
utilisateur: $utilisateur,
);
}
}