Installation
Add the bundle to your composer.json:
composer require dywee/product-cms-bundle
Enable it in config/bundles.php:
return [
// ...
Dywee\ProductCmsBundle\DyweeProductCmsBundle::class => ['all' => true],
];
Database Setup
Run migrations (check src/Resources/migrations/ for schema):
php bin/console doctrine:migrations:migrate
First Product Create a product via CLI or admin interface (if available):
php bin/console dywee:product:create --name="Test Product" --price=19.99
Basic Usage in Controller Fetch and display a product:
use Dywee\ProductCmsBundle\Entity\Product;
public function show(Product $product) {
return $this->render('product/show.html.twig', [
'product' => $product,
]);
}
Routing
Ensure routes are imported in config/routes.yaml:
dywee_product_cms:
resource: "@DyweeProductCmsBundle/Resources/config/routing.yml"
Product Management
// Create
$product = new Product();
$product->setName('Laptop');
$product->setPrice(999.99);
$em->persist($product);
$em->flush();
// Fetch
$product = $em->getRepository(Product::class)->findOneBy(['slug' => 'laptop']);
Product Attributes
ProductAttribute entity for custom fields (e.g., weight, dimensions):
$attribute = new ProductAttribute();
$attribute->setName('weight');
$attribute->setValue('2.5kg');
$product->addAttribute($attribute);
Categories & Taxonomy
ProductCategory:
$category = new ProductCategory();
$category->setName('Electronics');
$product->addCategory($category);
Inventory & Stock
ProductStock:
$stock = new ProductStock();
$stock->setQuantity(100);
$product->setStock($stock);
API Integration
# config/api_platform/resources.yaml
resources:
Dywee\ProductCmsBundle\Entity\Product:
collectionOperations:
- GET
itemOperations:
- GET
Symfony Forms Integrate with Symfony Forms for admin panels:
use Dywee\ProductCmsBundle\Form\Type\ProductType;
$form = $this->createForm(ProductType::class, $product);
Event Listeners
Extend functionality with events (e.g., ProductEvents::PRE_SAVE):
// src/EventListener/ProductListener.php
public function onPreSave(ProductEvent $event) {
$product = $event->getProduct();
$product->setSlug(Str::slug($product->getName()));
}
Custom Repositories Override default repositories for complex queries:
// src/Repository/ProductRepository.php
public function findByPriceRange(float $min, float $max): array {
return $this->createQueryBuilder('p')
->where('p.price BETWEEN :min AND :max')
->setParameter('min', $min)
->setParameter('max', $max)
->getQuery()
->getResult();
}
Doctrine Lifecycle Callbacks
Use @ORM\PrePersist in entities for automation:
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Product {
#[ORM\PrePersist]
public function setSlug(): void {
$this->slug = Str::slug($this->name);
}
}
Translation Support Enable translations for product fields (e.g., name, description):
# config/packages/doctrine.yaml
orm:
translations:
Dywee\ProductCmsBundle\Entity\Product:
name: ~
description: ~
Missing Doctrine Migrations
php bin/console doctrine:migrations:migrate post-install.Entity Naming Conflicts
Product).config/packages/doctrine.yaml:
orm:
entity_managers:
default:
mappings:
dywee_product:
alias: DyweeProduct
is_bundle: false
Admin Interface Dependencies
Slug Generation
Performance with Large Catalogs
JOIN FETCH:
$qb = $em->createQueryBuilder()
->select('p, c')
->from(Product::class, 'p')
->leftJoin('p.categories', 'c');
Enable SQL Logging
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Check Event Dispatching
public function onKernelEvent(GetResponseEvent $event) {
$this->container->get('debug.stopwatch')->lap('product_event');
}
Validate Entity States
$errors = $validator->validate($product);
if (count($errors) > 0) {
throw new \RuntimeException((string) $errors);
}
Custom Product Types
Product entity or use inheritance:
class DigitalProduct extends Product {
#[ORM\Column(type: 'string')]
private $licenseKey;
}
Dynamic Attributes
ProductAttributeType entity to support custom attribute types (e.g., dropdown, checkbox).Multi-Store Support
ProductStore entity for store-specific configurations:
class ProductStore {
#[ORM\ManyToOne]
private $store;
#[ORM\ManyToOne(targetEntity: Product::class, inversedBy: 'stores')]
private $product;
}
API Filtering
# config/api_platform/resources.yaml
Dywee\ProductCmsBundle\Entity\Product:
properties:
price: ~
name: ~
filters: ['search', 'range']
Webhooks for Inventory
public function onStockUpdate(ProductEvent $event) {
$this->dispatchWebhook('stock_updated', $event->getProduct());
}
How can I help you explore Laravel packages today?