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

Sulu Category Extra Bundle Laravel Package

alengo/sulu-category-extra-bundle

Adds an “Additional Data” tab to Sulu CMS categories. Configure fields via a standard Sulu form XML file and store values as a JSON column on the existing ca_categories table (no extra tables). Tab title, form key, and resource key are configurable.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Install the Bundle

    composer require alengo/sulu-category-extra-bundle
    

    Add to config/bundles.php:

    Alengo\SuluCategoryExtraBundle\AlengoSuluCategoryExtraBundle::class => ['all' => true],
    
  2. Register Routes Add to config/routes/sulu_admin.yaml:

    CategoryExtraBundle:
        resource: "@AlengoSuluCategoryExtraBundle/Resources/config/routing_admin_api.yaml"
        prefix: /admin/api
    
  3. Define the Form Create config/forms/category_additional_data.xml with a basic field (e.g., text_line):

    <form xmlns="...">
        <key>category_additional_data</key>
        <properties>
            <property name="custom_field" type="text_line" colspan="12">
                <meta>
                    <title lang="en">Custom Field</title>
                </meta>
            </property>
        </properties>
    </form>
    
  4. Run Migration

    php bin/console doctrine:schema:update --force
    
  5. Access the Tab Navigate to Sulu Admin → Categories → Edit Category and verify the "Additional Data" tab appears.


First Use Case: Adding a Simple Custom Field

  • Edit a category in Sulu Admin.
  • Fill out the new "Additional Data" tab (e.g., custom_field).
  • Save the category.
  • Verify the data persists by reloading the category or checking the database (ca_categories.additionalData).

Implementation Patterns

Workflows

  1. Form Configuration

    • Use standard Sulu form XML syntax (e.g., single_select, media_selection, text_editor).
    • Example: Adding a color picker (via single_select with predefined values) or a rich text field (text_editor).
    • Best Practice: Group related fields logically (e.g., SEO settings, metadata) to avoid clutter.
  2. Entity Access in Twig

    • Always check if the category is an instance of Alengo\SuluCategoryExtraBundle\Entity\Category before accessing additionalData:
      {% if category instanceof Alengo\SuluCategoryExtraBundle\Entity\Category %}
          {{ dump(category.additionalData.custom_field) }}
      {% endif %}
      
  3. API Integration

    • Use the /admin/api/category-additional-data/{id} endpoints for custom backend logic (e.g., syncing with external services).
    • Example: Fetch additional data in a controller:
      $client = \Symfony\Panther\Client::createChromeClient();
      $response = $client->request('GET', '/admin/api/category-additional-data/123');
      $data = json_decode($response->getContent(), true);
      
  4. Dynamic Forms

    • Conditionally render fields in Twig based on additionalData:
      {% if category.additionalData.theme == 'blue' %}
          <style>body { background: lightblue; }</style>
      {% endif %}
      

Integration Tips

  • Sulu Events: Listen to sulu.category.post_persist or sulu.category.post_update to trigger actions when additionalData changes:

    // src/EventListener/CategoryExtraListener.php
    public function onCategoryUpdate(CategoryEvent $event): void {
        $category = $event->getCategory();
        if ($category->hasAdditionalData() && $category->getAdditionalData()['custom_field'] === 'trigger') {
            // Execute logic (e.g., send email, update related content).
        }
    }
    
  • Validation: Add custom validation to the form XML using validation tags:

    <property name="email" type="text_line" colspan="12">
        <meta>
            <title lang="en">Email</title>
        </meta>
        <validation>
            <constraint name="NotBlank" />
            <constraint name="Email" />
        </validation>
    </property>
    
  • Localization: Translate field labels and placeholders in the form XML:

    <meta>
        <title lang="en">Custom Field</title>
        <title lang="de">Benutzerdefiniertes Feld</title>
        <placeholder lang="en">Enter value</placeholder>
    </meta>
    

Gotchas and Tips

Pitfalls

  1. Database Schema

    • The migration must be run after installation; otherwise, the additionalData column won’t exist.
    • Fix: If you forget, manually add the column:
      ALTER TABLE ca_categories ADD additionalData JSON;
      
  2. Entity Type Mismatch

    • If you don’t extend the Category entity (default behavior), additionalData won’t be available via getAdditionalData().
    • Fix: Ensure your Category entity extends Alengo\SuluCategoryExtraBundle\Entity\Category:
      use Alengo\SuluCategoryExtraBundle\Entity\Category as BaseCategory;
      
      class Category extends BaseCategory { ... }
      
  3. Form Key Mismatch

    • The form_key in config/packages/alengo_sulu_category_extra.yaml must match the <key> in your form XML.
    • Fix: Double-check the key in both files after installation.
  4. Caching Issues

    • Sulu’s admin API may cache responses. Clear the cache after changes:
      php bin/console sulu:cache:clear
      
  5. JSON Data Corruption

    • Invalid JSON in additionalData (e.g., unclosed braces) will break the admin UI.
    • Fix: Validate JSON manually or use a library like json_encode()/json_decode() when updating data programmatically.

Debugging

  • Check API Responses Use Postman or cURL to test the /admin/api/category-additional-data/{id} endpoints:

    curl -X GET http://your-sulu-admin/admin/api/category-additional-data/1 \
         -H "Authorization: Bearer YOUR_TOKEN"
    
  • Log Additional Data Add a debug listener to log additionalData changes:

    public function onCategoryUpdate(CategoryEvent $event): void {
        $this->logger->info('Additional Data:', [
            'id' => $event->getCategory()->getId(),
            'data' => $event->getCategory()->getAdditionalData(),
        ]);
    }
    
  • Verify Form XML Use Sulu’s form validator to check for syntax errors:

    php bin/console sulu:form:validate config/forms/category_additional_data.xml
    

Extension Points

  1. Custom Entity Class Extend the default Category entity to add methods or logic:

    class CustomCategory extends Alengo\SuluCategoryExtraBundle\Entity\Category {
        public function isFeatured(): bool {
            return $this->getAdditionalData()['featured'] ?? false;
        }
    }
    

    Update config/packages/alengo_sulu_category_extra.yaml:

    alengo_sulu_category_extra:
        entity_class: App\Entity\CustomCategory
    
  2. Dynamic Form Loading Override the form key dynamically based on category type (e.g., blog vs. product categories):

    // In a pre-persist listener
    $category->setAdditionalDataFormKey('blog_category_data');
    
  3. Third-Party Integrations Use the PUT API endpoint to sync data with external services (e.g., Google Analytics, CRM):

    $client->request('PUT', '/admin/api/category-additional-data/123', [
        'json' => [
            'id' => 123,
            'custom_field' => 'updated_value',
            'external_id' => '1001',
        ],
    ]);
    
  4. Migration Hooks Seed default additionalData during migrations:

    // src/Migrations/Version20230101000000.php
    public function up(Schema $schema): void {
        $this->addSql('UPDATE ca_categories SET additionalData = \'{"theme": "default"}\' WHERE id = 1');
    }
    
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.
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime
canaltp/sam-ecore-application-manager-bundle
canaltp/sam-ecore-security-manager-bundle