Master Symfony's Dependency Injection with autowiring, interface binding, service decoration, and tagged services for flexible architecture
/plugin marketplace add MakFly/superpowers-symfony/plugin install makfly-superpowers-symfony@MakFly/superpowers-symfonyThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Symfony automatically injects dependencies based on type-hints:
<?php
// src/Service/OrderService.php
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
class OrderService
{
public function __construct(
private EntityManagerInterface $em,
private LoggerInterface $logger,
) {}
public function createOrder(array $data): Order
{
$this->logger->info('Creating order', $data);
// ...
}
}
No configuration needed - Symfony wires it automatically.
<?php
// src/Service/PaymentGatewayInterface.php
namespace App\Service;
interface PaymentGatewayInterface
{
public function charge(int $amount, string $currency): PaymentResult;
public function refund(string $transactionId, int $amount): RefundResult;
}
<?php
// src/Service/StripePaymentGateway.php
namespace App\Service;
class StripePaymentGateway implements PaymentGatewayInterface
{
public function __construct(
private string $apiKey,
) {}
public function charge(int $amount, string $currency): PaymentResult
{
// Stripe implementation
}
public function refund(string $transactionId, int $amount): RefundResult
{
// Stripe implementation
}
}
# config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
# Bind interface to implementation
App\Service\PaymentGatewayInterface: '@App\Service\StripePaymentGateway'
# Or with parameters
App\Service\StripePaymentGateway:
arguments:
$apiKey: '%env(STRIPE_API_KEY)%'
class OrderService
{
public function __construct(
private PaymentGatewayInterface $paymentGateway, // Autowired!
) {}
}
Wrap a service to add behavior without modifying it:
<?php
// src/Service/LoggingPaymentGateway.php
namespace App\Service;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
#[AsDecorator(decorates: StripePaymentGateway::class)]
class LoggingPaymentGateway implements PaymentGatewayInterface
{
public function __construct(
#[AutowireDecorated]
private PaymentGatewayInterface $inner,
private LoggerInterface $logger,
) {}
public function charge(int $amount, string $currency): PaymentResult
{
$this->logger->info('Charging payment', [
'amount' => $amount,
'currency' => $currency,
]);
$result = $this->inner->charge($amount, $currency);
$this->logger->info('Payment result', [
'success' => $result->isSuccessful(),
'transactionId' => $result->getTransactionId(),
]);
return $result;
}
public function refund(string $transactionId, int $amount): RefundResult
{
$this->logger->info('Processing refund', [
'transactionId' => $transactionId,
'amount' => $amount,
]);
return $this->inner->refund($transactionId, $amount);
}
}
<?php
// src/Export/ExporterInterface.php
namespace App\Export;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('app.exporter')]
interface ExporterInterface
{
public function supports(string $format): bool;
public function export(array $data): string;
}
<?php
// src/Export/CsvExporter.php
namespace App\Export;
class CsvExporter implements ExporterInterface
{
public function supports(string $format): bool
{
return $format === 'csv';
}
public function export(array $data): string
{
// CSV export logic
}
}
// src/Export/JsonExporter.php
class JsonExporter implements ExporterInterface
{
public function supports(string $format): bool
{
return $format === 'json';
}
public function export(array $data): string
{
return json_encode($data, JSON_PRETTY_PRINT);
}
}
<?php
// src/Service/ExportService.php
namespace App\Service;
use App\Export\ExporterInterface;
use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
class ExportService
{
/**
* @param iterable<ExporterInterface> $exporters
*/
public function __construct(
#[AutowireIterator('app.exporter')]
private iterable $exporters,
) {}
public function export(array $data, string $format): string
{
foreach ($this->exporters as $exporter) {
if ($exporter->supports($format)) {
return $exporter->export($data);
}
}
throw new \InvalidArgumentException("Unsupported format: {$format}");
}
public function getSupportedFormats(): array
{
$formats = [];
foreach ($this->exporters as $exporter) {
// Each exporter reports what it supports
}
return $formats;
}
}
When you have multiple implementations:
# config/services.yaml
services:
App\Service\StripePaymentGateway:
arguments:
$apiKey: '%env(STRIPE_API_KEY)%'
App\Service\PaypalPaymentGateway:
arguments:
$clientId: '%env(PAYPAL_CLIENT_ID)%'
# Named bindings
App\Service\PaymentGatewayInterface $stripeGateway: '@App\Service\StripePaymentGateway'
App\Service\PaymentGatewayInterface $paypalGateway: '@App\Service\PaypalPaymentGateway'
class PaymentService
{
public function __construct(
private PaymentGatewayInterface $stripeGateway, // Stripe
private PaymentGatewayInterface $paypalGateway, // PayPal
) {}
}
Load service only when actually used:
use Symfony\Component\DependencyInjection\Attribute\Lazy;
#[Lazy]
class ExpensiveService
{
public function __construct()
{
// Heavy initialization
}
}
# List all services
bin/console debug:container
# Find specific service
bin/console debug:container OrderService
# Show autowiring candidates
bin/console debug:autowiring
# Show autowiring for specific type
bin/console debug:autowiring Payment
final by defaultprivate readonly for dependenciesCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.