Přechod na Symfony 7
Symfony 7.0 jen uklidilo: odstranilo všechno, co Symfony 6 zavrhlo, třeba anotaci @Route,
anotace SensioFrameworkExtraBundle, MessageHandlerInterface, renderForm() nebo vlastnost
$defaultName příkazu. Náhrady za ně má už Symfony 6.4, a tak většinu upgradu ze Symfony 6 na 7 uděláte
ještě na něm: DressCode s balíčkem dresscode/upgrade-symfony váš kód přepíše a co přepsat neumí,
ohlásí.
Podle UPGRADE-7.0.md má verze 7.0 stejné funkce jako 6.4, jen bez těch zavržených; obě vyšly společně na konci listopadu 2023. Verze 7.0 ale potřebuje PHP 8.2, kdežto 6.4 běží i na PHP 8.1 (Symfony 7.0).
Jak to vypadá
Tenhle controller vznikl pro Symfony 6.4 a projekt má v composer.json balíčky Symfony na 6.4.*.
Používá tři věci, které Symfony 7.0 odstranilo:
use Symfony\Component\Routing\Annotation\Route;
class OrderController extends AbstractController
{
/** @Route("/orders/{id}", name="order_show") */
public function show(Request $request, int $id): Response
{
$form = $this->createForm(OrderType::class);
return $this->renderForm('order/show.html.twig', [
'form' => $form,
'format' => $request->getContentType(),
]);
}
}
Po dresscode upgrade today, pořád na Symfony 6.4:
use Symfony\Component\Routing\Attribute\Route;
class OrderController extends AbstractController
{
#[Route('/orders/{id}', name: 'order_show')]
public function show(Request $request, int $id): Response
{
$form = $this->createForm(OrderType::class);
return $this->render('order/show.html.twig', [
'form' => $form,
'format' => $request->getContentTypeFormat(),
]);
}
}
Z anotace se stal stejnojmenný atribut, importovaný ze jmenného prostoru Attribute místo
Annotation. Z renderForm() je render(), které bere formulář tak, jak je, a z
getContentType() je getContentTypeFormat(). Kód dál běží na 6.4. Po zvednutí verzí v
composer.json na 7.0.* už druhý běh v tomhle controlleru nenašel nic k přepsání.
Anotace SensioFrameworkExtraBundle
SensioFrameworkExtraBundle je opuštěný a jeho poslední verze 6.2.10 připouští symfony/framework-bundle
jen do řady 6.x, jak ukazuje Packagist. Framework má
od Symfony 6.2 pro tyto anotace vlastní atributy a DressCode je napíše místo anotací:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class ProductController extends AbstractController
{
/**
* @IsGranted("ROLE_EDITOR")
* @Cache(maxage=3600, public=true)
* @Template("product/list.html.twig")
*/
public function list(): array
{
return ['products' => []];
}
}
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class ProductController extends AbstractController
{
#[\Symfony\Component\Security\Http\Attribute\IsGranted('ROLE_EDITOR')]
#[\Symfony\Component\HttpKernel\Attribute\Cache(maxage: 3600, public: true)]
#[\Symfony\Bridge\Twig\Attribute\Template('product/list.html.twig')]
public function list(): array
{
return ['products' => []];
}
}
Importy bundlu v souboru zůstanou, a tak se nové atributy píšou plně kvalifikovanými jmény, která se s nimi
nemůžou střetnout. Importy smažte, až bundle odeberete. Anotace @Security, jejíž výraz jen volá
is_granted(), se převede také na #[IsGranted], jak ukazuje stránka Symfony.
Co se přepíše
Data balíčku dresscode/upgrade-symfony nesou 135 změn, které Symfony zavrhlo ve verzích 6.1 až 6.4 a ve
verzi 7.0 odstranilo. Z nich 98 DressCode přepíše sám a zbylých 37 ohlásí. Tabulka ukazuje příklady, každý
ověřený během DressCode. Úplný seznam je v datech balíčku, kde má každá komponenta svůj soubor, třeba console.neon.
| staré API | nové API | od verze |
|---|---|---|
protected static $defaultName = 'app:import'; |
#[AsCommand(name: 'app:import')] u třídy |
symfony/console 6.1 |
/** @Route("/orders/{id}") */ z Routing\Annotation |
#[Route('/orders/{id}')] z Routing\Attribute |
symfony/routing 6.4 |
class OrderPlacedHandler implements MessageHandlerInterface |
#[AsMessageHandler] class OrderPlacedHandler |
symfony/messenger 6.2 |
Symfony\Component\Security\Core\Security |
Symfony\Bundle\SecurityBundle\Security |
symfony/security-bundle 6.2 |
$this->renderForm($view, ['form' => $form]) |
$this->render($view, ['form' => $form]) |
symfony/framework-bundle 6.2 |
$request->getContentType() |
$request->getContentTypeFormat() |
symfony/http-foundation 6.2 |
$response->setEtag() |
$response->setEtag(null) |
symfony/http-foundation 6.2 |
/** @required */ |
#[Required] |
symfony/dependency-injection 6.3 |
@Assert\Regex("/^\w+$/") |
#[Assert\Regex('/^\w+$/')] |
symfony/validator 6.4 |
$e->getNestedExceptions() |
\array_values($e->getWrappedExceptions()) |
symfony/messenger 6.4 |
Symfony\Component\HttpKernel\UriSigner |
Symfony\Component\HttpFoundation\UriSigner |
symfony/http-kernel 6.4 |
SendinblueApiTransport |
BrevoApiTransport |
symfony/brevo-mailer 6.4 |
Sekci pro 7.0 data nemají, protože 7.0 přineslo tytéž funkce jako 6.4 a jen odstranilo, co bylo zavržené. Co
změnilo Symfony 6.0, třeba přejmenování MASTER_REQUEST na MAIN_REQUEST, patří k přechodu ze
Symfony 5 na 6 a balíček to pokrývá také.
Co se jen ohlásí
Kde se náhrada používá jinak nebo žádná není, DressCode do kódu nesáhne, jen místo ohlásí a poradí, co tam napsat. Typickým případem je třída, která si bere služby z kontejneru:
Class `Symfony\Component\DependencyInjection\ContainerAwareInterface` is deprecated: pass the services the class needs to its constructor, or implement `Symfony\Contracts\Service\ServiceSubscriberInterface` to fetch them lazily, since symfony/dependency-injection 6.4.
| staré API | co místo toho | od verze |
|---|---|---|
ContainerAwareInterface, ContainerAwareTrait |
služby v konstruktoru, nebo ServiceSubscriberInterface, který je načte líně |
symfony/dependency-injection 6.4 |
CacheableSupportsMethodInterface |
getSupportedTypes() normalizeru, které pro každý typ řekne, jestli se smí výsledek supports*()
cachovat |
symfony/serializer 6.3 |
PostSubmitEvent::setData() |
setData() z PreSubmitEvent nebo SubmitEvent, v listeneru, který běží před
odesláním formuláře |
symfony/form 6.4 |
Symfony\Bridge\Doctrine\Logger\DbalLogger |
middleware DBAL, třeba Doctrine\DBAL\Logging\Middleware |
symfony/doctrine-bridge 6.4 |
StopWorkerOnSignalsListener |
nic, messenger:consume zastaví workera při SIGTERM a SIGINT sám; listener
odeberte |
symfony/messenger 6.4 |
Kernel::stripComments() |
náhrada není; zkopírujte metodu do projektu | symfony/http-kernel 6.4 |
Takové místo potvrdíte komentářem // dresscode:ignore <rozhodnutí> -- <důvod>, nebo ho
přepíšete; podrobnosti najdete v kapitole Ruční úkoly
po cestě.
Změny konfigurace v YAMLu, šablon Twig a chování data nezachytí. Symfony 7.0 také dalo mnoha metodám nativní návratové typy (Symfony 7.0 type declarations) a vaše metoda, která některou z nich přepisuje, potřebuje stejný typ; jak takové signatury DressCode píše, říká stránka Symfony.
Krok za krokem
DressCode potřebuje PHP 8.4. Pokud vaše aplikace běží na starším PHP, nainstalujte DressCode globálně, s PHPStanem a s daty pro Symfony:
composer global require dresscode/dresscode dresscode/upgrade-symfony phpstan/phpstan
Na PHP 8.4 a novějším může být vývojovou závislostí projektu, jak ukazuje Instalace.
- Začněte na Symfony 6.4 s čistým pracovním stromem. Pusťte
dresscode upgrade today, a pokud to poradí, ještě jednou. Přepíše, co Symfony 6.1 až 6.4 zavrhlo, protože náhrady už v 6.4 existují. - Projděte, co ohlásí, pusťte testy a PHPStan a commitněte.
- Zvedněte balíčky Symfony v
composer.jsonna7.0.*nebo na pozdější 7.x arequire.phpaspoň na 8.2. Se Symfony Flex zvedněte iextra.symfony.require. Pak pusťtecomposer update "symfony/*" -W --prefer-lowest. - Pusťte znovu
dresscode upgrade today. Najde, co po zvednutí zbylo, a na pozdější 7.x i to, co zavrhla ta verze. Pak pusťte testy a commitněte.
Verzi každého balíčku DressCode čte z jeho omezení v composer.json. Když má balíček
Symfony v composer.json jen * a verzi nechává na extra.symfony.require, DressCode dolní
mez nevidí a změny toho balíčku jen ohlásí. Napište verzi do omezení, třeba 6.4.*.
Proč --prefer-lowest a proč po jedné hlavní verzi, vysvětluje Upgrade kódu krok za krokem.
Kam dál
- Symfony, všechny komponenty, které balíček pokrývá, i přechod ze Symfony 5 na 6.
- Upgrade kódu krok za krokem, celý postup s testy a commity.
- Přechod na novější PHP, protože Symfony 7 potřebuje PHP 8.2.