Installation
composer require sylius/product
Add the bundle to config/bundles.php (Symfony) or config/app.php (Laravel via bridge):
return [
// ...
Sylius\Product\SyliusProductBundle::class => ['all' => true],
];
Database Migrations Run migrations to create product-related tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Use Case: Creating a Product
use Sylius\Component\Product\Model\ProductInterface;
use Sylius\Component\Product\Model\ProductTranslationInterface;
$product = new Product();
$product->setEnabled(true);
$product->setCode('PROD-001');
$translation = new ProductTranslation();
$translation->setName('Test Product');
$translation->setSlug('test-product');
$translation->setLocale('en_US');
$product->addTranslation($translation);
$productRepository->save($product);
Sylius\Component\Product\Model\Product – Core product entity.Sylius\Component\Product\Model\ProductTranslation – Localized product data.Sylius\Component\Product\Repository\ProductRepositoryInterface – Product CRUD operations.Sylius\Component\Product\Factory\ProductFactoryInterface – Product creation helpers.Product Creation Workflow
// Using factory for cleaner code
$productFactory = $container->get('sylius.factory.product');
$product = $productFactory->createNew();
$product->setCode('PROD-002');
// Add translations
$translation = $productFactory->createTranslation();
$translation->setName('Premium Product');
$product->addTranslation($translation);
$productRepository->save($product);
Bulk Product Updates
$products = $productRepository->findBy(['enabled' => true]);
foreach ($products as $product) {
$product->setEnabled(false); // Soft disable
$productRepository->save($product);
}
Localized Data Handling
$product = $productRepository->findOneBy(['code' => 'PROD-001']);
$translation = $product->getTranslation('en_US');
$translation->setDescription('Updated description for English');
$productRepository->save($product);
Event-Driven Extensions
Listen to Sylius\Component\Product\Event\ProductCreatedEvent for post-save logic:
$dispatcher->addListener(
'sylius.product.created',
function (ProductCreatedEvent $event) {
// Send notification, log, etc.
}
);
API Layer (Laravel) Use Laravel’s API resources to expose products:
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ProductResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->getId(),
'code' => $this->getCode(),
'name' => $this->getName(),
];
}
}
Search Functionality Integrate with Elasticsearch or Algolia via custom repositories:
$searchResults = $searchRepository->search('laptop', 'en_US');
Translation Locale Mismatch
'en_US'). Missing locales cause NullPointerException.if (!$translation->getLocale() || !in_array($translation->getLocale(), ['en_US', 'fr_FR'])) {
throw new \InvalidArgumentException('Invalid locale');
}
Code Uniqueness
UniqueConstraintViolationException.findOneBy(['code' => $code]) to check existence before saving.Lazy-Loaded Translations
getTranslation() without a locale throws UnexpectedValueException.$product->setCurrentLocale('en_US'); // Set default locale
Enable Doctrine Debugging
Add to .env:
APP_DEBUG=true
SYLUS_DEBUG=true
Check logs for SQL queries and entity state:
php bin/console doctrine:query:sql "SELECT * FROM product WHERE code = 'PROD-001'"
Common SQL Queries
-- Find disabled products
SELECT * FROM product WHERE enabled = false;
-- Count products by locale
SELECT COUNT(*) FROM product_translation WHERE locale = 'en_US';
Custom Product Fields
Extend the Product entity via traits or inheritance:
namespace App\Entity;
use Sylius\Component\Product\Model\Product as BaseProduct;
class Product extends BaseProduct
{
private ?string $customField = null;
public function getCustomField(): ?string
{
return $this->customField;
}
public function setCustomField(?string $customField): void
{
$this->customField = $customField;
}
}
Override Factories
Replace default factories in config/packages/sylius_product.yaml:
sylius_product:
resources:
product:
factory: 'app.factory.product' # Your custom factory
Add Validation Use Symfony’s validator or custom constraints:
use Symfony\Component\Validator\Constraints as Assert;
$product->setCode('PROD-003');
$validator = $validator->validate($product);
if (count($validator) > 0) {
throw new \RuntimeException('Validation failed');
}
How can I help you explore Laravel packages today?