Developing plugins for Shopware 6 is incredibly powerful, but the framework's event-driven architecture and tightly coupled container can make diagnosing issues feel like navigating a labyrinth. With the release of Shopware 6.7, the platform has matured significantly: it now leverages Symfony 6.4/7.x, enforces stricter PHP 8.2+ typing, and ships with a more transparent debugging ecosystem. Understanding how to systematically debug your plugin is no longer optional; it's foundational for shipping stable, performant extensions. This guide walks you through practical debugging strategies tailored specifically to Shopware 6.7 and beyond.
Setting Up Your Debugging Environment
Before touching code, ensure your development stack aligns with Shopware 6.7's expectations. Start by configuring your .env file for local or staging environments: APP_ENV=dev, APP_DEBUG=true, and APP_TRUSTED_PROXIES=*. Shopware 6.7 no longer relies on legacy var_dump() or print_r() outputs. Instead, the framework fully integrates Symfony's var-dumper component, which provides safe, context-aware variable inspection in both the browser and CLI.
Verify that your PHP runtime is strictly 8.2 or higher. Composer dependencies like shopware/dev-tools should be installed alongside your plugin. This package includes pre-configured debugging helpers, profiler middleware, and deprecation scanners specifically built for the 6.7 architecture. Finally, ensure your web server virtual host points to public/index.php (not index.html) so that Shopware's kernel bootstrapping process executes correctly during debugging sessions.
Mastering PSR-3 Logging in Shopware 6.7
Logging remains your most reliable diagnostic tool, but Shopware 6.7 enforces strict dependency injection patterns. Never instantiate loggers manually. Instead, inject \Psr\Log\LoggerInterface or Shopware\Core\Framework\Log\LoggerInterface via your service constructor. Use contextual arrays to tag logs with plugin-specific metadata:
$this->logger->info('Custom hook executed', [
'plugin' => 'my_custom_plugin',
'hook_name' => 'ProductWrittenEvent',
'payload_count' => count($events),
]);
Shopware 6.7 introduces a unified log channel system. To isolate your plugin's output from core logs, configure a dedicated Monolog handler in your services.xml:
<service id="my_plugin.log_handler" class="Monolog\Handler\StreamHandler">
<argument>%kernel.logs_dir%/my_plugin.log</argument>
<argument>debug</argument>
</service>
<service id="monolog.channel.my_plugin" parent="monolog.logger" public="false">
<tag name="monolog.channel"/>
</service>
Always avoid logging sensitive customer data or raw payloads in production. In development, set your handler to debug level and monitor the file with tail -f. Contextual logging reduces noise while preserving traceability, making it easier to correlate errors with specific plugin hooks.
Leveraging Symfony VarDumper for Inline Diagnostics
When you need real-time inspection of request objects, route parameters, or entity states, Shopware 6.7 expects you to use symfony/var-dumper. In controllers, subscribers, or service methods, replace legacy dump functions with:
use Symfony\Component\VarDumper\VarDumper;
// Inside any method context
VarDumper::dump($myEntity);
Or simply call the global helper if available in your scope:
dump($request->getRequestUri(), $this->container->getParameter('kernel.project_dir'));
Shopware 6.7's dump output is automatically sanitized, styled for CLI or browser, and safely handles circular references that previously crashed scripts. Dumping event payloads immediately upon subscription entry reveals exact payload structures without triggering hydration side effects. Remember to clear your cache after modifying dump logic: bin/console cache:clear. Stale containers in dev mode can sometimes mask updated dump behavior.
Debugging Plugin Lifecycle & Event Subscribers
Plugins hook into Shopware's decoupled event system, but subscribers often appear silent when misconfigured. Start by verifying registration in your plugin's register() method or service definition. If your subscriber isn't firing, trace the lifecycle systematically:
- Confirm the class implements
Symfony\Component\EventDispatcher\EventSubscriberInterface. - Verify static methods in
getSubscribedEvents()return exact event class names as keys. - Use runtime listener inspection during development:
$listeners = $this->eventDispatcher->getListeners('product.updated');
For complex payloads, dump the event object immediately upon entry: dump($event->getPayload());. Shopware 6.7 improves event tracing by allowing you to listen to KernelEvents::CONTROLLER and FINISH_RESPONSE to measure request execution timing. If hooks silently fail, check for namespace collisions, incorrect service visibility in services.xml, or missing public="true" declarations on injected dependencies. The new container compiler strictly validates service references, so typos now throw explicit errors rather than silent null returns.
Xdebug & IDE Integration for Shopware 6.7
Breakpoint debugging remains essential for tracing execution flow. Configure Xdebug 3+ with:
xdebug.mode=develop,debug
xdebug.start_with_request=yes
xdebug.client_port=9003
Shopware 6.7's compiled container can interfere with step-through debugging if cache isn't refreshed after code changes. Always run bin/console cache:clear --no-warmup before setting breakpoints. For high-traffic endpoints, use conditional triggering to avoid performance degradation:
xdebug.trigger_value="*" combined with XDEBUG_TRIGGER=my_debug_session.
In PHPStorm or VS Code, map remote paths accurately and enable Auto-detect for Xdebug ports. Use the "Listen for Xdebug" feature alongside Shopware's Symfony Profiler (accessible via _profiler) to correlate breakpoints with memory usage and query counts. When debugging entity writes, inspect Doctrine\ORM\EntityManagerInterface state at breakpoints to catch hydration issues before they propagate.
CLI & Console Command Diagnostics
Many plugins extend cron jobs or custom commands. Shopware 6.7 standardizes console debugging by supporting --debug flags natively. Verify command routing with bin/console debug:command your_plugin_command. When testing execution, wrap logic in try-catch blocks and log traces contextually:
} catch (\Throwable $e) {
$this->logger->error('Plugin CLI failed', ['exception' => $e->getMessage(), 'line' => $e->getLine()]);
}
Use bin/console config:dump-reference monolog to audit log levels, and bin/console plugin:info YourPluginName to validate manifest configuration. Shopware 6.7 enforces stricter service visibility and constructor injection rules, so CLI "service not found" errors almost always trace back to missing public declarations or incorrect autowiring in your plugin's service definitions.
Shopware 6.7 Specific Debugging Enhancements
Several architectural upgrades streamline plugin diagnostics in 6.7:
shopware/dev-toolsprovides profiling middleware and deprecation scanners out of the box.- Plugin manifests (
shopware.yml) are validated at runtime; invalid configurations now throw immediate boot errors. - The framework enforces explicit type hints, catching parameter mismatches during container compilation rather than at runtime.
- Error rendering in templates uses
Framework\Adapter\Twig\ErrorRenderer, which surfaces precise line numbers and context variables.
Best Practices & Final Thoughts
Isolate debugging environments from production. Prefer typed arguments and constructor injection to catch issues early. Profile memory bottlenecks with Blackfire or the Symfony Web Profiler instead of adding excessive log statements. Document your debugging hooks for team collaboration, and always clear cache after configuration changes. Shopware 6.7's ecosystem rewards systematic diagnostics: by combining PSR-3 logging, VarDumper, Xdebug, and CLI tools, you'll resolve most plugin issues rapidly and confidently.
Debugging a Shopware 6 plugin in the 6.7 era is more predictable than ever. Leverage the framework's modern tooling, respect its container rules, and trace data flow methodically. Your plugins will become more stable, your development faster, and your confidence unmatched.