Skip to content

Latest commit

 

History

History
1903 lines (1391 loc) · 54.6 KB

rector_rules_overview.md

File metadata and controls

1903 lines (1391 loc) · 54.6 KB

85 Rules Overview

ActionSuffixRemoverRector

Removes Action suffixes from methods in Symfony Controllers

 class SomeController
 {
-    public function indexAction()
+    public function index()
     {
     }
 }

AddRouteAnnotationRector

Collect routes from Symfony project router and add Route annotation to controller action

 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\Routing\Annotation\Route;

 final class SomeController extends AbstractController
 {
+    /**
+     * @Route(name="homepage", path="/welcome")
+     */
     public function index()
     {
     }
 }

AddViolationToBuildViolationRector

Change $context->addViolationAt to $context->buildViolation on Validator ExecutionContext

-$context->addViolationAt('property', 'The value {{ value }} is invalid.', array(
-    '{{ value }}' => $invalidValue,
-));
+$context->buildViolation('The value {{ value }} is invalid.')
+    ->atPath('property')
+    ->setParameter('{{ value }}', $invalidValue)
+    ->addViolation();

ArgumentValueResolverToValueResolverRector

Replaces ArgumentValueResolverInterface by ValueResolverInterface

-use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;

-final class EntityValueResolver implements ArgumentValueResolverInterface
+final class EntityValueResolver implements ValueResolverInterface
 {
-    public function supports(Request $request, ArgumentMetadata $argument): bool
-    {
-    }
-
     public function resolve(Request $request, ArgumentMetadata $argument): iterable
     {
     }
 }

AssertSameResponseCodeWithDebugContentsRector

Make assertSame(200, $response->getStatusCode()) in tests comparing response code to include response contents for faster feedback

 use PHPUnit\Framework\TestCase;

 class SomeClass extends TestCase
 {
     public function run()
     {
         /** @var \Symfony\Component\HttpFoundation\Response $response */
         $response = $this->processResult();

-        $this->assertSame(200, $response->getStatusCode());
+        $this->assertSame(200, $response->getStatusCode(), $response->getContent());
     }
 }

AuthorizationCheckerIsGrantedExtractorRector

Change $this->authorizationChecker->isGranted([$a, $b]) to $this->authorizationChecker->isGranted($a) || $this->authorizationChecker->isGranted($b), also updates AbstractController usages

-if ($this->authorizationChecker->isGranted(['ROLE_USER', 'ROLE_ADMIN'])) {
+if ($this->authorizationChecker->isGranted('ROLE_USER') || $this->authorizationChecker->isGranted('ROLE_ADMIN')) {
 }

BinaryFileResponseCreateToNewInstanceRector

Change deprecated BinaryFileResponse::create() to use __construct() instead

 use Symfony\Component\HttpFoundation;

 class SomeClass
 {
     public function run()
     {
-        $binaryFile = BinaryFileResponse::create();
+        $binaryFile = new BinaryFileResponse(null);
     }
 }

ChangeCollectionTypeOptionNameFromTypeToEntryTypeRector

Rename type option to entry_type in CollectionType

 use Symfony\Component\Form\AbstractType;
 use Symfony\Component\Form\FormBuilderInterface;
 use Symfony\Component\Form\Extension\Core\Type\CollectionType;
 use Symfony\Component\Form\Extension\Core\Type\ChoiceType;

 class TaskType extends AbstractType
 {
     public function buildForm(FormBuilderInterface $builder, array $options)
     {
         $builder->add('tags', CollectionType::class, [
-            'type' => ChoiceType::class,
-            'options' => [1, 2, 3],
+            'entry_type' => ChoiceType::class,
+            'entry_options' => [1, 2, 3],
         ]);
     }
 }

ChangeStringCollectionOptionToConstantRector

Change type in CollectionType from alias string to class reference

 use Symfony\Component\Form\AbstractType;
 use Symfony\Component\Form\FormBuilderInterface;
 use Symfony\Component\Form\Extension\Core\Type\CollectionType;

 class TaskType extends AbstractType
 {
     public function buildForm(FormBuilderInterface $builder, array $options)
     {
         $builder->add('tags', CollectionType::class, [
-            'type' => 'choice',
+            'type' => \Symfony\Component\Form\Extension\Core\Type\ChoiceType::class,
         ]);

         $builder->add('tags', 'collection', [
-            'type' => 'choice',
+            'type' => \Symfony\Component\Form\Extension\Core\Type\ChoiceType::class,
         ]);
     }
 }

CommandConstantReturnCodeRector

Changes int return from execute to use Symfony Command constants.

 class SomeCommand extends Command
 {
     protected function execute(InputInterface $input, OutputInterface $output): int
     {
-        return 0;
+        return \Symfony\Component\Console\Command\Command::SUCCESS;
     }

 }

CommandDescriptionToPropertyRector

Symfony Command description setters are moved to properties

 use Symfony\Component\Console\Command\Command

 final class SunshineCommand extends Command
 {
+    protected static $defaultDescription = 'sunshine description';
+
     public function configure()
     {
-        $this->setDescription('sunshine description');
     }
 }

CommandPropertyToAttributeRector

Add Symfony\Component\Console\Attribute\AsCommand to Symfony Commands and remove the deprecated properties

+use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Command\Command;

+#[AsCommand('sunshine')]
 final class SunshineCommand extends Command
 {
-    /** @var string|null */
-    public static $defaultName = 'sunshine';
 }

ConsoleExceptionToErrorEventConstantRector

Turns old event name with EXCEPTION to ERROR constant in Console in Symfony

-"console.exception"
+Symfony\Component\Console\ConsoleEvents::ERROR

-Symfony\Component\Console\ConsoleEvents::EXCEPTION
+Symfony\Component\Console\ConsoleEvents::ERROR

ConsoleExecuteReturnIntRector

Returns int from Command::execute() command

 use Symfony\Component\Console\Command\Command;

 class SomeCommand extends Command
 {
-    public function execute(InputInterface $input, OutputInterface $output)
+    public function execute(InputInterface $input, OutputInterface $output): int
     {
-        return null;
+        return 0;
     }
 }

ConstraintUrlOptionRector

Turns true value to Url::CHECK_DNS_TYPE_ANY in Validator in Symfony.

-$constraint = new Url(["checkDNS" => true]);
+$constraint = new Url(["checkDNS" => Url::CHECK_DNS_TYPE_ANY]);

ContainerBuilderCompileEnvArgumentRector

Turns old default value to parameter in ContainerBuilder->build() method in DI in Symfony

 use Symfony\Component\DependencyInjection\ContainerBuilder;

 $containerBuilder = new ContainerBuilder();
-$containerBuilder->compile();
+$containerBuilder->compile(true);

ContainerGetNameToTypeInTestsRector

Change $container->get("some_name") to bare type, useful since Symfony 3.4

 use PHPUnit\Framework\TestCase;

 final class SomeTest extends TestCase
 {
     public function run()
     {
         $container = $this->getContainer();
-        $someClass = $container->get('some_name');
+        $someClass = $container->get(SomeType::class);
     }
 }

ContainerGetToConstructorInjectionRector

Turns fetching of dependencies via $container->get() in ContainerAware to constructor injection in Command and Controller in Symfony

 final class SomeCommand extends ContainerAwareCommand
 {
+    public function __construct(SomeService $someService)
+    {
+        $this->someService = $someService;
+    }
+
     public function someMethod()
     {
         // ...
-        $this->getContainer()->get('some_service');
-        $this->container->get('some_service');
+        $this->someService;
+        $this->someService;
     }
 }

ConvertRenderTemplateShortNotationToBundleSyntaxRector

Change Twig template short name to bundle syntax in render calls from controllers

 class BaseController extends Controller {
     function indexAction()
     {
-        $this->render('appBundle:Landing\Main:index.html.twig');
+        $this->render('@app/Landing/Main/index.html.twig');
     }
 }

DefinitionAliasSetPrivateToSetPublicRector

Migrates from deprecated Definition/Alias->setPrivate() to Definition/Alias->setPublic()

 use Symfony\Component\DependencyInjection\Alias;
 use Symfony\Component\DependencyInjection\Definition;

 class SomeClass
 {
     public function run()
     {
         $definition = new Definition('Example\Foo');
-        $definition->setPrivate(false);
+        $definition->setPublic(true);

         $alias = new Alias('Example\Foo');
-        $alias->setPrivate(false);
+        $alias->setPublic(true);
     }
 }

DowngradeSymfonyCommandAttributeRector

Downgrade Symfony Command Attribute

 #[AsCommand(name: 'app:create-user', description: 'some description')]
 class CreateUserCommand extends Command
-{}
+{
+    protected function configure(): void
+    {
+        $this->setName('app:create-user');
+        $this->setDescription('some description');
+    }
+}

ErrorNamesPropertyToConstantRector

Turns old Constraint::$errorNames properties to use Constraint::ERROR_NAMES instead

 use Symfony\Component\Validator\Constraints\NotBlank;

 class SomeClass
 {
-    NotBlank::$errorNames
+    NotBlank::ERROR_NAMES

 }

EventDispatcherParentConstructRector

Removes parent construct method call in EventDispatcher class

 use Symfony\Component\EventDispatcher\EventDispatcher;

 final class SomeEventDispatcher extends EventDispatcher
 {
     public function __construct()
     {
         $value = 1000;
+        parent::__construct();
     }
 }

EventListenerToEventSubscriberRector

Change Symfony Event listener class to Event Subscriber based on configuration in service.yaml file

-class SomeListener
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class SomeEventSubscriber implements EventSubscriberInterface
 {
+     /**
+      * @return string[]
+      */
+     public static function getSubscribedEvents(): array
+     {
+         return ['some_event' => 'methodToBeCalled'];
+     }
+
      public function methodToBeCalled()
      {
      }
-}
-
-// in config.yaml
-services:
-    SomeListener:
-        tags:
-            - { name: kernel.event_listener, event: 'some_event', method: 'methodToBeCalled' }
+}

FormBuilderSetDataMapperRector

Migrates from deprecated Form Builder->setDataMapper(new PropertyPathMapper()) to Builder->setDataMapper(new DataMapper(new PropertyPathAccessor()))

 use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
 use Symfony\Component\Form\FormConfigBuilderInterface;
+use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper;
+use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor;

 class SomeClass
 {
     public function run(FormConfigBuilderInterface $builder)
     {
-        $builder->setDataMapper(new PropertyPathMapper());
+        $builder->setDataMapper(new DataMapper(new PropertyPathAccessor()));
     }
 }

FormIsValidRector

Adds $form->isSubmitted() validation to all $form->isValid() calls in Form in Symfony

-if ($form->isValid()) {
+if ($form->isSubmitted() && $form->isValid()) {
 }

FormTypeGetParentRector

Turns string Form Type references to their CONSTANT alternatives in getParent() and getExtendedType() methods in Form in Symfony

 use Symfony\Component\Form\AbstractType;

 class SomeType extends AbstractType
 {
     public function getParent()
     {
-        return 'collection';
+        return \Symfony\Component\Form\Extension\Core\Type\CollectionType::class;
     }
 }

 use Symfony\Component\Form\AbstractTypeExtension;

 class SomeExtension extends AbstractTypeExtension
 {
     public function getExtendedType()
     {
-        return 'collection';
+        return \Symfony\Component\Form\Extension\Core\Type\CollectionType::class;
     }
 }

FormTypeInstanceToClassConstRector

Changes createForm(new FormType), add(new FormType) to ones with "FormType::class"

 use Symfony\Bundle\FrameworkBundle\Controller\Controller;

 final class SomeController extends Controller
 {
     public function action()
     {
-        $form = $this->createForm(new TeamType);
+        $form = $this->createForm(TeamType::class);
     }
 }

GetCurrencyBundleMethodCallsToIntlRector

Intl static bundle method were changed to direct static calls

-$currencyBundle = \Symfony\Component\Intl\Intl::getCurrencyBundle();
-
-$currencyNames = $currencyBundle->getCurrencyNames();
+$currencyNames = \Symfony\Component\Intl\Currencies::getNames();

GetHelperControllerToServiceRector

Replace $this->getDoctrine() and $this->dispatchMessage() calls in AbstractController with direct service use

 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Doctrine\Persistence\ManagerRegistry;

 final class SomeController extends AbstractController
 {
+    public function __construct(
+        private ManagerRegistry $managerRegistry
+    ) {
+    }
+
     public function run()
     {
-        $productRepository = $this->getDoctrine()->getRepository(Product::class);
+        $productRepository = $this->managerRegistry->getRepository(Product::class);
     }
 }

GetRequestRector

Turns fetching of Request via $this->getRequest() to action injection

+use Symfony\Component\HttpFoundation\Request;
+
 class SomeController
 {
-    public function someAction()
+    public function someAction(Request $request)
     {
-        $this->getRequest()->...();
+        $request->...();
     }
 }

GetToConstructorInjectionRector

Turns fetching of dependencies via $this->get() to constructor injection in Command and Controller

 use Symfony\Bundle\FrameworkBundle\Controller\Controller;

 final class SomeController extend Controller
 {
+    public function __construct(SomeService $someService)
+    {
+        $this->someService = $someService;
+    }
+
     public function someMethod()
     {
-        // ...
-        $this->get('some_service');
+        $this->someService;
     }
 }

KernelTestCaseContainerPropertyDeprecationRector

Simplify use of assertions in WebTestCase

 use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

 class SomeTest extends KernelTestCase
 {
     protected function setUp(): void
     {
-        $container = self::$container;
+        $container = self::getContainer();
     }
 }

LiteralGetToRequestClassConstantRector

Replace "GET" string by Symfony Request object class constants

 use Symfony\Component\Form\FormBuilderInterface;

 final class SomeClass
 {
     public function detail(FormBuilderInterface $formBuilder)
     {
-        $formBuilder->setMethod('GET');
+        $formBuilder->setMethod(\Symfony\Component\HttpFoundation\Request::GET);
     }
 }

LoadValidatorMetadataToAnnotationRector

Move metadata from loadValidatorMetadata() to property/getter/method annotations

 use Symfony\Component\Validator\Constraints as Assert;
 use Symfony\Component\Validator\Mapping\ClassMetadata;

 final class SomeClass
 {
+    /**
+     * @Assert\NotBlank(message="City can't be blank.")
+     */
     private $city;
-
-    public static function loadValidatorMetadata(ClassMetadata $metadata): void
-    {
-        $metadata->addPropertyConstraint('city', new Assert\NotBlank([
-            'message' => 'City can\'t be blank.',
-        ]));
-    }
 }

LogoutHandlerToLogoutEventSubscriberRector

Change logout handler to an event listener that listens to LogoutEvent

-use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\Security\Http\Event\LogoutEvent;

-final class SomeLogoutHandler implements LogoutHandlerInterface
+final class SomeLogoutHandler implements EventSubscriberInterface
 {
-    public function logout(Request $request, Response $response, TokenInterface $token)
+    public function onLogout(LogoutEvent $logoutEvent): void
     {
+        $request = $logoutEvent->getRequest();
+        $response = $logoutEvent->getResponse();
+        $token = $logoutEvent->getToken();
+    }
+
+    /**
+     * @return array<string, string[]>
+     */
+    public static function getSubscribedEvents(): array
+    {
+        return [
+            LogoutEvent::class => ['onLogout'],
+        ];
     }
 }

LogoutSuccessHandlerToLogoutEventSubscriberRector

Change logout success handler to an event listener that listens to LogoutEvent

-use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\Security\Http\Event\LogoutEvent;

-final class SomeLogoutHandler implements LogoutSuccessHandlerInterface
+final class SomeLogoutHandler implements EventSubscriberInterface
 {
     /**
       * @var HttpUtils
       */
     private $httpUtils;

-    public function __construct(HttpUtils $httpUtils)
+    public function onLogout(LogoutEvent $logoutEvent): void
     {
-        $this->httpUtils = $httpUtils;
+        if ($logoutEvent->getResponse() !== null) {
+            return;
+        }
+
+        $response = $this->httpUtils->createRedirectResponse($logoutEvent->getRequest(), 'some_url');
+        $logoutEvent->setResponse($response);
     }

-    public function onLogoutSuccess(Request $request)
+    /**
+     * @return array<string, mixed>
+     */
+    public static function getSubscribedEvents(): array
     {
-        $response = $this->httpUtils->createRedirectResponse($request, 'some_url');
-        return $response;
+        return [
+            LogoutEvent::class => [['onLogout', 64]],
+        ];
     }
 }

MagicClosureTwigExtensionToNativeMethodsRector

Change TwigExtension function/filter magic closures to inlined and clear callables

 use Twig\Extension\AbstractExtension;
 use Twig\TwigFunction;

 final class TerminologyExtension extends AbstractExtension
 {
     public function getFunctions(): array
     {
         return [
-            new TwigFunction('resolve', [$this, 'resolve']);
+            new TwigFunction('resolve', $this->resolve(...)),
         ];
     }

     private function resolve($value)
     {
         return $value + 100;
     }
 }

MakeCommandLazyRector

Make Symfony commands lazy

 use Symfony\Component\Console\Command\Command

 final class SunshineCommand extends Command
 {
+    protected static $defaultName = 'sunshine';
     public function configure()
     {
-        $this->setName('sunshine');
     }
 }

MakeDispatchFirstArgumentEventRector

Make event object a first argument of dispatch() method, event name as second

 use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

 class SomeClass
 {
     public function run(EventDispatcherInterface $eventDispatcher)
     {
-        $eventDispatcher->dispatch('event_name', new Event());
+        $eventDispatcher->dispatch(new Event(), 'event_name');
     }
 }

MaxLengthSymfonyFormOptionToAttrRector

Change form option "max_length" to a form "attr" > "max_length"

 $formBuilder = new Symfony\Component\Form\FormBuilder();

 $form = $formBuilder->create('name', 'text', [
-    'max_length' => 123,
+    'attr' => ['maxlength' => 123],
 ]);

MergeMethodAnnotationToRouteAnnotationRector

Merge removed @Method annotation to @Route one

-use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
 use Symfony\Component\Routing\Annotation\Route;

 class DefaultController extends Controller
 {
     /**
-     * @Route("/show/{id}")
-     * @Method({"GET", "HEAD"})
+     * @Route("/show/{id}", methods={"GET","HEAD"})
      */
     public function show($id)
     {
     }
 }

MessageHandlerInterfaceToAttributeRector

Replaces MessageHandlerInterface with AsMessageHandler attribute

-use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
+use Symfony\Component\Messenger\Attribute\AsMessageHandler;

-class SmsNotificationHandler implements MessageHandlerInterface
+#[AsMessageHandler]
+class SmsNotificationHandler
 {
     public function __invoke(SmsNotification $message)
     {
         // ... do some work - like sending an SMS message!
     }
 }

MessageSubscriberInterfaceToAttributeRector

Replace MessageSubscriberInterface with AsMessageHandler attribute(s)

-use Symfony\Component\Messenger\Handler\MessageSubscriberInterface;
+use Symfony\Component\Messenger\Attribute\AsMessageHandler;

-class SmsNotificationHandler implements MessageSubscriberInterface
+class SmsNotificationHandler
 {
-    public function __invoke(SmsNotification $message)
+    #[AsMessageHandler]
+    public function handleSmsNotification(SmsNotification $message)
     {
         // ...
     }

+    #[AsMessageHandler(priority: 0, bus: 'messenger.bus.default']
     public function handleOtherSmsNotification(OtherSmsNotification $message)
     {
         // ...
-    }
-
-    public static function getHandledMessages(): iterable
-    {
-        // handle this message on __invoke
-        yield SmsNotification::class;
-
-        // also handle this message on handleOtherSmsNotification
-        yield OtherSmsNotification::class => [
-            'method' => 'handleOtherSmsNotification',
-            'priority' => 0,
-            'bus' => 'messenger.bus.default',
-        ];
     }
 }

OptionNameRector

Turns old option names to new ones in FormTypes in Form in Symfony

 $builder = new FormBuilder;
-$builder->add("...", ["precision" => "...", "virtual" => "..."];
+$builder->add("...", ["scale" => "...", "inherit_data" => "..."];

ParamConverterAttributeToMapEntityAttributeRector

Replace ParamConverter attribute with mappings with the MapEntity attribute

+use Symfony\Bridge\Doctrine\Attribute\MapEntity;
+
 class SomeController
 {
-    #[ParamConverter('post', options: ['mapping' => ['date' => 'date', 'slug' => 'slug']])]
-    #[ParamConverter('comment', options: ['mapping' => ['comment_slug' => 'slug']])]
     public function showComment(
+        #[MapEntity(mapping: ['date' => 'date', 'slug' => 'slug'])]
         Post $post,

+        #[MapEntity(mapping: ['comment_slug' => 'slug'])]
         Comment $comment
     ) {
     }
 }

ParamTypeFromRouteRequiredRegexRector

Complete strict param type declaration based on route annotation

 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 use Symfony\Component\Routing\Annotation\Route;

 final class SomeController extends Controller
 {
     /**
      * @Route(
      *     requirements={"number"="\d+"},
      * )
      */
-    public function detailAction($number)
+    public function detailAction(int $number)
     {
     }
 }

ParseFileRector

Replaces deprecated Yaml::parse() of file argument with file contents

 use Symfony\Component\Yaml\Yaml;

-$parsedFile = Yaml::parse('someFile.yml');
+$parsedFile = Yaml::parse(file_get_contents('someFile.yml'));

ProcessBuilderGetProcessRector

Removes $processBuilder->getProcess() calls to $processBuilder in Process in Symfony, because ProcessBuilder was removed. This is part of multi-step Rector and has very narrow focus.

 $processBuilder = new Symfony\Component\Process\ProcessBuilder;
-$process = $processBuilder->getProcess();
-$commamdLine = $processBuilder->getProcess()->getCommandLine();
+$process = $processBuilder;
+$commamdLine = $processBuilder->getCommandLine();

ProcessBuilderInstanceRector

Turns ProcessBuilder::instance() to new ProcessBuilder in Process in Symfony. Part of multi-step Rector.

-$processBuilder = Symfony\Component\Process\ProcessBuilder::instance($args);
+$processBuilder = new Symfony\Component\Process\ProcessBuilder($args);

PropertyAccessorCreationBooleanToFlagsRector

Changes first argument of PropertyAccessor::__construct() to flags from boolean

 class SomeClass
 {
     public function run()
     {
-        $propertyAccessor = new PropertyAccessor(true);
+        $propertyAccessor = new PropertyAccessor(PropertyAccessor::MAGIC_CALL | PropertyAccessor::MAGIC_GET | PropertyAccessor::MAGIC_SET);
     }
 }

PropertyPathMapperToDataMapperRector

Migrate from PropertyPathMapper to DataMapper and PropertyPathAccessor

 use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;

 class SomeClass
 {
     public function run()
     {
-        return new PropertyPathMapper();
+        return new \Symfony\Component\Form\Extension\Core\DataMapper\DataMapper(new \Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor());
     }
 }

ReadOnlyOptionToAttributeRector

Change "read_only" option in form to attribute

 use Symfony\Component\Form\FormBuilderInterface;

 function buildForm(FormBuilderInterface $builder, array $options)
 {
-    $builder->add('cuid', TextType::class, ['read_only' => true]);
+    $builder->add('cuid', TextType::class, ['attr' => ['read_only' => true]]);
 }

RedirectToRouteRector

Turns redirect to route to short helper method in Controller in Symfony

-$this->redirect($this->generateUrl("homepage"));
+$this->redirectToRoute("homepage");

ReflectionExtractorEnableMagicCallExtractorRector

Migrates from deprecated enable_magic_call_extraction context option in ReflectionExtractor

 use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;

 class SomeClass
 {
     public function run()
     {
         $reflectionExtractor = new ReflectionExtractor();
         $readInfo = $reflectionExtractor->getReadInfo(Dummy::class, 'bar', [
-            'enable_magic_call_extraction' => true,
+            'enable_magic_methods_extraction' => ReflectionExtractor::MAGIC_CALL | ReflectionExtractor::MAGIC_GET | ReflectionExtractor::MAGIC_SET,
         ]);
     }
 }

RemoveDefaultGetBlockPrefixRector

Rename getBlockPrefix() if it returns the default value - class to underscore, e.g. UserFormType = user_form

 use Symfony\Component\Form\AbstractType;

 class TaskType extends AbstractType
 {
-    public function getBlockPrefix()
-    {
-        return 'task';
-    }
 }

RemoveServiceFromSensioRouteRector

Remove service from Sensio @Route

 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

 final class SomeClass
 {
     /**
-     * @Route(service="some_service")
+     * @Route()
      */
     public function run()
     {
     }
 }

RemoveUnusedRequestParamRector

Remove unused $request parameter from controller action

 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;

 final class SomeController extends Controller
 {
-    public function run(Request $request, int $id)
+    public function run(int $id)
     {
         echo $id;
     }
 }

ReplaceSensioRouteAnnotationWithSymfonyRector

Replace Sensio @Route annotation with Symfony one

-use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Symfony\Component\Routing\Annotation\Route;

 final class SomeClass
 {
     /**
      * @Route()
      */
     public function run()
     {
     }
 }

ReplaceServiceArgumentRector

Replace defined service() argument in Symfony PHP config

🔧 configure it!

 use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

-return service(ContainerInterface::class);
+return service('service_container');

ResponseReturnTypeControllerActionRector

Add Response object return type to controller actions

 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\Routing\Annotation\Route;

 final class SomeController extends AbstractController
 {
     #[Route]
-    public function detail()
+    public function detail(): Response
     {
         return $this->render('some_template');
     }
 }

ResponseStatusCodeRector

Turns status code numbers to constants

 use Symfony\Component\HttpFoundation\Response;

 class SomeController
 {
     public function index()
     {
         $response = new Response();
-        $response->setStatusCode(200);
+        $response->setStatusCode(Response::HTTP_OK);

-        if ($response->getStatusCode() === 200) {
+        if ($response->getStatusCode() === Response::HTTP_OK) {
         }
     }
 }

RootNodeTreeBuilderRector

Changes TreeBuilder with root() call to constructor passed root and getRootNode() call

 use Symfony\Component\Config\Definition\Builder\TreeBuilder;

-$treeBuilder = new TreeBuilder();
-$rootNode = $treeBuilder->root('acme_root');
+$treeBuilder = new TreeBuilder('acme_root');
+$rootNode = $treeBuilder->getRootNode();
 $rootNode->someCall();

RouteCollectionBuilderToRoutingConfiguratorRector

Change RouteCollectionBuilder to RoutingConfiguratorRector

 use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
 use Symfony\Component\HttpKernel\Kernel;
-use Symfony\Component\Routing\RouteCollectionBuilder;
+use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

 final class ConcreteMicroKernel extends Kernel
 {
     use MicroKernelTrait;

-    protected function configureRoutes(RouteCollectionBuilder $routes)
+    protected function configureRouting(RoutingConfigurator $routes): void
     {
-        $routes->add('/admin', 'App\Controller\AdminController::dashboard', 'admin_dashboard');
-    }
-}
+        $routes->add('admin_dashboard', '/admin')
+            ->controller('App\Controller\AdminController::dashboard')
+    }}

ServiceArgsToServiceNamedArgRector

Converts order-dependent arguments args() to named arg() call

 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

 return static function (ContainerConfigurator $containerConfigurator): void {
     $services = $containerConfigurator->services();

     $services->set(SomeClass::class)
-        ->args(['some_value']);
+        ->arg('$someCtorParameter', 'some_value');
 };

ServiceSetStringNameToClassNameRector

Change $service->set() string names to class-type-based names, to allow $container->get() by types in Symfony 2.8. Provide XML config via $rectorConfig->symfonyContainerXml(...);

 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

 return static function (ContainerConfigurator $containerConfigurator): void {
     $services = $containerConfigurator->services();

-    $services->set('some_name', App\SomeClass::class);
+    $services->set('app\\someclass', App\SomeClass::class);
 };

ServiceSettersToSettersAutodiscoveryRector

Change $services->set(..., ...) to $services->load(..., ...) where meaningful

 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

-use App\Services\FistService;
-use App\Services\SecondService;
-
 return static function (ContainerConfigurator $containerConfigurator): void {
     $parameters = $containerConfigurator->parameters();

     $services = $containerConfigurator->services();

-    $services->set(FistService::class);
-    $services->set(SecondService::class);
+    $services->load('App\\Services\\', '../src/Services/*');
 };

ServiceTagsToDefaultsAutoconfigureRector

Change $services->set(..., ...)->tag(...) to $services->defaults()->autodiscovery() where meaningful

 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
 use App\Command\SomeCommand;

 return static function (ContainerConfigurator $containerConfigurator): void {
     $services = $containerConfigurator->services();
+    $services->defaults()
+        ->autoconfigure();

-    $services->set(SomeCommand::class)
-        ->tag('console.command');
+    $services->set(SomeCommand::class);
 };

ServicesSetNameToSetTypeRector

Change $services->set("name_type", SomeType::class) to bare type, useful since Symfony 3.4

 use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

 return static function (ContainerConfigurator $containerConfigurator): void {
     $services = $containerConfigurator->services();

-    $services->set('some_name', App\SomeClass::class);
+    $services->set(App\SomeClass::class);
 };

SignalableCommandInterfaceReturnTypeRector

Return int or false from SignalableCommandInterface::handleSignal() instead of void

-public function handleSignal(int $signal): void
+public function handleSignal(int $signal): int|false
     {
+        return false;
     }

SimpleFunctionAndFilterRector

Changes Twig_Function_Method to Twig_SimpleFunction calls in Twig_Extension.

 class SomeExtension extends Twig_Extension
 {
     public function getFunctions()
     {
         return [
-            'is_mobile' => new Twig_Function_Method($this, 'isMobile'),
+             new Twig_SimpleFunction('is_mobile', [$this, 'isMobile']),
         ];
     }

     public function getFilters()
     {
         return [
-            'is_mobile' => new Twig_Filter_Method($this, 'isMobile'),
+             new Twig_SimpleFilter('is_mobile', [$this, 'isMobile']),
         ];
     }
 }

SimplifyFormRenderingRector

Symplify form rendering by not calling ->createView() on render function

 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

 class ReplaceFormCreateViewFunctionCall extends AbstractController
 {
     public function form(): Response
     {
         return $this->render('form.html.twig', [
-            'form' => $form->createView(),
+            'form' => $form,
         ]);
     }
 }

StringExtensionToConfigBuilderRector

Add config builder classes

-use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
+use Symfony\Config\SecurityConfig;

-return static function (ContainerConfigurator $containerConfigurator): void {
-    $containerConfigurator->extension('security', [
-        'firewalls' => [
-            'dev' => [
-                'pattern' => '^/(_(profiler|wdt)|css|images|js)/',
-                'security' => false,
-            ],
-        ],
-    ]);
+return static function (SecurityConfig $securityConfig): void {
+    $securityConfig->firewall('dev')
+        ->pattern('^/(_(profiler|wdt)|css|images|js)/')
+        ->security(false);
 };

StringFormTypeToClassRector

Turns string Form Type references to their CONSTANT alternatives in FormTypes in Form in Symfony. To enable custom types, add link to your container XML dump in "$rectorConfig->symfonyContainerXml(...)"

 $formBuilder = new Symfony\Component\Form\FormBuilder;
-$formBuilder->add('name', 'form.type.text');
+$formBuilder->add('name', \Symfony\Component\Form\Extension\Core\Type\TextType::class);

StringToArrayArgumentProcessRector

Changes Process string argument to an array

 use Symfony\Component\Process\Process;
-$process = new Process('ls -l');
+$process = new Process(['ls', '-l']);

SwiftCreateMessageToNewEmailRector

Changes createMessage() into a new Symfony\Component\Mime\Email

-$email = $this->swift->createMessage('message');
+$email = new \Symfony\Component\Mime\Email();

SwiftMessageToEmailRector

Convert \Swift_Message into an \Symfony\Component\Mime\Email

-$message = (new \Swift_Message('Hello Email'))
-        ->setFrom('send@example.com')
-        ->setTo(['recipient@example.com' => 'Recipient'])
-        ->setBody(
-            $this->renderView(
-                'emails/registration.html.twig',
-                ['name' => $name]
-            ),
-            'text/html'
-        )
+$message = (new Email())
+    ->from(new Address('send@example.com'))
+    ->to(new Address('recipient@example.com', 'Recipient'))
+    ->subject('Hello Email')
+    ->html($this->renderView(
+        'emails/registration.html.twig',
+        ['name' => $name]
+    ))
+;

SwiftSetBodyToHtmlPlainMethodCallRector

Changes setBody() method call on Swift_Message into a html() or plain() based on second argument

 $message = new Swift_Message();

-$message->setBody('...', 'text/html');
+$message->html('...');

-$message->setBody('...', 'text/plain');
-$message->setBody('...');
+$message->text('...');
+$message->text('...');

TemplateAnnotationToThisRenderRector

Turns @Template annotation to explicit method call in Controller of FrameworkExtraBundle in Symfony

 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

 final class SomeController
 {
-    /**
-     * @Template()
-     */
     public function indexAction()
     {
+        return $this->render('index.html.twig');
     }
 }

TwigBundleFilesystemLoaderToTwigRector

Change TwigBundle FilesystemLoader to native one

-use Symfony\Bundle\TwigBundle\Loader\FilesystemLoader;
-use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator;
-use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
+use Twig\Loader\FilesystemLoader;

-$filesystemLoader = new FilesystemLoader(new TemplateLocator(), new TemplateParser());
-$filesystemLoader->addPath(__DIR__ . '/some-directory');
+$fileSystemLoader = new FilesystemLoader([__DIR__ . '/some-directory']);

ValidatorBuilderEnableAnnotationMappingRector

Migrates from deprecated ValidatorBuilder->enableAnnotationMapping($reader) to ValidatorBuilder->enableAnnotationMapping(true)->setDoctrineAnnotationReader($reader)

 use Doctrine\Common\Annotations\Reader;
 use Symfony\Component\Validator\ValidatorBuilder;

 class SomeClass
 {
     public function run(ValidatorBuilder $builder, Reader $reader)
     {
-        $builder->enableAnnotationMapping($reader);
+        $builder->enableAnnotationMapping(true)->setDoctrineAnnotationReader($reader);
     }
 }

VarDumperTestTraitMethodArgsRector

Adds a new $filter argument in VarDumperTestTrait->assertDumpEquals() and VarDumperTestTrait->assertDumpMatchesFormat() in Validator in Symfony.

-$varDumperTestTrait->assertDumpEquals($dump, $data, $message = "");
+$varDumperTestTrait->assertDumpEquals($dump, $data, $filter = 0, $message = "");

-$varDumperTestTrait->assertDumpMatchesFormat($dump, $data, $message = "");
+$varDumperTestTrait->assertDumpMatchesFormat($dump, $data, $filter = 0, $message = "");

WebTestCaseAssertIsSuccessfulRector

Simplify use of assertions in WebTestCase

 use PHPUnit\Framework\TestCase;

 class SomeClass extends TestCase
 {
     public function test()
     {
-        $this->assertSame(200, $this->client->getResponse()->getStatusCode());
+         $this->assertResponseIsSuccessful();
     }
 }

WebTestCaseAssertResponseCodeRector

Simplify use of assertions in WebTestCase

 use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

 final class SomeClass extends WebTestCase
 {
     public function test()
     {
-        $response = self::getClient()->getResponse();
-
-        $this->assertSame(301, $response->getStatusCode());
-        $this->assertSame('https://example.com', $response->headers->get('Location'));
+        $this->assertResponseStatusCodeSame(301);
+        $this->assertResponseRedirects('https://example.com');
     }
 }

WebTestCaseAssertSelectorTextContainsRector

Simplify use of assertions in WebTestCase to assertSelectorTextContains()

 use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
 use Symfony\Component\DomCrawler\Crawler;

 final class SomeTest extends WebTestCase
 {
     public function testContains()
     {
         $crawler = new Symfony\Component\DomCrawler\Crawler();
-        $this->assertContains('Hello World', $crawler->filter('h1')->text());
+        $this->assertSelectorTextContains('h1', 'Hello World');
     }
 }