Shopware 6.7 introduced significant improvements to how developers can extend the platform's data model. Two primary approaches for extending entities are Entity Extensions and Custom Fields. Understanding when to use each approach is crucial for building maintainable and performant extensions.
Understanding Entity Extensions
Entity Extensions in Shopware 6.7 provide a powerful way to add new fields directly to existing database tables through the entity definition system. This approach modifies the core entity structure at runtime, allowing you to seamlessly integrate additional data into existing business objects.
Basic Implementation
To create an entity extension, you need to define it within your plugin's src/Resources/config directory:
<?php declare(strict_types=1);
use Shopware\Core\Framework\DataAbstractionLayer\EntityExtension;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required;
use Shopware\Core\Framework\DataAbstractionLayer\Field\TextField;
use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection;
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new TextField('custom_text_field', 'customTextField'))
->addFlags(new Required())
);
}
}
Registering Extensions
The extension must be registered in your plugin's src/Resources/config/services.xml:
<service id="MyPlugin\Core\Content\Product\Extension\ProductExtension">
<tag name="shopware.entity.extension"/>
</service>
Custom Fields: The Flexible Approach
Custom Fields offer a different paradigm entirely. Instead of modifying existing entity schemas, they provide a flexible key-value storage system that can be attached to any entity without requiring database schema changes.
Defining Custom Fields
Custom fields are defined through the custom_field_set entity:
<?php declare(strict_types=1);
use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\CreateCommand;
use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\ConstraintViolationException;
class CustomFieldSetup
{
public function createCustomFields(): void
{
$customFieldSet = [
'name' => 'product_custom_fields',
'config' => [
'label' => [
'de-DE' => 'Produkt Erweiterte Felder',
'en-GB' => 'Product Custom Fields'
]
],
'customFields' => [
[
'name' => 'internal_reference',
'type' => 'text',
'config' => [
'label' => [
'de-DE' => 'Interne Referenz',
'en-GB' => 'Internal Reference'
]
]
]
]
];
}
}
Key Differences and Use Cases
Performance Considerations
Entity Extensions provide better performance for frequently accessed data because they are part of the standard entity structure. Custom fields, while more flexible, require additional lookups and processing.
// Entity Extension - Direct database access
$product = $productRepository->search(
(new Criteria())->addFilter(new EqualsFilter('customTextField', 'value')),
$context
);
// Custom Fields - Requires additional processing
$product = $productRepository->search(
(new Criteria())->addFilter(new EqualsFilter('customFields.internal_reference', 'value')),
$context
);
Schema Impact
Entity Extensions modify the database schema directly, requiring migration handling during plugin updates:
<?php declare(strict_types=1);
use Shopware\Core\Framework\Migration\MigrationStep;
class Migration670000000000AddCustomFieldToProduct extends MigrationStep
{
public function getCreationTimestamp(): int
{
return 670000000000;
}
public function update(Connection $connection): void
{
$connection->executeStatement(
'ALTER TABLE `product` ADD COLUMN `custom_text_field` VARCHAR(255) NULL'
);
}
public function updateDestructive(Connection $connection): void
{
// Implementation for destructive changes
}
}
Data Type Support
Entity Extensions support all standard Shopware field types with full database indexing capabilities:
use Shopware\Core\Framework\DataAbstractionLayer\Field\IntField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\FloatField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\BoolField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\DateField;
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(new IntField('stock_limit', 'stockLimit'));
$collection->add(new FloatField('discount_rate', 'discountRate'));
$collection->add(new BoolField('is_featured', 'isFeatured'));
$collection->add(new DateField('release_date', 'releaseDate'));
}
}
Custom Fields, while more flexible in terms of field types, are limited to predefined configurations:
// Custom fields configuration
[
'type' => 'text', // String values only
'type' => 'number', // Numeric values only
'type' => 'checkbox', // Boolean values only
'type' => 'select', // Dropdown with predefined options
]
Advanced Entity Extension Patterns
Association Extensions
Entity extensions can also extend relationships between entities:
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
new OneToManyAssociationField('customProducts', CustomProductDefinition::class, 'product_id')
);
}
}
Computed Fields
You can create computed fields that are calculated at runtime:
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
new ComputedField('total_value', 'decimal(10,2)', function (ComputedField $field) {
return [
'price',
'quantity'
];
})
);
}
}
Best Practices for Custom Fields
Field Grouping Strategy
Organize custom fields into logical sets to maintain clarity:
// Define multiple custom field sets for different purposes
$customFieldSets = [
'product_technical' => [
'name' => 'product_technical_fields',
'label' => 'Technical Specifications'
],
'product_marketing' => [
'name' => 'product_marketing_fields',
'label' => 'Marketing Information'
]
];
Versioning and Migration
Custom fields should be versioned to handle updates gracefully:
class CustomFieldVersionManager
{
public function updateCustomFields(): void
{
// Check existing field set versions
$existingSet = $this->customFieldSetRepository->search(
(new Criteria())->addFilter(new EqualsFilter('name', 'product_custom_fields')),
$context
);
if ($existingSet->getTotal() > 0) {
// Update existing set
$this->updateExistingSet($existingSet->first());
} else {
// Create new set
$this->createNewSet();
}
}
}
Choosing Between Approaches
Use Entity Extensions When:
- Performance is critical - Direct database access without additional lookups
- Data is frequently queried - Complex filtering and sorting operations
- Schema stability is required - You need guaranteed field availability
- Complex data types are needed - Advanced field types with full indexing support
- Database integrity is paramount - Required fields, constraints, and validation
Use Custom Fields When:
- Flexibility is more important - Rapid prototyping and frequent changes
- Minimal database impact - Avoiding schema modifications
- User-defined configurations - Admin interface for field management
- Temporary or experimental features - Easy removal without migration
- Multiple entities need similar extensions - Reusable field structures
Migration Considerations
When migrating from one approach to another, consider the following:
// Migration script example
class MigrationFromCustomFieldsToEntityExtensions extends MigrationStep
{
public function update(Connection $connection): void
{
// Copy data from custom fields to new entity fields
$connection->executeStatement(
'UPDATE product SET custom_text_field = (SELECT value FROM custom_field_value WHERE custom_field_id = ? AND entity_id = product.id)'
);
}
}
Conclusion
Both Entity Extensions and Custom Fields serve important roles in Shopware 6.7's extension ecosystem. Entity Extensions provide robust, performant solutions for core business data that requires frequent access and complex queries. Custom Fields offer flexibility for rapidly changing requirements and user-defined configurations without the overhead of database schema changes.
The key is understanding your specific use case and choosing the approach that best balances performance, maintainability, and development speed. For critical business data with stable requirements, Entity Extensions are typically the better choice. For flexible, user-facing extensions or experimental features, Custom Fields provide the necessary agility while maintaining platform stability.
Remember to consider the long-term maintenance implications of each approach, especially regarding database migrations, performance monitoring, and upgrade compatibility when building your Shopware 6.7 extensions.