Building extensions for Shopware 6 has evolved into a highly structured discipline, and version 6.7 raises that bar significantly. The platform now enforces stricter dependency injection rules, tighter Symfony integration, and more predictable event handling. Developers who adapt early will write plugins that are faster, safer, and far easier to maintain across major updates. This guide outlines the essential best practices for crafting production-ready Shopware 6 plugins in 2024 and beyond.
1. Modern Plugin Architecture & Registration
Shopware 6.7 expects a clean, predictable directory layout. Every plugin must live under src/Shopware/Plugins/ or be autoloaded via composer.json with a valid namespace. Manual file detection is deprecated; rely on Shopware’s PluginManager to discover and register extensions during the boot process. Structure your code logically: separate business logic (Service/, Repository/), data mappings (Entity/, Definition/), administration assets (Administration/), and configuration (config/). Never mix plugin code with core overrides. If you need to extend core behavior, do it through events or service decoration instead of copying files.
2. Strict Dependency Injection & Service Definitions
The dependency injection container in Shopware 6.7 no longer tolerates lazy guessing. Always define services explicitly in src/Resources/config/services.xml. Use constructor injection and avoid calling the container directly inside your code. Leverage Symfony’s autowiring for simple services, but tag complex ones clearly. Common tags include shopware.event_subscriber, shopware.command, and shopware.entity_listener.
<service id="YourNamespace\Service\CheckoutProcessor">
<argument type="service" id="Shopware\Core\Checkout\Cart\SalesChannel\CartService"/>
<argument type="service" id="Shopware\Core\Framework\Validation\DataBagFactory"/>
</service>
If your service requires multiple dependencies or configuration, define it manually. Never use new ClassName() in business logic. It breaks the container, prevents mocking during tests, and causes memory leaks under high concurrency.
3. Event-Driven Design & Subscriber Patterns
The event system remains the safest way to modify Shopware’s behavior. In 6.7, you must implement Symfony\Component\EventDispatcher\EventSubscriberInterface or extend Shopware’s base subscriber classes. Prefer named events over generic hooks. For example, use Cart\BeforeRecalculationEvent instead of legacy checkout hooks. Subscribers should be lightweight: validate data, transform payloads, or trigger side effects asynchronously. Avoid blocking operations inside subscribers; delegate heavy tasks to queue workers. Always return immutable objects when possible to prevent accidental state mutation across the request lifecycle.
4. Configuration Management & Administration UI
Store plugin settings using Shopware’s configuration repository rather than raw files or environment variables alone. The framework provides Shopware\Core\Framework\Adapter\Store\Settings for multi-store compatibility and transactional safety. When building admin interfaces, use the official Vue-based administration framework. Define routes in config/routes.yaml, register components in Administration/, and expose configuration through dynamic forms. Avoid hardcoding settings; always read from the repository to support system stores and context switching.
5. Database Migrations & Entity Definitions
Never modify tables manually or via raw SQL. Shopware 6.7 enforces strict migration versioning per plugin. Create Migration classes that handle both forward and rollback operations. The migration system runs in dependency order, so use ->addDependencies() if your plugin relies on another extension’s schema changes. For custom entities, define them using DefinitionEntity or CoreFrameworkDefinition. Use the entity manager (EntityManagerInterface) for all CRUD operations. Avoid direct DQL or PDO calls; they bypass Shopware’s security layer, caching system, and event listeners.
6. Security, Validation & Input Handling
Treat every input as untrusted, even data coming from your own admin UI or other plugins. Validate payloads using Shopware’s constraint-based validation system before processing. Hash all secrets, use environment variables for API keys, and follow OWASP guidelines religiously. Disable debug output in production builds, sanitize file uploads, and validate MIME types. Never expose stack traces or raw query logs to end users. If your plugin communicates with external services, sign requests where possible and verify responses cryptographically.
7. Performance, Caching & Queue Integration
E-commerce workloads demand surgical performance optimization. Cache expensive computations using CacheTag and invalidate caches explicitly via ClearCacheMessageBus when underlying data changes. Never cache context-dependent data without proper tags. Offload email sending, webhooks, imports, and third-party API calls to queue workers using Shopware\Core\Framework\MessageQueue\Envelope. Synchronous processing in HTTP requests will degrade checkout speeds and trigger timeout errors under load. Profile your code with Blackfire or Xdebug, and optimize database queries by fetching only needed columns.
8. Testing, Versioning & Update Safety
Write comprehensive PHPUnit tests for services, migrations, admin routes, and event subscribers. Use Shopware’s Test\TestCase base classes and mock dependencies explicitly to avoid database calls during unit tests. Pin your plugin’s minimum Shopware version in composer.json and test against the latest 6.7 LTS patch releases before publishing. Document breaking changes in CHANGELOG.md, follow SemVer strictly, and never force-deploy untested code to production. Update compatibility checks regularly, as Shopware routinely tightens its internal contracts between minor releases.
Final Thoughts
Shopware 6.7 rewards developers who embrace architecture-first thinking. By prioritizing strict dependency injection, event-driven modularity, proper migrations, and rigorous testing, your plugin will perform reliably in complex store environments and survive framework upgrades without friction. The ecosystem is maturing rapidly; stay aligned with official documentation, participate in community discussions, and build extensions that scale responsibly. The future of Shopware development belongs to those who write clean, predictable, and maintainable code today.