Shopware 6.7 introduces significant improvements to its rule system, making it more flexible and extensible than ever before. One of the most powerful features is the ability to create custom rule conditions that can be used throughout the platform's commerce engine. This blog post will guide you through the complete process of registering a custom rule condition in Shopware 6.7.
Understanding Rule Conditions in Shopware 6.7
Before diving into implementation, it's crucial to understand what rule conditions are and how they work in Shopware 6.7. Rule conditions are used to evaluate specific criteria within the platform's business logic. They're commonly used for:
- Product pricing rules
- Shipping method calculations
- Promotion eligibility
- Customer group assignments
- Cart rule evaluations
In Shopware 6.7, the rule system has been enhanced with better performance optimizations and more intuitive APIs for developers to extend functionality.
Prerequisites and Setup
To create a custom rule condition, you'll need:
- A working Shopware 6.7 installation
- Basic knowledge of Symfony and PHP
- Understanding of Shopware's service container and dependency injection
- Familiarity with the platform's event system
Creating the Custom Rule Condition Class
The first step in creating a custom rule condition is to create the condition class itself. This class will extend Shopware's base condition class and implement the necessary interfaces.
<?php declare(strict_types=1);
namespace MyPlugin\Rule;
use Shopware\Core\Framework\Rule\Rule;
use Shopware\Core\Framework\Rule\RuleScope;
use Symfony\Component\Validator\Constraints as Assert;
class CustomProductCondition extends Rule
{
protected ?string $productId = null;
protected bool $isNot = false;
public function __construct(?string $productId = null, bool $isNot = false)
{
$this->productId = $productId;
$this->isNot = $isNot;
}
public function getName(): string
{
return 'custom_product_condition';
}
public function match(RuleScope $scope): bool
{
if (!$scope instanceof ProductScope) {
return false;
}
$product = $scope->getProduct();
if (!$product || !$this->productId) {
return false;
}
$result = $product->getId() === $this->productId;
return $this->isNot ? !$result : $result;
}
public function getConstraints(): array
{
return [
'productId' => [new Assert\NotBlank()],
'isNot' => [new Assert\Type('bool')],
];
}
}
Creating the Condition Scope
In Shopware 6.7, rule conditions require specific scope implementations. You'll need to create a custom scope class that defines how your condition should be evaluated.
<?php declare(strict_types=1);
namespace MyPlugin\Rule;
use Shopware\Core\Framework\Rule\RuleScope;
use Shopware\Core\Framework\Rule\RuleScopeInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
class ProductScope implements RuleScopeInterface
{
private ?string $productId = null;
private SalesChannelContext $context;
public function __construct(
string $productId,
SalesChannelContext $context
) {
$this->productId = $productId;
$this->context = $context;
}
public function getProductId(): ?string
{
return $this->productId;
}
public function getContext(): SalesChannelContext
{
return $this->context;
}
}
Registering the Condition with Dependency Injection
The next step involves registering your custom rule condition with Shopware's service container. This is done through the services.xml file in your plugin's configuration directory.
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="MyPlugin\Rule\CustomProductCondition">
<tag name="shopware.rule_condition"/>
<argument type="service" id="Shopware\Core\Framework\Validation\DataValidator"/>
</service>
<service id="MyPlugin\Rule\ProductScope">
<argument type="service" id="Shopware\Core\System\SalesChannel\SalesChannelContext"/>
</service>
</services>
</container>
Creating the Rule Configuration
To make your custom rule condition available in the admin interface, you need to create a configuration file that defines how it should be displayed and configured.
<?php declare(strict_types=1);
namespace MyPlugin\Rule;
use Shopware\Core\Framework\Rule\RuleConfig;
use Symfony\Component\Validator\Constraints as Assert;
class CustomProductConditionConfig extends RuleConfig
{
public function __construct()
{
parent::__construct();
$this->add('productId', [
'type' => 'text',
'label' => 'Product ID',
'required' => true,
]);
$this->add('isNot', [
'type' => 'checkbox',
'label' => 'Negate Condition',
'default' => false,
]);
}
public function getRule(): string
{
return CustomProductCondition::class;
}
}
Implementing the Rule Configuration Service
You'll need to create a service that handles the configuration and registration of your rule conditions.
<?php declare(strict_types=1);
namespace MyPlugin\Rule;
use Shopware\Core\Framework\Rule\RuleConfigServiceInterface;
use Shopware\Core\Framework\Rule\RuleConfig;
class CustomRuleConfigService implements RuleConfigServiceInterface
{
public function getConfig(string $ruleClass): ?RuleConfig
{
if ($ruleClass === CustomProductCondition::class) {
return new CustomProductConditionConfig();
}
return null;
}
public function getAvailableRules(): array
{
return [
CustomProductCondition::class => 'Custom Product Condition',
];
}
}
Registering the Configuration Service
Don't forget to register your configuration service in the services.xml file:
<service id="MyPlugin\Rule\CustomRuleConfigService">
<tag name="shopware.rule_config_service"/>
</service>
Creating the Admin Interface Integration
Shopware 6.7 provides enhanced tools for creating admin interfaces for rule conditions. You'll need to create a Vue component that handles the configuration UI.
<template>
<div class="custom-product-condition">
<sw-field
type="text"
:label="$t('custom-product-condition.product-id')"
v-model="config.productId"
required
/>
<sw-checkbox-field
:label="$t('custom-product-condition.negate')"
v-model="config.isNot"
/>
</div>
</template>
<script>
export default {
name: 'custom-product-condition',
props: {
config: {
type: Object,
required: true
}
}
}
</script>
Implementing the Rule Condition Service
To ensure your custom condition works seamlessly with Shopware's rule system, create a dedicated service that manages all aspects of the condition.
<?php declare(strict_types=1);
namespace MyPlugin\Rule;
use Shopware\Core\Framework\Rule\RuleConditionServiceInterface;
use Shopware\Core\Framework\Rule\RuleScope;
use Shopware\Core\Framework\Rule\RuleContext;
class CustomProductConditionService implements RuleConditionServiceInterface
{
public function match(Rule $rule, RuleScope $scope): bool
{
if (!$rule instanceof CustomProductCondition) {
return false;
}
if (!$scope instanceof ProductScope) {
return false;
}
$product = $scope->getProduct();
if (!$product || !$rule->getProductId()) {
return false;
}
$result = $product->getId() === $rule->getProductId();
return $rule->isNot() ? !$result : $result;
}
public function getRuleClass(): string
{
return CustomProductCondition::class;
}
}
Performance Considerations
When implementing custom rule conditions in Shopware 6.7, consider performance implications:
- Caching: Implement appropriate caching mechanisms for frequently used conditions
- Database Queries: Minimize database hits within condition logic
- Memory Usage: Be mindful of memory consumption during rule evaluation
- Indexing: Ensure proper database indexing for condition parameters
<?php declare(strict_types=1);
class OptimizedCustomProductCondition extends Rule
{
// ... previous implementation
public function match(RuleScope $scope): bool
{
// Add caching layer to prevent repeated evaluations
if ($this->shouldCache()) {
return $this->getCachedResult($scope);
}
// ... original matching logic
}
private function shouldCache(): bool
{
return $this->productId !== null;
}
}
Testing Your Custom Rule Condition
Proper testing is crucial for rule conditions. Create unit tests to ensure your implementation works correctly:
<?php declare(strict_types=1);
namespace MyPlugin\Tests\Rule;
use PHPUnit\Framework\TestCase;
use MyPlugin\Rule\CustomProductCondition;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
class CustomProductConditionTest extends TestCase
{
public function testConditionMatches(): void
{
$condition = new CustomProductCondition('product-123');
// Mock product and context
$mockProduct = $this->createMock(Product::class);
$mockProduct->method('getId')->willReturn('product-123');
$context = $this->createMock(SalesChannelContext::class);
$scope = new ProductScope('product-123', $context);
$result = $condition->match($scope);
$this->assertTrue($result);
}
public function testConditionDoesNotMatch(): void
{
$condition = new CustomProductCondition('product-123');
$mockProduct = $this->createMock(Product::class);
$mockProduct->method('getId')->willReturn('product-456');
$context = $this->createMock(SalesChannelContext::class);
$scope = new ProductScope('product-123', $context);
$result = $condition->match($scope);
$this->assertFalse($result);
}
}
Best Practices and Recommendations
When creating custom rule conditions in Shopware 6.7, follow these best practices:
- Keep Conditions Simple: Each condition should focus on a single business logic point
- Use Proper Validation: Always validate input parameters to prevent runtime errors
- Implement Caching: Cache frequently used conditions to improve performance
- Handle Edge Cases: Consider null values, empty strings, and unexpected inputs
- Document Your Conditions: Provide clear documentation for other developers
- Follow Naming Conventions: Use consistent naming patterns that align with Shopware's standards
Conclusion
Creating custom rule conditions in Shopware 6.7 opens up tremendous possibilities for extending your e-commerce platform's functionality. By following the steps outlined in this guide, you can create robust, performant rule conditions that integrate seamlessly with Shopware's existing commerce engine.
The key to successful implementation lies in understanding how Shopware's rule system works, properly structuring your code, and considering performance implications from the start. With proper testing and documentation, your custom rule conditions will provide valuable functionality while maintaining the stability and performance of your Shopware installation.
Remember to test thoroughly in different scenarios, monitor performance metrics, and keep your implementation updated with Shopware 6.7's ongoing improvements and best practices. The enhanced rule system in Shopware 6.7 makes it easier than ever to create sophisticated business logic that can be reused throughout your platform.