sylius/taxonomy
Sylius Taxonomy component for building and managing product taxonomies in PHP. Provides models and utilities for taxons and hierarchical trees, supporting categorization, navigation menus, and structured browsing in Sylius-based eCommerce apps.
Installation:
composer require sylius/taxonomy
Add to config/app.php under providers:
Sylius\Component\Taxonomy\TaxonomyServiceProvider::class,
Publish migrations (if using Doctrine):
php artisan vendor:publish --provider="Sylius\Component\Taxonomy\TaxonomyServiceProvider" --tag="migrations"
php artisan migrate
First Use Case:
Define a taxonomy (e.g., ProductCategory) and a root node:
use Sylius\Component\Taxonomy\Model\TaxonInterface;
use Sylius\Component\Taxonomy\Model\TaxonTranslationInterface;
$taxon = new Taxon();
$taxon->setCode('electronics');
$taxon->setTranslation(new TaxonTranslation(), 'en_US');
$taxon->getTranslation()->setName('Electronics');
$taxonManager->persist($taxon);
$taxonManager->flush();
Where to Look First:
Sylius\Component\Taxonomy\Model\Taxon and TaxonTranslation.TaxonManager (CRUD), TaxonRepository (queries).Gedmo\Sortable (for ordering).Hierarchical Taxonomy Management:
// Create a child taxon under "electronics"
$laptopTaxon = new Taxon();
$laptopTaxon->setCode('laptops');
$laptopTaxon->setParent($electronicsTaxon); // Link to parent
$laptopTaxon->setTranslation(new TaxonTranslation(), 'en_US');
$laptopTaxon->getTranslation()->setName('Laptops');
$taxonManager->persist($laptopTaxon);
Bulk Operations:
Use TaxonRepository for batch queries:
$children = $taxonRepository->findChildren($parentTaxon);
$allDescendants = $taxonRepository->findDescendants($parentTaxon);
Translation Handling:
Dynamically load translations via TaxonTranslation:
$taxon->addTranslation(new TaxonTranslation(), 'fr_FR');
$taxon->getTranslation('fr_FR')->setName('Électronique');
Integration with Eloquent:
If using Eloquent, extend the Taxon model:
class Taxon extends \Sylius\Component\Taxonomy\Model\Taxon implements \Illuminate\Database\Eloquent\Model
{
use \Sylius\Component\Taxonomy\Model\TaxonTrait;
use \Illuminate\Database\Eloquent\Model;
}
$product->taxons()->attach($electronicsTaxon);
$path = $taxonRepository->getPath($taxon);
// Returns: ['electronics' => 'Electronics', 'laptops' => 'Laptops']
$products = Product::whereHas('taxons', function ($query) use ($taxon) {
$query->where('taxons.code', $taxon->getCode());
})->get();
Circular References:
Avoid creating loops in the hierarchy (e.g., A → B → A). The package doesn’t enforce this; validate manually:
if ($taxonRepository->isDescendant($taxon, $parentTaxon)) {
throw new \RuntimeException('Circular reference detected!');
}
Translation Locale Mismatches: Always set the locale when adding translations:
// ❌ Bad: Missing locale
$taxon->addTranslation(new TaxonTranslation());
// ✅ Good
$taxon->addTranslation(new TaxonTranslation(), 'en_US');
Performance with Deep Hierarchies:
Fetching all descendants of a deep taxon can be slow. Use DISTINCT in queries or limit depth:
$taxonRepository->findDescendants($taxon, 2); // Max depth = 2
Doctrine vs. Eloquent:
Sylius\Component\Taxonomy\Repository\Doctrine\TaxonRepository.findChildren/findDescendants.TaxonManager is bound in the container and migrations are run.
php artisan db:show
TaxonTranslation:
$taxon->getTranslation('en_US')->getName(); // Returns null if missing
Custom Taxon Fields:
Extend Taxon to add attributes (e.g., icon, slug):
class ExtendedTaxon extends Taxon
{
protected $icon;
protected $slug;
// Add getters/setters and update migrations.
}
Event Listeners:
Hook into taxon events (e.g., prePersist, postRemove) via Symfony events:
$dispatcher->addListener(TaxonEvents::PRE_PERSIST, function (TaxonEvent $event) {
$taxon = $event->getSubject();
// Validate or modify $taxon here.
});
Custom Repository Methods:
Add query methods to TaxonRepository:
public function findByPath(array $path)
{
return $this->createQueryBuilder('t')
->where('t.code = :code')
->setParameter('code', end($path))
->andWhere('t.parent IN (
SELECT parent FROM SyliusTaxonomyTaxon t2
WHERE t2.code IN (:codes)
)')
->setParameter('codes', $path)
->getQuery()
->getOneOrNullResult();
}
Soft Deletes:
Enable soft deletes by adding use SoftDeletableTrait to Taxon and updating the entity:
class Taxon extends \Sylius\Component\Taxonomy\Model\Taxon
{
use \Sylius\Component\Taxonomy\Model\TaxonTrait;
use \Doctrine\ORM\Mapping as ORM;
use \Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
// Add @ORM\SoftDeleteable field.
}
config/packages/sylius_taxonomy.yaml:
sylius_taxonomy:
default_locale: en_US
Gedmo\Sortable for manual ordering:
# config/packages/gedmo_sortable.yaml
gedmo_sortable:
sortable: true
Then update the Taxon entity:
use Gedmo\Sortable\Mapping\Annotation as Gedmo;
/**
* @Gedmo\Sortable
*/
protected $position;
How can I help you explore Laravel packages today?