chauhan-mukesh/extended-block-bundle

Pimcore bundle that extends block data type with separate table storage for better performance and queryability

Installs: 20

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 1

Type:pimcore-bundle

pkg:composer/chauhan-mukesh/extended-block-bundle

dev-main / 1.0.x-dev 2026-02-19 11:47 UTC

README

Latest Version License PHP Version Pimcore Version

A Pimcore bundle that extends the block data type by storing data in separate database tables instead of serialized JSON in a single column. This provides better performance, queryability, and proper relational data modeling while maintaining the same UI/UX experience as Pimcore's native block field.

๐Ÿ“‹ Table of Contents

โœจ Features

  • Separate Table Storage: Each extended block stores data in dedicated database tables, similar to field collections
  • SQL Queryable: Unlike standard blocks that use serialized JSON, extended block data can be queried using SQL
  • Better Performance: Eliminates serialization overhead and enables efficient database queries
  • Pimcore-style UI/UX: Follows Pimcore's native block UI patterns with inline controls (add before/after, delete, move up/down)
  • Responsive Design: Fully responsive interface with auto-adjusting height/width, transitions, and animations
  • Multiple Block Types: Define multiple block types with different field configurations
  • Nesting Prevention: Automatic validation prevents invalid block nesting configurations
  • Safe Schema Updates: New fields can be added without data loss; removed fields preserve existing data
  • Lazy Loading: Optional lazy loading for improved performance with large datasets
  • Dark Mode Support: CSS supports dark mode when the browser prefers dark color scheme

๐Ÿ“ฆ Requirements

  • PHP 8.0 or higher
  • Pimcore 10.0 or higher (supports Pimcore 10.x and 11.x)
  • Symfony 5.4 or higher (5.x for Pimcore 10, 6.x for Pimcore 11)

๐Ÿš€ Installation

Step 1: Install via Composer

Option A: Install from Packagist (if published)

composer require chauhan-mukesh/extended-block-bundle

Option B: Install from GitHub repository

If the package is not yet available on Packagist, or you want to install directly from GitHub, add the repository to your composer.json:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Chauhan-Mukesh/extended-block"
        }
    ]
}

Then run:

composer require chauhan-mukesh/extended-block-bundle:dev-main

Note: When installing from GitHub, you may need to set "minimum-stability": "dev" in your composer.json or use @dev version constraint if no stable releases are tagged.

Step 2: Enable the Bundle

Add the bundle to your config/bundles.php:

return [
    // ... other bundles
    ExtendedBlockBundle\ExtendedBlockBundle::class => ['all' => true],
];

Step 3: Install the Bundle

Run the installer to set up required database tables:

bin/console pimcore:bundle:install ExtendedBlockBundle

Step 4: Publish Assets

bin/console assets:install public --symlink

โš™๏ธ Configuration

Configure the bundle in config/packages/extended_block.yaml:

extended_block:
    # Prefix for database tables (default: 'object_eb_')
    table_prefix: 'object_eb_'
    
    # Enable strict validation mode (default: true)
    strict_mode: true
    
    # Maximum items per block (null for unlimited)
    max_items: null
    
    # Enable query logging for debugging (default: false)
    debug_queries: false

๐Ÿ“– Usage

Adding ExtendedBlock to a Class Definition

  1. Open the Pimcore Admin panel
  2. Navigate to Settings > Data Objects > Classes
  3. Select or create a class
  4. Add a new field by right-clicking in the tree and selecting Extended Block from the Structured data types section
  5. Configure the field settings (name, title, min/max items, etc.)
  6. Add sub-fields by right-clicking on the ExtendedBlock field and selecting the desired field type

Adding Sub-fields

ExtendedBlock follows Pimcore's standard Block pattern for adding sub-fields:

  1. Right-click on the ExtendedBlock field in the class definition tree
  2. Select "Add data component" from the context menu
  3. Choose a field type from the submenu (grouped by category: text, numeric, date, etc.)
  4. Configure the field settings in the right panel

Note: The context menu will show "Add data component" with grouped field types. Not all field types are available - complex nested types like LocalizedFields, Block, FieldCollections, ObjectBricks, and ExtendedBlock cannot be added inside ExtendedBlock.

Example structure:

MyExtendedBlock (ExtendedBlock)
โ”œโ”€โ”€ title (Input)
โ”œโ”€โ”€ content (WYSIWYG)
โ”œโ”€โ”€ description (Textarea)
โ””โ”€โ”€ image (Image)

Supported Field Types

The following field types can be added as sub-fields:

Text & Content:

  • Input, Textarea, WYSIWYG, Email

Numeric & Selection:

  • Numeric, Checkbox, Slider, BooleanSelect
  • Select, Multiselect
  • Country, Country Multiselect
  • Language, Language Multiselect, Gender

Date & Time:

  • Date, DateTime

Relations (simple reference storage):

  • ManyToOneRelation
  • ManyToManyRelation
  • ManyToManyObjectRelation

Assets:

  • Image, Link

Note: Relation fields store element references (ID + type) in the ExtendedBlock table. Advanced relation types with metadata (AdvancedManyToManyRelation, AdvancedManyToManyObjectRelation) and ReverseObjectRelation are not supported.

Defining Block Types

In the class editor, you can define multiple block types, each with its own set of fields:

Block Type: text_block
โ”œโ”€โ”€ title (Input)
โ”œโ”€โ”€ content (WYSIWYG)
โ””โ”€โ”€ description (Textarea)

Block Type: image_block
โ”œโ”€โ”€ image (Image)
โ”œโ”€โ”€ caption (Input)
โ””โ”€โ”€ link (Link)

Working with Extended Block Data

<?php

use ExtendedBlockBundle\Model\DataObject\Data\ExtendedBlockContainer;
use ExtendedBlockBundle\Model\DataObject\Data\ExtendedBlockItem;

// Get extended block data from an object
$container = $object->getMyExtendedBlock();

// Check if container has items
if (!$container->isEmpty()) {
    
    // Iterate over items
    foreach ($container as $item) {
        echo $item->getType();           // e.g., 'text_block'
        echo $item->getFieldValue('title');
    }
    
    // Get first/last item
    $first = $container->first();
    $last = $container->last();
    
    // Get items by type
    $textBlocks = $container->getItemsByType('text_block');
    
    // Count items
    echo count($container);
}

// Create a new item
$newItem = new ExtendedBlockItem('text_block', 0);
$newItem->setFieldValue('title', 'My Title');
$newItem->setFieldValue('content', 'My Content');

// Add item to container
$container->addItem($newItem);

// Remove item at index
$container->removeItem(0);

// Move item
$container->moveItem(0, 2);

// Clear all items
$container->clear();

// Save the object
$object->save();

Using Magic Methods

ExtendedBlockItem supports magic getters and setters:

// Magic setter
$item->title = 'My Title';
$item->content = '<p>Some content</p>';

// Magic getter
echo $item->title;
echo $item->content;

// Magic isset
if (isset($item->title)) {
    // ...
}

// Magic unset
unset($item->title);  // Equivalent to $item->removeFieldValue('title')

๐Ÿ”ง PHP API

The Extended Block bundle provides a PHP API that works similarly to Pimcore's standard Block data type. For comprehensive documentation, see doc/PHP_API.md.

Quick Start

<?php

use ExtendedBlockBundle\Model\DataObject\Data\ExtendedBlockContainer;
use ExtendedBlockBundle\Model\DataObject\Data\ExtendedBlockItem;
use Pimcore\Model\DataObject\Product;

// Get an object with an extended block field
$product = Product::getById(123);

// Access the extended block container
$container = $product->getContentBlocks();

// Create and add a new block item
$item = new ExtendedBlockItem('text_block', 0);
$item->setFieldValue('title', 'Product Features');
$item->setFieldValue('content', '<p>Amazing features...</p>');

$container->addItem($item);
$product->save();

Key Classes

Class Namespace Description
ExtendedBlockContainer ExtendedBlockBundle\Model\DataObject\Data Container for block items with iteration and array access support
ExtendedBlockItem ExtendedBlockBundle\Model\DataObject\Data Individual block item with field values

Common Operations

Reading Block Data

$container = $product->getContentBlocks();

// Iterate through items
foreach ($container as $item) {
    echo $item->getType();                    // Block type
    echo $item->getFieldValue('title');       // Field value
}

// Access specific items
$first = $container->first();
$last = $container->last();
$byIndex = $container->getItem(2);

// Filter by type
$textBlocks = $container->getItemsByType('text_block');

Creating and Modifying Blocks

// Create new item
$item = new ExtendedBlockItem('image_block', 0);
$item->setFieldValue('image', $assetId);
$item->setFieldValue('caption', 'Product Image');

// Using magic methods
$item->title = 'My Title';
echo $item->title;

// Add to container
$container->addItem($item);

// Modify existing item
$firstItem = $container->first();
$firstItem->setFieldValue('title', 'Updated Title');

// Remove and reorder
$container->removeItem(0);
$container->moveItem(0, 2);

Direct Database Queries

Since data is stored in separate tables, you can query directly:

use Pimcore\Db;

$db = Db::get();
$classId = Product::classId();
// Note: Table prefix is configurable via extended_block.table_prefix (default: 'object_eb_')
$tableName = 'object_eb_' . $classId . '_contentBlocks';

// Find objects with specific content
$objectIds = $db->fetchFirstColumn(
    "SELECT DISTINCT o_id FROM `{$tableName}` WHERE title LIKE ?",
    ['%promotion%']
);

For more detailed examples including CRUD operations, per-item localization, working with multiple block types, and best practices, see the PHP API Documentation.

๐Ÿ—๏ธ Architecture

Class Diagram

ExtendedBlockBundle
โ”œโ”€โ”€ ExtendedBlockBundle.php              # Main bundle class
โ”œโ”€โ”€ DependencyInjection/
โ”‚   โ”œโ”€โ”€ ExtendedBlockExtension.php       # DI extension
โ”‚   โ””โ”€โ”€ Configuration.php                # Bundle configuration
โ”œโ”€โ”€ Model/
โ”‚   โ””โ”€โ”€ DataObject/
โ”‚       โ”œโ”€โ”€ ClassDefinition/
โ”‚       โ”‚   โ””โ”€โ”€ Data/
โ”‚       โ”‚       โ””โ”€โ”€ ExtendedBlock.php    # Data type definition
โ”‚       โ””โ”€โ”€ Data/
โ”‚           โ”œโ”€โ”€ ExtendedBlockContainer.php  # Container class
โ”‚           โ””โ”€โ”€ ExtendedBlockItem.php       # Item class
โ”œโ”€โ”€ Service/
โ”‚   โ””โ”€โ”€ TableSchemaService.php           # Schema management
โ”œโ”€โ”€ EventListener/
โ”‚   โ””โ”€โ”€ ClassDefinitionListener.php      # Class definition events
โ”œโ”€โ”€ Installer/
โ”‚   โ””โ”€โ”€ ExtendedBlockInstaller.php       # Bundle installer
โ””โ”€โ”€ Resources/
    โ”œโ”€โ”€ config/
    โ”‚   โ””โ”€โ”€ services.yaml                # Service definitions
    โ””โ”€โ”€ public/
        โ”œโ”€โ”€ js/                          # Admin JavaScript
        โ””โ”€โ”€ css/                         # Admin CSS

๐Ÿ—„๏ธ Database Schema

Main Table Structure

For each extended block field, a table is created:

CREATE TABLE `object_eb_{classId}_{fieldName}` (
    `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    `o_id` INT(11) UNSIGNED NOT NULL,      -- Reference to parent object
    `fieldname` VARCHAR(70) NOT NULL,       -- Field name
    `index` INT(11) UNSIGNED NOT NULL,      -- Position in block
    `type` VARCHAR(100) NOT NULL,           -- Block type identifier
    -- ... field columns based on definition
    PRIMARY KEY (`id`),
    INDEX `idx_object` (`o_id`),
    INDEX `idx_fieldname` (`fieldname`)
);

๐Ÿšซ Field Restrictions

ExtendedBlock has specific field restrictions to ensure data integrity and prevent storage complexity issues. The following field types cannot be used within ExtendedBlock items:

Field Type Reason
LocalizedFields Complex table relationships would break storage logic
Block Standard Block uses serialized JSON storage mechanism
FieldCollections Complex container types cannot be nested
ObjectBricks Complex container types cannot be nested
ExtendedBlock Would cause infinite recursion
AdvancedManyToManyRelation Complex metadata per relation not supported
AdvancedManyToManyObjectRelation Complex metadata per relation not supported
ReverseObjectRelation Virtual field, reads owner's relations
Classificationstore Complex multi-table structure
StructuredTable Creates Nร—M columns per field, table-in-table UI complexity
Table Serialized storage defeats queryable purpose, table-in-table UI complexity

Why StructuredTable and Table are Blocked

StructuredTable and Table field types represent nested table structures that create significant complexity when used inside ExtendedBlock:

StructuredTable Issues:

  • Creates rows ร— columns number of database columns per field (e.g., 3 rows ร— 4 columns = 12 columns)
  • This would significantly bloat the ExtendedBlock table schema
  • Renders as a full table in the UI, causing table-within-table nesting
  • Each row-column combination requires separate column management

Table Issues:

  • Stores data as serialized PHP arrays in a single LONGTEXT column
  • Serialized storage defeats ExtendedBlock's purpose of queryable separate tables
  • Renders as a dynamic table grid, causing table-within-table nesting
  • Cannot be efficiently queried via SQL

UI/UX Concerns:

  • Both types render as tables within the ExtendedBlock grid, creating nested table complexity
  • Potential for layout instability and performance degradation
  • Excessive DOM injection when rendering table-within-table structures
  • Large datasets can cause significant memory and rendering overhead

If you need table-like data within ExtendedBlock, consider using multiple simple fields or restructuring your data model.

Supported Field Types

ExtendedBlock supports the following field types:

Category Field Types
Text & Content Input, Textarea, WYSIWYG, Email
Numeric & Boolean Numeric, Checkbox, Slider, BooleanSelect
Selection Select, Multiselect, Country, Country Multiselect, Language, Language Multiselect, Gender
Date & Time Date, DateTime
Relations ManyToOneRelation, ManyToManyRelation, ManyToManyObjectRelation
Assets Image, Link

Note: Simple relation fields store element references (ID + type) directly in the ExtendedBlock table. The table prefix is configurable via extended_block.table_prefix (default: object_eb_).

Grid Rendering Behavior

ExtendedBlock displays a preview table in the object grid view. The following describes how different field types are rendered:

Field Type Grid Display
Text fields (Input, Textarea, WYSIWYG, Email) Text content (truncated to 50 characters)
Numeric fields (Numeric, Slider) Numeric value
Boolean fields (Checkbox, BooleanSelect) "Yes" or "No"
Selection fields (Select, Multiselect, etc.) Selected value(s)
Date fields (Date, DateTime) Formatted date (Y-m-d)
Relations (ManyToOne, ManyToMany) Element key or path
Image Full asset path (e.g., /Products/Sample/image.jpg)
Link Link path or URL

Grid Preview Limits:

  • Maximum 5 items are shown in the grid preview
  • String values are truncated to 50 characters
  • HTML tags are stripped from WYSIWYG content

Media Field Rendering Strategy:

  • Image and Link fields display the full asset path for human-readable reference
  • This approach avoids performance overhead from thumbnail generation in nested grid cells
  • The full path includes the asset key (filename) for clear identification

Note: While Pimcore's native Image field renders thumbnails in grids, ExtendedBlock displays full asset paths to maintain performance with nested data structures and avoid N+1 asset loading issues.

๐Ÿšซ Placement and Nesting Rules

ExtendedBlock can only be placed at the root level of a class definition. To ensure data integrity and prevent performance issues, the following configurations are not allowed:

Where ExtendedBlock CAN be Used

Location Allowed
Root level of Class Definition โœ… Yes
Inside Tabpanel (layout) โœ… Yes
Inside Panel (layout) โœ… Yes
Inside Fieldcontainer (layout) โœ… Yes
Inside any layout container at root level โœ… Yes

Note: Layout containers (Tabpanel, Panel, Fieldcontainer, etc.) are transparent wrappers in Pimcore class definitions. ExtendedBlock can be placed inside any layout container as long as it's at the root level of the class definition.

Where ExtendedBlock CANNOT be Used

Location Reason
Inside LocalizedFields Complex table relationships would break
Inside FieldCollections FieldCollections have their own storage mechanism
Inside ObjectBricks ObjectBricks have their own storage mechanism
Inside Block Block uses serialized JSON storage
Inside another ExtendedBlock Would cause infinite recursion

What ExtendedBlock CANNOT Contain

Field Type Reason
ExtendedBlock Would cause infinite recursion and complex data relationships
Block Standard Block uses different storage mechanism
FieldCollections Complex container types cannot be nested
ObjectBricks Complex container types cannot be nested
LocalizedFields Complex table relationships would break storage logic

Examples

โŒ Invalid: ExtendedBlock inside LocalizedFields
LocalizedFields
โ””โ”€โ”€ contentBlocks (ExtendedBlock)  # Not allowed!

โŒ Invalid: ExtendedBlock inside FieldCollection
myFieldCollection (Fieldcollections)
โ””โ”€โ”€ contentBlocks (ExtendedBlock)  # Not allowed!

โŒ Invalid: ExtendedBlock inside ObjectBrick
myObjectBrick (Objectbricks)
โ””โ”€โ”€ contentBlocks (ExtendedBlock)  # Not allowed!

โŒ Invalid: ExtendedBlock inside Block
mainBlock (Block)
โ””โ”€โ”€ contentBlocks (ExtendedBlock)  # Not allowed!

โŒ Invalid: FieldCollections inside ExtendedBlock
contentBlocks (ExtendedBlock)
โ””โ”€โ”€ text_block
    โ””โ”€โ”€ myCollection (Fieldcollections)  # Not allowed!

โŒ Invalid: ObjectBricks inside ExtendedBlock
contentBlocks (ExtendedBlock)
โ””โ”€โ”€ text_block
    โ””โ”€โ”€ myBricks (Objectbricks)  # Not allowed!

โŒ Invalid: ExtendedBlock nesting
contentBlocks (ExtendedBlock)
โ””โ”€โ”€ text_block
    โ””โ”€โ”€ nestedBlocks (ExtendedBlock)  # Not allowed!

โŒ Invalid: Block inside ExtendedBlock
contentBlocks (ExtendedBlock)
โ””โ”€โ”€ text_block
    โ””โ”€โ”€ innerBlock (Block)  # Not allowed!

โœ… Valid: ExtendedBlock at root level with simple fields
Class: Product
โ”œโ”€โ”€ name (Input)
โ”œโ”€โ”€ contentBlocks (ExtendedBlock)  # At root level โœ“
โ”‚   โ”œโ”€โ”€ text_block
โ”‚   โ”‚   โ”œโ”€โ”€ title (Input)
โ”‚   โ”‚   โ”œโ”€โ”€ content (WYSIWYG)
โ”‚   โ”‚   โ””โ”€โ”€ description (Textarea)
โ”‚   โ””โ”€โ”€ image_block
โ”‚       โ”œโ”€โ”€ image (Image)
โ”‚       โ””โ”€โ”€ caption (Input)
โ””โ”€โ”€ price (Numeric)

โœ… Valid: ExtendedBlock inside layout containers
Class: Product
โ””โ”€โ”€ Tabpanel (layout)
    โ”œโ”€โ”€ Panel "General" (layout)
    โ”‚   โ”œโ”€โ”€ name (Input)
    โ”‚   โ””โ”€โ”€ price (Numeric)
    โ””โ”€โ”€ Panel "Content" (layout)
        โ””โ”€โ”€ Fieldcontainer (layout)
            โ””โ”€โ”€ contentBlocks (ExtendedBlock)  # Inside layouts at root level โœ“
                โ”œโ”€โ”€ text_block
                โ”‚   โ””โ”€โ”€ title (Input)
                โ””โ”€โ”€ image_block
                    โ””โ”€โ”€ image (Image)

Validation

The bundle automatically validates your class definition when saving and will throw an exception if any invalid placement or nesting is detected. This validation occurs both in the admin UI and via the PHP API.

๐Ÿ“š API Reference

ExtendedBlockContainer

Method Description
getItems() Get all block items
setItems(array $items) Set all block items
addItem(ExtendedBlockItem $item) Add an item
removeItem(int $index) Remove item at index
getItem(int $index) Get item at index
moveItem(int $from, int $to) Move item position
getItemsByType(string $type) Filter items by type
first() Get first item (or null if empty)
last() Get last item (or null if empty)
clear() Remove all items
isEmpty() Check if container is empty
count() Count items (Countable)
toArray() Convert to array
getObject() / setObject() Get/set parent object
getFieldname() / setFieldname() Get/set field name
getDefinition() / setDefinition() Get/set block definition
isLazyLoad() / isLoaded() Check lazy loading state

ExtendedBlockItem

Method Description
getId() / setId() Get/set database ID
getType() / setType() Get/set block type
getIndex() / setIndex() Get/set position index
getFieldValue(string $name) Get field value
setFieldValue(string $name, $value) Set field value
hasFieldValue(string $name) Check if field exists
removeFieldValue(string $name) Remove a field value
getAllFieldValues() Get all field values as array
toArray() Convert to array
fromArray(array $data) Create from array (static)
isModified() / setModified() Check/set modified state

Localization Methods (per-item)

Method Description
getLocalizedValue(string $language, string $name) Get localized field value
setLocalizedValue(string $language, string $name, $value) Set localized field value
getLocalizedValuesForLanguage(string $language) Get all values for a language
getLocalizedData() / setLocalizedData() Get/set all localized data
hasLocalizedData(string $language, ?string $name = null) Check if localized data exists
clearLocalizedData(string $language) Clear localized data for a language

Note: Per-item localization methods store data in a separate localized table. This is different from Pimcore's LocalizedFields data type (which is NOT supported inside ExtendedBlock).

๐Ÿงช Testing

Run the test suite:

# Install dev dependencies
composer install

# Run PHPUnit tests
composer test

# Run with coverage
composer test -- --coverage-html coverage

# Run coding standards check
composer cs-check

# Fix coding standards
composer cs-fix

# Run PHPStan static analysis
composer phpstan

๐Ÿ”ง Troubleshooting

Package Not Found Error

If you encounter the error:

Could not find a matching version of package chauhan-mukesh/extended-block-bundle

This typically means the package is not yet published to Packagist. Use the GitHub installation method instead:

  1. Add the repository to your project's composer.json:
{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Chauhan-Mukesh/extended-block"
        }
    ]
}
  1. Install the package:
composer require chauhan-mukesh/extended-block-bundle:dev-main

Stability Issues

If you get stability-related errors like:

Could not find a version of package chauhan-mukesh/extended-block-bundle matching your minimum-stability (stable).

This occurs when there are no tagged releases. Choose one of these solutions:

Option 1: Use the dev version with explicit stability

composer require chauhan-mukesh/extended-block-bundle:dev-main

Or with explicit stability flag:

composer require chauhan-mukesh/extended-block-bundle:dev-main@dev

Option 2: Use the branch alias version

The package provides a branch alias that maps dev-main to 1.0.x-dev:

composer require chauhan-mukesh/extended-block-bundle:1.0.x-dev

Option 3: Lower your project's minimum stability

Add the following to your composer.json:

{
    "minimum-stability": "dev",
    "prefer-stable": true
}

For Package Maintainers: Creating Stable Releases

To make the package installable with stable minimum-stability, create a git tag:

# Create a signed annotated tag (recommended)
git tag -a v1.0.0 -m "Release version 1.0.0"

# Push the tag to GitHub
git push origin v1.0.0

After pushing the tag, users can then install with:

composer require chauhan-mukesh/extended-block-bundle
# or with specific version constraint
composer require chauhan-mukesh/extended-block-bundle:^1.0

Note: The above commands only work after a stable version tag (e.g., v1.0.0) has been created and pushed to the repository.

๐Ÿค Contributing

Contributions are welcome! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and coding standards checks
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Coding Standards

This project follows:

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ‘ค Author

Chauhan Mukesh

๐Ÿ™ Acknowledgments

  • Pimcore for the amazing platform
  • Symfony for the robust framework
  • All contributors who help improve this bundle

๐Ÿ“– Documentation

For more detailed documentation, refer to the following resources:

Document Description
PHP API Reference Comprehensive guide for working with Extended Block through PHP API
README.md This file - overview and quick start guide

Additional Resources

Made with โค๏ธ for the Pimcore community