Shopware 6.7 introduces several enhancements to the platform's architecture, including significant improvements to console command development and execution. As developers working with Shopware, understanding how to create custom console commands is crucial for automating tasks, performing maintenance operations, and extending platform functionality.
Understanding Console Commands in Shopware 6.7
Console commands in Shopware 6.7 are part of the Symfony Console component integration, which provides a robust framework for command-line interface applications. These commands can be executed via the bin/console script and are particularly useful for administrative tasks, data processing, batch operations, and system maintenance.
The new version brings improved dependency injection handling, better error management, and enhanced debugging capabilities that make console command development more reliable and maintainable than previous versions.
Prerequisites and Setup
Before diving into command creation, ensure your Shopware 6.7 environment is properly configured. You'll need:
- Shopware 6.7.x installed
- Composer for dependency management
- Basic understanding of Symfony Console commands
- Access to the command line interface
The standard directory structure for console commands in Shopware follows the pattern of placing them in src/Core/Command or within your custom plugin's command directory.
Creating Your First Custom Console Command
To create a custom console command, you'll need to extend the Command class from Symfony's console component. Here's a comprehensive example demonstrating how to build a command that processes product data:
<?php declare(strict_types=1);
namespace MyPlugin\Command;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class ProductImportCommand extends Command
{
protected static $defaultName = 'myplugin:product:import';
private EntityRepositoryInterface $productRepository;
private Context $context;
public function __construct(
EntityRepositoryInterface $productRepository,
Context $context
) {
parent::__construct();
$this->productRepository = $productRepository;
$this->context = $context;
}
protected function configure(): void
{
$this
->setDescription('Imports products from external source')
->setHelp('This command allows you to import products from an external API or file');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title('Product Import Command');
try {
// Your import logic here
$products = $this->fetchProductsFromExternalSource();
$io->progressStart(count($products));
foreach ($products as $productData) {
$this->importSingleProduct($productData);
$io->progressAdvance();
}
$io->progressFinish();
$io->success('Products imported successfully!');
return Command::SUCCESS;
} catch (\Exception $e) {
$io->error('Import failed: ' . $e->getMessage());
return Command::FAILURE;
}
}
private function fetchProductsFromExternalSource(): array
{
// Implementation depends on your data source
return [
['name' => 'Product 1', 'price' => 100],
['name' => 'Product 2', 'price' => 200],
];
}
private function importSingleProduct(array $productData): void
{
// Product import logic here
$this->productRepository->create([
[
'name' => $productData['name'],
'price' => $productData['price'],
]
], $this->context);
}
}
Registering Your Command
In Shopware 6.7, command registration follows the standard Symfony service container approach. You'll need to register your command as a service in your plugin's services.xml file:
<?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 https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="MyPlugin\Command\ProductImportCommand">
<argument type="service" id="product.repository"/>
<argument type="service" id="Shopware\Core\Framework\Context"/>
<tag name="console.command" command="myplugin:product:import"/>
</service>
</services>
</container>
Advanced Command Features
Input Validation and Options
Shopware 6.7 enhances input handling with better validation mechanisms. You can define required options and arguments:
protected function configure(): void
{
$this
->setDescription('Imports products with advanced options')
->addArgument('source', InputArgument::REQUIRED, 'Source file or URL')
->addOption('limit', null, InputOption::VALUE_OPTIONAL, 'Limit number of products', 100)
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Run without actually importing');
}
Progress Indicators and Logging
The improved progress bar implementation in Shopware 6.7 provides better user feedback during long-running operations:
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$limit = (int) $input->getOption('limit');
$progressBar = $io->createProgressBar($limit);
$progressBar->start();
// Processing logic here
$progressBar->finish();
$io->newLine(2);
return Command::SUCCESS;
}
Error Handling and Logging
Shopware 6.7 introduces enhanced logging capabilities within console commands. Proper error handling ensures that your commands fail gracefully:
protected function execute(InputInterface $input, OutputInterface $output): int
{
try {
// Your command logic
$this->performOperation();
return Command::SUCCESS;
} catch (Exception $e) {
// Log the exception using Shopware's logging system
$this->logger->error('Command failed: ' . $e->getMessage());
return Command::FAILURE;
}
}
Integration with Shopware's Context System
One of the key improvements in Shopware 6.7 is the seamless integration between console commands and the platform's context system. This allows you to leverage Shopware's built-in functionality:
public function __construct(
EntityRepositoryInterface $productRepository,
Context $context,
LoggerInterface $logger
) {
parent::__construct();
$this->productRepository = $productRepository;
$this->context = $context;
$this->logger = $logger;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// Set context properties
$this->context = $this->context->addExtension('command', 'product-import');
// Use context in operations
$this->productRepository->search(new Criteria(), $this->context);
return Command::SUCCESS;
}
Performance Considerations
When developing console commands for Shopware 6.7, consider performance implications:
Batch Processing
For large datasets, implement batch processing to avoid memory issues:
private function processBatch(array $products): void
{
$batchSize = 50;
foreach (array_chunk($products, $batchSize) as $batch) {
$this->importBatch($batch);
// Optional: Add delay between batches
usleep(100000); // 0.1 second delay
}
}
Memory Management
Monitor memory usage and implement cleanup strategies:
protected function execute(InputInterface $input, OutputInterface $output): int
{
$startMemory = memory_get_usage();
// Your processing logic
$endMemory = memory_get_usage();
$memoryUsed = $endMemory - $startMemory;
$output->writeln("Memory used: " . number_format($memoryUsed) . " bytes");
return Command::SUCCESS;
}
Testing Your Commands
Shopware 6.7 provides better testing capabilities for console commands through the Symfony testing framework:
public function testCommandExecution(): void
{
$command = new ProductImportCommand(
$this->productRepository,
$this->context
);
$tester = new CommandTester($command);
$tester->execute(['--dry-run' => true]);
$this->assertEquals(Command::SUCCESS, $tester->getStatusCode());
}
Best Practices
Command Naming Conventions
Follow Shopware's naming conventions for commands:
// Good: Plugin name prefix + category + action
protected static $defaultName = 'myplugin:product:import';
// Avoid: Generic names
protected static $defaultName = 'import';
Documentation and Help Text
Provide comprehensive help text to make your commands user-friendly:
protected function configure(): void
{
$this
->setDescription('Imports products from external source')
->setHelp(
<<<EOF
The <info>%command.name%</info> command imports products from an external API or file.
<comment>Example:</comment>
bin/console myplugin:product:import /path/to/products.csv
EOF
);
}
Error Recovery
Implement proper error recovery mechanisms:
private function importSingleProduct(array $productData): bool
{
try {
// Import logic
return true;
} catch (Exception $e) {
$this->logger->error('Failed to import product: ' . $e->getMessage());
return false;
}
}
Running Your Command
Once registered, your command can be executed using:
# Basic execution
bin/console myplugin:product:import
# With options
bin/console myplugin:product:import --limit=50 --dry-run
# In production environment
bin/console myplugin:product:import --env=prod
Conclusion
Shopware 6.7 significantly enhances console command development with improved dependency injection, better error handling, and enhanced debugging capabilities. By following the patterns and best practices outlined in this article, you can create robust, maintainable console commands that integrate seamlessly with the Shopware platform.
The ability to process large datasets efficiently, handle errors gracefully, and provide meaningful user feedback makes console commands an invaluable tool for extending Shopware's functionality. As you continue developing custom solutions, remember to leverage Shopware's context system, implement proper logging, and consider performance implications when dealing with large-scale operations.
The improved Symfony Console integration in Shopware 6.7 ensures that your commands will be more reliable and easier to maintain while providing the flexibility needed for complex administrative tasks and data processing operations.