Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Taxonomy Bundle Laravel Package

sylius/taxonomy-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sylius/taxonomy-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        Sylius\Bundle\TaxonomyBundle\SyliusTaxonomyBundle::class => ['all' => true],
    ];
    
  2. Database Migrations: Run migrations to create taxon, taxon_parent, and taxon_string tables:

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    
  3. First Use Case: Create a taxonomy (e.g., "Product Categories") and taxons (e.g., "Electronics", "Clothing") via:

    php bin/console sylius:taxonomy:create product_categories
    php bin/console sylius:taxonomy:create-taxon product_categories Electronics
    

Where to Look First

  • Doctrine Entities: src/Entity/Taxon.php, src/Entity/TaxonTranslation.php
  • Commands: src/Command/ for CLI management.
  • Fixtures: src/Resources/fixtures/ for sample data.
  • Documentation: Sylius TaxonomyBundle Docs.

Implementation Patterns

Core Workflows

  1. Taxonomy Creation: Define taxonomies (e.g., "Product Categories", "Blog Tags") and associate them with entities (e.g., Product, BlogPost).

    # config/packages/sylius_taxonomy.yaml
    sylius_taxonomy:
        resources:
            product_categories:
                driver: doctrine/orm
                classes:
                    taxon: App\Entity\ProductCategory
                    taxon_translation: App\Entity\ProductCategoryTranslation
    
  2. Taxon Assignment: Use the TaxonAwareInterface trait or embed taxons in entities:

    use Sylius\Component\Taxonomy\Model\TaxonAwareInterface;
    use Sylius\Component\Taxonomy\Model\TaxonAwareTrait;
    
    class Product implements TaxonAwareInterface
    {
        use TaxonAwareTrait;
    }
    

    Assign taxons via repository or form:

    $product->addTaxon($taxonRepository->findOneBy(['slug' => 'electronics']));
    
  3. Hierarchical Management: Build nested taxonomies (e.g., "Electronics > Phones > iPhone"):

    $parentTaxon = $taxonRepository->findOneBy(['slug' => 'electronics']);
    $childTaxon = new Taxon();
    $childTaxon->setParent($parentTaxon);
    $childTaxon->setCode('phones');
    $taxonManager->persist($childTaxon);
    
  4. Translation Handling: Use translations for multilingual taxons:

    $taxonTranslation = new TaxonTranslation();
    $taxonTranslation->setLocale('en_US');
    $taxonTranslation->setName('Phones');
    $taxon->addTranslation($taxonTranslation);
    

Integration Tips

  • APIs: Expose taxonomies via API Platform or REST controllers:
    # config/api/resources.yaml
    resources:
        Sylius\Bundle\TaxonomyBundle\Resources/config/api:
            type: sylius.resource
            collectionOperations:
                get:
                    method: GET
                    path: /api/taxonomies/{id}/taxons
    
  • Forms: Use TaxonType for Symfony forms:
    use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonAutocompleteType;
    
    $builder->add('taxons', TaxonAutocompleteType::class, [
        'taxonomy' => 'product_categories',
        'multiple' => true,
    ]);
    
  • Event Listeners: Hook into taxon.pre_persist or taxon.post_remove events for custom logic:
    use Sylius\Component\Taxonomy\Event\TaxonEvent;
    
    $eventDispatcher->addListener(TaxonEvent::PRE_PERSIST, function (TaxonEvent $event) {
        $taxon = $event->getSubject();
        $taxon->setSlug(Str::slug($taxon->getName()));
    });
    

Gotchas and Tips

Pitfalls

  1. Circular References: Avoid creating circular parent-child relationships (e.g., A → B → A). Validate in pre-persist listeners:

    if ($taxon->getParent() && $taxon->getParent()->hasAncestor($taxon)) {
        throw new \RuntimeException('Circular reference detected!');
    }
    
  2. Slug Uniqueness: Slugs must be unique per taxonomy. Override TaxonSlugger to handle conflicts:

    use Sylius\Component\Taxonomy\Generator\TaxonSluggerInterface;
    
    class CustomTaxonSlugger implements TaxonSluggerInterface
    {
        public function generateSlug(TaxonInterface $taxon): string
        {
            $slug = Str::slug($taxon->getName());
            $originalSlug = $slug;
            $count = 1;
    
            while ($taxon->getTaxonomy()->hasTaxonWithSlug($slug)) {
                $slug = "{$originalSlug}-{$count}";
                $count++;
            }
            return $slug;
        }
    }
    
  3. Performance with Large Taxonomies: Use DISTINCT queries or materialized paths for deep hierarchies. Example with materialized_path:

    // Add to Taxon entity
    #[ORM\Column(type: 'string', length: 255)]
    private string $path = '/';
    
    // Update in TaxonManager
    $taxon->setPath($parent->getPath() . $taxon->getCode() . '/');
    

Debugging

  • Taxon Not Found: Ensure the taxonomy code matches exactly (case-sensitive) when querying:
    $taxon = $taxonRepository->findOneBy(['code' => 'electronics', 'taxonomy' => 'product_categories']);
    
  • Translation Missing: Verify the locale exists in taxon_translation table and is set in TaxonTranslation:
    $taxonTranslation->setLocale('en_US'); // Must match entity's locale
    

Extension Points

  1. Custom Taxon Fields: Extend Taxon entity and update fixtures:

    #[ORM\Entity]
    class CustomTaxon extends Taxon
    {
        #[ORM\Column(type: 'integer', nullable: true)]
        private ?int $priority = null;
    }
    

    Update TaxonRepository to handle custom queries.

  2. Taxonomy Drivers: Implement TaxonomyDriverInterface for non-Doctrine storage (e.g., Elasticsearch):

    class ElasticsearchTaxonomyDriver implements TaxonomyDriverInterface
    {
        public function findTaxon(string $taxonomyCode, string $taxonCode): ?TaxonInterface
        {
            // Custom Elasticsearch logic
        }
    }
    
  3. Validation: Add constraints to Taxon or TaxonTranslation:

    use Symfony\Component\Validator\Constraints as Assert;
    
    #[Assert\Length(min: 2, max: 100)]
    private ?string $name = null;
    
  4. Symfony UX Autocomplete: Integrate with Symfony UX for live search:

    {{ attribute_form_widget(attribute, {
        'attr': {
            'data-controller': 'sylius-taxon-autocomplete',
            'data-sylius-taxon-autocomplete_taxonomy-value': 'product_categories'
        }
    }) }}
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware