Installation Add the package via Composer:
composer require comsa/sulu-shopping-cart
Ensure SuluShoppingCartBundle is enabled in config/bundles.php:
Comsa\SuluShoppingCartBundle\SuluShoppingCartBundle::class => ['all' => true],
Basic Setup Run migrations to create the required database tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Use Case: Adding a Product to Cart
Inject the CartManager service and use it to add a product:
use Comsa\SuluShoppingCartBundle\Manager\CartManagerInterface;
class MyController
{
public function __construct(private CartManagerInterface $cartManager) {}
public function addToCart(Product $product)
{
$cart = $this->cartManager->getCart();
$cart->addProduct($product);
$this->cartManager->persistCart($cart);
}
}
Where to Look First
config/packages/sulu_shopping_cart.yaml for default settings.CartManagerInterface and related services in src/Manager/.Cart Management
$cart = $this->cartManager->getCart(); // Gets or creates a cart for the current user.
$cart->updateProductQuantity($productId, 3);
$this->cartManager->persistCart($cart);
$this->cartManager->clearCart();
Product Integration
ProductRuleInterface to validate products (e.g., stock, pricing):
$rule = new StockRule(5); // Allow max 5 items.
$this->cartManager->addProductRule($rule);
ProductInterface to integrate with your product system:
class MyProduct implements ProductInterface
{
public function getId(): string { /* ... */ }
public function getPrice(): float { /* ... */ }
// ...
}
Checkout Process
if (!$this->cartManager->validateCart($cart)) {
throw new \RuntimeException("Cart validation failed.");
}
Persistence
sulu_shopping_cart.yaml:
sulu_shopping_cart:
storage: database # or 'session'
cart.product.added or cart.updated events for real-time updates:
$dispatcher->addListener('cart.product.added', function (CartEvent $event) {
// Send notification, update UI, etc.
});
CartRepositoryInterface to fetch carts by ID (e.g., for order history):
$cart = $this->cartRepository->findById($cartId);
CartManagerInterface in unit tests to isolate logic:
$this->cartManager = $this->createMock(CartManagerInterface::class);
$this->cartManager->method('getCart')->willReturn($mockCart);
Session Storage Limitations
database storage for critical applications or implement a hybrid approach.Product Rule Conflicts
StockRule + MaxQuantityRule) may cause unexpected rejections.RuleValidator to handle conflicts:
$validator = new RuleValidator([$rule1, $rule2]);
if (!$validator->isValid($product)) { /* ... */ }
Cart Expiration
ttl (time-to-live) in sulu_shopping_cart.yaml:
sulu_shopping_cart:
ttl: 3600 # 1 hour in seconds
Database Locking
$cart = $this->cartRepository->find($id);
$cart->lock(); // If supported.
$cart->addProduct($product);
$this->cartRepository->save($cart);
sulu_shopping_cart:
debug: true
cart.updated).Product and CartItem entities implement all required interfaces/methods.Custom Storage
StorageInterface to use Redis, Elasticsearch, etc.:
class RedisStorage implements StorageInterface
{
public function save(Cart $cart) { /* ... */ }
public function findById(string $id) { /* ... */ }
}
services.yaml:
Comsa\SuluShoppingCartBundle\Storage\StorageInterface: '@redis_storage'
Custom Rules
ProductRule for business logic (e.g., "Blacklist categories"):
class CategoryBlacklistRule implements ProductRuleInterface
{
public function isAllowed(ProductInterface $product): bool
{
return !in_array($product->getCategory(), ['electronics', 'restricted']);
}
}
API Extensions
JsonResponse:
#[Route('/api/cart', methods: ['POST'])]
public function updateCart(Request $request): JsonResponse
{
$data = json_decode($request->getContent(), true);
$cart = $this->cartManager->getCart();
$cart->setItems($data['items']);
$this->cartManager->persistCart($cart);
return new JsonResponse(['success' => true]);
}
Frontend Integration
CartSerializer to convert carts to JSON for JavaScript frameworks:
$serializer = new CartSerializer();
$json = $serializer->serialize($cart);
How can I help you explore Laravel packages today?