Sylius et API Platform : exposer votre catalogue en REST et GraphQL
Sylius 2.x integre API Platform 4 comme citoyen de premiere classe. Chaque resource (produit, commande, client, panier) est exposee via une API REST complete et optionnellement en GraphQL. Voici comment l'exploiter et la personnaliser.
L'API par defaut
Des l'installation, Sylius expose deux familles d'endpoints :
| Namespace | Audience | Exemples |
|---|---|---|
/api/v2/shop/ | Frontend (clients) | Produits, panier, checkout, compte |
/api/v2/admin/ | Back-office | CRUD complet sur toutes les resources |
La documentation interactive (Swagger UI) est accessible a /api/v2/docs.
Configuration des resources
Les resources API sont declarees via des attributs PHP (API Platform 4) :
<?php
// Pour ajouter un endpoint custom sur les produits
namespace App\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
#[Get(
uriTemplate: '/shop/products/{code}/availability',
provider: ProductAvailabilityProvider::class,
normalizationContext: ['groups' => ['shop:product:availability']],
)]
class ProductAvailability
{
public string $code;
public bool $inStock;
public int $quantity;
public ?string $estimatedRestockDate;
}
Authentification JWT
Pour obtenir un token :
curl -X POST https://votre-site.com/api/v2/shop/authentication-token \
-H "Content-Type: application/json" \
-d '{"email": "client@example.com", "password": "motdepasse"}'
# Reponse
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
}
# Utilisation
curl https://votre-site.com/api/v2/shop/orders \
-H "Authorization: Bearer eyJ0eXAiOiJKV1Q..."
Personnaliser la serialisation
Sylius utilise des groupes de serialisation pour controler les champs exposes. Pour ajouter un champ custom :
<?php
// src/Entity/Product/Product.php
namespace App\Entity\Product;
use Sylius\Component\Core\Model\Product as BaseProduct;
use Symfony\Component\Serializer\Annotation\Groups;
class Product extends BaseProduct
{
#[Groups(['shop:product:read', 'shop:product:index'])]
private ?string $customBadge = null;
public function getCustomBadge(): ?string
{
return $this->customBadge;
}
}
Activer GraphQL
composer require api-platform/graphql
# config/packages/api_platform.yaml
api_platform:
graphql:
enabled: true
L'interface GraphiQL est alors accessible a /api/v2/graphql. Exemple de requete :
{
products(first: 10) {
edges {
node {
code
name
shortDescription
variants {
edges {
node {
code
price
inStock
}
}
}
}
}
}
}
Gestion du panier via l'API
Le workflow complet du panier est disponible en API :
# Creer un panier
POST /api/v2/shop/orders
{ "localeCode": "fr_FR" }
# Ajouter un produit
POST /api/v2/shop/orders/{token}/items
{
"productVariant": "/api/v2/shop/product-variants/TSHIRT-RED-M",
"quantity": 2
}
# Voir le panier
GET /api/v2/shop/orders/{token}
# Passer au checkout
PATCH /api/v2/shop/orders/{token}/address
{
"billingAddress": { ... },
"shippingAddress": { ... }
}
PATCH /api/v2/shop/orders/{token}/select-shipping-method/{shipmentId}
{ "shippingMethod": "/api/v2/shop/shipping-methods/UPS" }
PATCH /api/v2/shop/orders/{token}/select-payment-method/{paymentId}
{ "paymentMethod": "/api/v2/shop/payment-methods/STRIPE" }
PATCH /api/v2/shop/orders/{token}/complete
Filtres et pagination
API Platform fournit des filtres puissants sur les collections :
# Produits d'un taxon
GET /api/v2/shop/products?productTaxons.taxon.code=t-shirts
# Recherche par nom
GET /api/v2/shop/products?translations.name=Chemise
# Pagination
GET /api/v2/shop/products?page=2&itemsPerPage=20
# Tri
GET /api/v2/shop/products?order[price]=asc
Bonnes pratiques
- Utilisez les groupes de serialisation pour ne pas exposer de donnees sensibles
- Cachez les reponses API avec Varnish ou un CDN (les listings produits changent peu)
- Limitez le rate sur les endpoints d'authentification
- Versionnez vos endpoints custom pour ne pas casser les clients existants
- Testez avec Postman ou Bruno avant d'integrer dans le front
Vous souhaitez construire un e-commerce headless avec Sylius ? Contactez-nous pour discuter de votre architecture. Voir aussi notre guide sur l'integration d'un frontend headless.
