Symfony to nie tylko framework – to zestaw niezależnych komponentów PHP, które możesz używać osobno w dowolnym projekcie. Magento 2 samo z nich korzysta (Console, Filesystem, Serializer). Pokazuję kilka komponentów, które realnie przydają się w codziennej pracy z PHP i Magento: Console do pisania komend CLI, Validator do walidacji danych i HttpClient do komunikacji z zewnętrznymi API.
Symfony Console – komendy CLI jak w Magento
Jeśli piszesz skrypty migracyjne, importery lub narzędzia deweloperskie – Symfony Console to standard. Magento 2 buduje na nim własny system komend bin/magento:
composer require symfony/console
<?php
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\ProgressBar;
class ImportProductsCommand extends Command
{
protected function configure(): void
{
$this
->setName('import:products')
->setDescription('Importuje produkty z pliku CSV')
->addArgument('file', InputArgument::REQUIRED, 'Ścieżka do pliku CSV')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Tylko walidacja, bez zapisu')
->addOption('batch', 'b', InputOption::VALUE_OPTIONAL, 'Rozmiar batcha', 100);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$file = $input->getArgument('file');
$dryRun = $input->getOption('dry-run');
$batch = (int) $input->getOption('batch');
if (!file_exists($file)) {
$output->writeln("Plik nie istnieje: {$file} ");
return Command::FAILURE;
}
$rows = array_slice(file($file), 1); // pomiń nagłówek
$total = count($rows);
$output->writeln("Importuję {$total} produktów (batch: {$batch}) ");
if ($dryRun) {
$output->writeln('Tryb dry-run – bez zapisu do bazy ');
}
$progressBar = new ProgressBar($output, $total);
$progressBar->start();
foreach (array_chunk($rows, $batch) as $chunk) {
foreach ($chunk as $row) {
// logika importu
$progressBar->advance();
}
if (!$dryRun) {
// zapis batcha do bazy
}
}
$progressBar->finish();
$output->writeln('');
$output->writeln('Import zakończony. ');
return Command::SUCCESS;
}
}
// Bootstrap aplikacji CLI
$app = new \Symfony\Component\Console\Application('Import Tool', '1.0.0');
$app->add(new ImportProductsCommand());
$app->run();
Symfony Validator – walidacja danych wejściowych
Zamiast pisać własne walidatory od zera, Symfony Validator oferuje gotowe constraints i możliwość tworzenia własnych:
composer require symfony/validator
<?php
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validation;
// Walidacja prostej tablicy danych
$validator = Validation::createValidator();
$productData = [
'sku' => '', // błąd - wymagane
'price' => -10.0, // błąd - musi być >= 0
'email' => 'nie-email', // błąd - niepoprawny format
'name' => 'Produkt testowy',
];
$constraints = new Assert\Collection([
'sku' => [new Assert\NotBlank(), new Assert\Length(['min' => 3, 'max' => 64])],
'price' => [new Assert\NotNull(), new Assert\GreaterThanOrEqual(0)],
'email' => [new Assert\Email()],
'name' => [new Assert\NotBlank(), new Assert\Length(['max' => 255])],
]);
$violations = $validator->validate($productData, $constraints);
if (count($violations) > 0) {
foreach ($violations as $violation) {
echo $violation->getPropertyPath() . ': ' . $violation->getMessage() . PHP_EOL;
}
// [sku]: This value should not be blank.
// [price]: This value should be greater than or equal to 0.
// [email]: This value is not a valid email address.
}
Walidacja obiektów przez adnotacje lub atrybuty PHP 8.0:
<?php
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validation;
class ProductImportDto
{
public function __construct(
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 64)]
public readonly string $sku,
#[Assert\NotBlank]
#[Assert\Length(max: 255)]
public readonly string $name,
#[Assert\GreaterThanOrEqual(0)]
public readonly float $price,
#[Assert\Email]
#[Assert\NotBlank]
public readonly string $contactEmail
) {}
}
$validator = Validation::createValidatorBuilder()
->enableAttributeMapping()
->getValidator();
$dto = new ProductImportDto(
sku: 'MG-001',
name: 'Testowy produkt',
price: 29.99,
contactEmail: 'bledny-email'
);
$violations = $validator->validate($dto);
// [contactEmail]: This value is not a valid email address.
Symfony HttpClient – komunikacja z zewnętrznymi API
Symfony HttpClient to nowoczesna alternatywa dla Guzzle – lżejsza, z wbudowanym wsparciem dla asynchronicznych requestów:
composer require symfony/http-client
<?php
use Symfony\Component\HttpClient\HttpClient;
$client = HttpClient::create([
'base_uri' => 'https://api.example.com',
'headers' => ['Authorization' => 'Bearer ' . $token],
'timeout' => 10,
]);
// Synchroniczny request
$response = $client->request('GET', '/v1/products', [
'query' => ['page' => 1, 'limit' => 100],
]);
if ($response->getStatusCode() !== 200) {
throw new \RuntimeException('API error: ' . $response->getStatusCode());
}
$products = $response->toArray(); // automatyczny JSON decode
// Kilka równoległych requestów - Symfony wykonuje je współbieżnie
$responses = [];
foreach ($productIds as $id) {
$responses[$id] = $client->request('GET', "/v1/products/{$id}");
}
// Dane pobierane są dopiero tu - współbieżnie
foreach ($responses as $id => $response) {
$data = $response->toArray();
echo $data['name'] . PHP_EOL;
}
Kiedy komponenty Symfony zamiast pisania od zera?
Główna zasada: nie reinventuj koła. Jeśli piszesz skrypt CLI i zaczynasz tworzyć własny parser argumentów – użyj Console. Jeśli walidacja danych przychodzących z CSV lub API rośnie w złożone if-else – użyj Validator. Symfony komponenty są battle-tested, dobrze udokumentowane i mają pełne pokrycie testami.
W kontekście Magento 2: pisząc moduł z rozbudowaną komendą CLI, możesz oprzeć się na Magento\Framework\Console\Command (która dziedziczy z Symfony Command) i korzystać z pełnego API Symfony Console – progress bary, tabele, pytania interaktywne.
Podsumowanie
Symfony jako zestaw komponentów to jeden z najlepszych zasobów ekosystemu PHP. Nie musisz używać pełnego frameworka żeby korzystać z Console, Validator czy HttpClient. W projektach Magento 2 komponenty Symfony pojawiają się naturalnie przy pisaniu narzędzi CLI, walidacji danych importowanych z zewnętrznych systemów i komunikacji z API – to dobre miejsca żeby zacząć.
