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

Classification Bundle Laravel Package

sonata-project/classification-bundle

Symfony bundle providing a classification system for Sonata: categories, tags and collections management with admin integration, persistence support and documentation. Part of the Sonata Project ecosystem.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require sonata-project/classification-bundle
    

    Ensure SonataClassificationBundle is enabled in config/bundles.php:

    SonataClassificationBundle\SonataClassificationBundle::class => ['all' => true],
    
  2. Database Migrations Run the bundle's migrations to create the required tables:

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    
  3. First Use Case: Admin Panel The bundle provides built-in admin interfaces for managing:

    • Categories (hierarchical)
    • Tags (flat)
    • Contexts (scopes for classifications)
    • Collections (grouped tags)

    Enable the admin in config/packages/sonata_admin.yaml:

    sonata_admin:
        options:
            html5_validation: true
        security:
            handler: sonata.admin.security.handler.acl
        assets:
            less_filters: ['less', 'cssrewrite']
        templates:
            layout: 'SonataClassificationBundle::standard_layout.html.twig'
    

    Register the admin services in config/services.yaml:

    SonataClassificationBundle\:
        resource: '../vendor/sonata-project/classification-bundle/Resources/config/services.xml'
        tags: ['controller.service_arguments']
    
  4. Access the Admin Panel Visit /admin/classification to manage classifications via SonataAdmin.


Implementation Patterns

Core Workflows

1. Hierarchical Categories

  • Create a Root Category:
    $categoryManager = $this->container->get('sonata.classification.category_manager');
    $rootCategory = $categoryManager->createRootCategory('Root Name', 'slug-root');
    $categoryManager->save($rootCategory);
    
  • Add Subcategories:
    $subCategory = $categoryManager->createChildCategory($rootCategory, 'Sub Name', 'slug-sub');
    $categoryManager->save($subCategory);
    
  • Fetch Categories with Tree Structure:
    $categories = $categoryManager->getRootCategories();
    foreach ($categories as $category) {
        $subCategories = $categoryManager->getSubCategories($category);
        // ...
    }
    

2. Tag Management

  • Assign Tags to an Entity:
    $tagManager = $this->container->get('sonata.classification.tag_manager');
    $tag = $tagManager->findOneBy(['name' => 'Featured']);
    if (!$tag) {
        $tag = $tagManager->create('Featured');
        $tagManager->save($tag);
    }
    $entity->setTags([$tag]); // Assuming your entity has a `tags` relation.
    

3. Context-Based Filtering

  • Create a Context:
    $contextManager = $this->container->get('sonata.classification.context_manager');
    $context = $contextManager->create('Products', 'products');
    $contextManager->save($context);
    
  • Assign Categories/Tags to a Context:
    $categoryManager->setContext($rootCategory, $context);
    $tagManager->setContext($tag, $context);
    

4. Collections (Grouped Tags)

  • Create a Collection:
    $collectionManager = $this->container->get('sonata.classification.collection_manager');
    $collection = $collectionManager->create('Promotions', 'promotions');
    $collectionManager->save($collection);
    
  • Add Tags to a Collection:
    $collectionManager->addTagToCollection($tag, $collection);
    

Integration with SonataAdmin

  1. Extend Admin Classes (if needed):

    use Sonata\ClassificationBundle\Admin\CategoryAdmin as BaseCategoryAdmin;
    
    class CustomCategoryAdmin extends BaseCategoryAdmin
    {
        protected function configureFormFields(FormMapper $formMapper)
        {
            $formMapper
                ->add('customField', 'text')
                ->add('parent', 'sonata_type_model', [
                    'by_reference' => false,
                ]);
        }
    }
    

    Register the custom admin in config/services.yaml:

    services:
        App\Admin\CustomCategoryAdmin:
            arguments: ['@sonata.admin.orm_admin', '@doctrine.orm.entity_manager', '@sonata.classification.category_manager']
            tags: ['sonata.admin', 'sonata.admin.category']
    
  2. Use Classifications in Your Entities:

    use Sonata\ClassificationBundle\Model\CategoryInterface;
    use Sonata\ClassificationBundle\Model\TagInterface;
    
    class Product
    {
        /**
         * @ORM\ManyToMany(targetEntity="Sonata\ClassificationBundle\Model\Category")
         */
        private $categories;
    
        /**
         * @ORM\ManyToMany(targetEntity="Sonata\ClassificationBundle\Model\Tag")
         */
        private $tags;
    }
    
  3. Filtering in SonataAdmin:

    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper
            ->add('categories', 'sonata_type_model_list', [
                'model_manager' => $this->modelManager,
                'property' => 'categories',
                'btn_add' => false,
            ]);
    }
    

API and Services

  • Category Manager:
    $categoryManager = $this->container->get('sonata.classification.category_manager');
    $categories = $categoryManager->getRootCategories(); // Returns a paginated list.
    
  • Tag Manager:
    $tagManager = $this->container->get('sonata.classification.tag_manager');
    $tags = $tagManager->findBy(['context' => $context]);
    
  • Context Manager:
    $contextManager = $this->container->get('sonata.classification.context_manager');
    $contexts = $contextManager->findAll();
    

Gotchas and Tips

Pitfalls

  1. Lazy Loading in Categories:

    • By default, child categories are lazy-loaded. To eager-load them:
      $category->getChildren()->load(); // For Doctrine ORM.
      
    • Avoid disableChildrenLazyLoading() (deprecated in v3.18.0+).
  2. Context Assignment:

    • Categories/Tags must be assigned to a context before use. Unassigned classifications won’t appear in filtered lists.
    • Use setContext() on the manager:
      $categoryManager->setContext($category, $context);
      
  3. Slug Generation:

    • Slugs are auto-generated from names but can be manually overridden. Ensure uniqueness to avoid conflicts.
  4. Symfony 6+ Deprecations:

    • Avoid using deprecated methods like renderWithExtraParams (replaced by Twig’s native methods).
    • Use Symfony\Component\HttpKernel\DependencyInjection\Extension alternatives if extending the bundle.
  5. Doctrine Cascade Merges:

    • If using doctrine/orm < 2.7, cascade merge may fail. Upgrade or handle manually:
      $em->merge($category); // Explicit merge if cascade fails.
      

Debugging Tips

  1. Missing Admin Buttons:

    • Clear cache and check sonata_admin configuration. Ensure the admin is properly tagged:
      tags: ['sonata.admin', 'sonata.admin.category']
      
  2. Performance with Large Trees:

    • Use getSubCategoriesPager() for paginated results:
      $pager = $categoryManager->getSubCategoriesPager($parentCategory, 1, 10);
      
  3. Translation Issues:

    • Ensure translations are loaded in your Twig templates:
      {% trans from 'SonataClassificationBundle' %}
      
    • Add missing translations to Resources/translations/messages.{locale}.yml.
  4. Schema Validation Errors:

    • Run php bin/console doctrine:schema:validate to check for mapping issues.
    • For MongoDB ODM, ensure xml validation is disabled if using newer Doctrine versions.

Extension Points

  1. Custom Entities:

    • Extend Sonata\ClassificationBundle\Model\Category or Tag to add fields:
      use Sonata\ClassificationBundle\Model\BaseCategory as BaseCategory;
      
      class CustomCategory extends BaseCategory
      {
          /**
           * @ORM\Column(type="string", nullable=true)
           */
          private $customField;
      }
      
    • Update the CategoryAdmin to include the new field.
  2. Custom Managers:

    • Override managers (e.g., CategoryManager) by extending and injecting dependencies:
      class CustomCategoryManager extends CategoryManager
      {
          public function getCustomCategories()
          {
              // Custom logic.
          }
      }
      
    • Register the service with the correct alias:
      services:
          sonata.classification.category_manager:
      
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity