awaresoft/sonata-classification-bundle
## Getting Started
### Minimal Setup
1. **Installation via Composer** (if not symlinked):
```bash
composer require awaresoft/sonata-classification-bundle
Note: Follow the README’s symlink instructions if modifying locally.
Enable the Bundle in config/bundles.php:
return [
// ...
Awaresoft\SonataClassificationBundle\SonataClassificationBundle::class => ['all' => true],
];
Database Setup:
classification, classification_category).php bin/console make:migration
php bin/console doctrine:migrations:migrate
First Use Case:
Awaresoft\SonataClassificationBundle\Entity\Classification or use traits like ClassifiableInterface.
// src/Entity/Product.php
use Awaresoft\SonataClassificationBundle\Entity\ClassificationTrait;
class Product
{
use ClassificationTrait;
// ...
}
# config/sonata_classification.yml
sonata_classification:
categories:
- { name: 'Product Type', slug: 'product_type' }
- { name: 'Color', slug: 'color' }
classifications:
- { category: 'product_type', name: 'Electronics', slug: 'electronics' }
- { category: 'color', name: 'Red', slug: 'red' }
Assign Classifications to Entities:
Use the ClassifiableInterface methods:
$product = new Product();
$product->addClassification($classificationEntity);
$entityManager->persist($product);
Awaresoft\SonataClassificationBundle\Model\ClassificationInterface for parent-child relationships.
$subCategory = new Classification();
$subCategory->setParent($parentCategory);
$subCategory->setName('Subcategory');
# config/packages/sonata_admin.yml
sonata_admin:
options:
models:
Awaresoft\SonataClassificationBundle\Entity\Classification: ~
ClassificationTrait in multiple entities to avoid duplication:
class Book implements ClassifiableInterface
{
use ClassificationTrait;
// ...
}
$classifiedProducts = $entityManager->getRepository(Product::class)
->findBy(['classifications' => $classification]);
$builder->add('classifications', EntityType::class, [
'class' => Classification::class,
'multiple' => true,
'expanded' => true,
]);
use Awaresoft\SonataClassificationBundle\Validator\Constraints\ValidClassification;
/**
* @ValidClassification(groups={"classification"})
*/
class Product { ... }
#[Groups(['api'])]
#[SerializedName('classifications')]
public function getClassifications(): array
{
return $this->classifications->map(fn($c) => $c->getSlug());
}
type Product {
classifications: [Classification!]!
}
$cache = $container->get('cache.app');
$key = 'classification_tree_' . $category->getSlug();
$tree = $cache->get($key, function() use ($category) {
return $category->getChildren(); // Custom method
});
Classification entities are mapped correctly in orm.xml or annotations.{% for classification in product.classifications %}
{{ classification.getName() }}
{% endfor %}
// src/EventListener/ClassificationListener.php
public function onClassificationUpdate(ClassificationEvent $event)
{
$classification = $event->getClassification();
// Log or trigger actions
}
$em = $this->getEntityManager();
$em->getConnection()->beginTransaction();
foreach ($products as $product) {
$product->addClassification($classification);
$em->persist($product);
if ($i % 20 === 0) {
$em->flush();
$em->clear();
}
}
$em->getConnection()->commit();
public function testClassificationAssignment()
{
$client = static::createClient();
$client->request('POST', '/api/products', [
'json' => [
'classifications' => ['electronics', 'red']
]
]);
$this->assertResponseIsSuccessful();
}
ClassificationTrait methods:
$product = $this->createMock(Product::class);
$product->method('getClassifications')->willReturn([$mockClassification]);
Backward Compatibility:
Symlink Issues:
autoload_psr4.php after symlinking can cause autoloading errors.composer dump-autoload after manual symlink changes.Circular References:
Missing Doctrine Mappings:
Classification entities aren’t properly mapped, queries will fail silently.orm.xml or annotations for Classification and related entities.Concurrent Modifications:
Query Logs: Enable Doctrine debug mode to inspect classification queries:
# config/packages/dev/doctrine.yaml
doctrine:
dbal:
logging: true
profiling: true
Event Listeners: Add debug listeners to trace classification changes:
public function onClassificationPrePersist(ClassificationEvent $event)
{
$this->logger->debug('Classification saved', ['classification' => $event->getClassification()->getSlug()]);
}
Common Errors:
/src/Awaresoft.ValidClassification constraints and entity mappings.Custom Classification Logic:
Awaresoft\SonataClassificationBundle\Entity\Classification:
class CustomClassification extends Classification
{
private $customField;
// Add getters/setters and business logic
}
New Classification Types:
ClassificationType (if available) or create a custom form type:
class CustomClassificationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('custom_field', TextType::class);
}
}
API Extensions:
#[Groups(['api', 'export'])]
public function getClassificationTree(): array
{
return $this->getChildren()->map(fn($c) => $c->getSlug());
}
**Admin
How can I help you explore Laravel packages today?