Find the best Rector rule to solve your problem. Searching through 1009 rules.
Found 101 rules:
Rename copy_on_windows option to follow_symlinks in Filesystem::mirror()
use Symfony\Component\Filesystem\Filesystem;
final class Foo
{
public function __construct(private Filesystem $filesystem) {}
public function bar($originDir, $targetDir): void
{
- $this->filesystem->mirror(targetDir: $originDir, originDir: $targetDir, options: $options = ['copy_on_windows' => true]);
+ $this->filesystem->mirror(targetDir: $originDir, originDir: $targetDir, options: $options = ['follow_symlinks' => true]);
}
}
Migrate deprecated ConstraintValidatorInterface::validate() in ConstraintValidatorTestCase tests to $this->validate(), otherwise to validateInContext() (Symfony 8.1+).
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
final class SomeValidatorTest extends ConstraintValidatorTestCase
{
public function test(): void
{
- $this->validator->validate($value, $constraint);
+ $this->validate($value, $constraint);
}
}
Add $format argument to Ulid::isValid()
Symfony\Component\Uid\Ulid;
final class Foo
{
public function bar(string $id): bool
{
- return Ulid::isValid($id);
+ return Ulid::isValid($id, Symfony\Component\Uid\Ulid::FORMAT_BASE_32);
}
}
Remove unused $eraseCredentials argument from AuthenticatorManager constructor
use Symfony\Component\Security\Http\Authentication\AuthenticatorManager;
final class Foo
{
public function bar(): void
{
new AuthenticatorManager(
$authenticators,
$tokenStorage,
$eventDispatcher,
$firewallName,
- true
);
}
}
Remove unused UserInterface::eraseCredentials() method, make it part of serialize if needed
use Symfony\Component\Security\Core\User\UserInterface;
final class User implements UserInterface
{
- public function eraseCredentials()
- {
- // some logic here
- }
}
Replaces AuthorizationCheckerInterface with AccessDecisionManagerInterface inside Symfony Voters
-use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
+use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
final class AuthorizationCheckerVoter extends Voter
{
public function __construct(
- private AuthorizationCheckerInterface $authorizationChecker
+ private AccessDecisionManagerInterface $accessDecisionManager
) {}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
- return $this->authorizationChecker->isGranted('ROLE_ADMIN', $subject);
+ return $this->accessDecisionManager->decide($token, ['ROLE_ADMIN'], $subject);
}
}
Replace getDefaultName() and getDefaultDescription() by #[AsCommand] attribute
+use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
+#[AsCommand(
+ name: 'app:some-command',
+ description: 'This is some command description'
+)]
final class SomeCommand extends Command
{
- public static function getDefaultName(): string
- {
- return 'app:some-command';
- }
-
- public static function getDefaultDescription(): string
- {
- return 'This is some command description';
- }
}
Moves $this->setHelp() to the "help" named argument of #[AsCommand]
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
-#[AsCommand(name: 'app:some')]
+#[AsCommand(name: 'app:some', help: <<<'TXT'
+Some help text
+TXT)]
final class SomeCommand extends Command
{
- protected function configure(): void
- {
- $this->setHelp('Some help text');
- }
}
Refactor Symfony constraints using array options to named arguments syntax for better readability and type safety.
use Symfony\Component\Validator\Constraints\NotBlank;
-$constraint = new NotBlank(['message' => 'This field should not be blank.']);
+$constraint = new NotBlank(message: 'This field should not be blank.');
Adds a new $voter argument in protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?Vote $vote = null): bool
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
final class MyVoter extends Voter
{
protected function supports(string $attribute, mixed $subject): bool
{
return true;
}
- protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
+ protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
return true;
}
}
Change Symfony Command with execute() + configure() to __invoke() with attributes
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Argument;
+use Symfony\Component\Console\Option;
#[AsCommand(name: 'some_name')]
-final class SomeCommand extends Command
+final class SomeCommand
{
- public function configure()
- {
- $this->addArgument('argument', InputArgument::REQUIRED, 'Argument description');
- $this->addOption('option', 'o', InputOption::VALUE_NONE, 'Option description');
- }
-
- public function execute(InputInterface $input, OutputInterface $output)
- {
- $someArgument = $input->getArgument('argument');
- $someOption = $input->getOption('option');
+ public function __invoke(
+ #[Argument(name: 'argument', description: 'Argument description')]
+ string $argument,
+ #[Option(name: 'option', shortcut: 'o', mode: Option::VALUE_NONE, description: 'Option description')]
+ bool $option = false,
+ ) {
+ $someArgument = $argument;
+ $someOption = $option;
// ...
return Command::SUCCESS;
}
}
Move push(request) to "Symfony\Component\HttpFoundation\RequestStack" constructor
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use PHPUnit\Framework\TestCase;
-final class SomeClass extends TestCase
+class SomeClass extends TestCase
{
public function run()
{
- $requestStack = new RequestStack();
$request = new Request();
- $requestStack->push($request);
+ $requestStack = new RequestStack([$request]);
}
}
Make param/env use in #[Attribute] more precise
namespace App\Service;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
class MessageGenerator
{
public function __construct(
- #[Autowire('%kernel.debug%')]
+ #[Autowire(param: 'kernel.debug')]
bool $debugMode,
- #[Autowire('%env(SOME_ENV_VAR)%')]
+ #[Autowire(env: 'SOME_ENV_VAR')]
string $senderName,
) {
}
}
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;
}
Replaces #[Security] framework-bundle attribute with Symfony native #[IsGranted] one
-use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
+use Symfony\Component\ExpressionLanguage\Expression;
+use Symfony\Component\Security\Http\Attribute\IsGranted;
class PostController extends Controller
{
- #[Security("is_granted('ROLE_ADMIN')")]
+ #[IsGranted(attribute: 'ROLE_ADMIN')]
public function index()
{
}
- #[Security("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')")]
+ #[IsGranted(attribute: new Expression("is_granted('ROLE_ADMIN') and is_granted('ROLE_FRIENDLY_USER')"))]
public function list()
{
}
}
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!
}
}
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',
- ];
}
}
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
) {
}
}
Replaces ArgumentValueResolverInterface by ValueResolverInterface with supports logic moved to resolve() method
-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
{
}
}
Narrow #[Security] attribute with inner single "is_granted/has_role" condition string to #[IsGranted] attribute
-use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
+use Symfony\Component\Security\Http\Attribute\IsGranted;
-#[Security("is_granted('ROLE_USER')")]
+#[IsGranted('ROLE_USER')]
class SomeClass
{
}
Split #[Security] attribute with "and" condition string to multiple #[IsGranted] attributes with sole values
-use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
+use Symfony\Component\Security\Http\Attribute\IsGranted;
-#[Security("is_granted('ROLE_USER') and has_role('ROLE_ADMIN')")]
+#[IsGranted('ROLE_USER')]
+#[IsGranted('ROLE_ADMIN')]
class SomeClass
{
}
Replace regex string in #[Route] requirements with a Requirement constant
use Symfony\Component\Routing\Attribute\Route;
+use Symfony\Component\Routing\Requirement\Requirement;
final class SomeController
{
#[Route('/detail/{id}', requirements: [
- 'id' => '[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}',
+ 'id' => Requirement::UUID_V4,
])]
public function detail()
{
}
}
Turns old Constraint::$errorNames properties to use Constraint::ERROR_NAMES instead
use Symfony\Component\Validator\Constraints\NotBlank;
class SomeClass
{
- NotBlank::$errorNames
+ NotBlank::ERROR_NAMES
}
Add Symfony\Component\Console\Attribute\AsCommand to Symfony Commands from configure()
+use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
+#[AsCommand(name: 'sunshine', description: 'Some description')]
final class SunshineCommand extends Command
{
- public function configure()
- {
- $this->setName('sunshine');
- $this->setDescription('Some description');
-
- }
}
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;
}
}
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(name: 'sunshine', description: 'some description')]
final class SunshineCommand extends Command
{
- public static $defaultName = 'sunshine';
-
- public static $defaultDescription = 'some description';
}
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);
}
}
Replace removed ContainerInterface alias with "service_container" service id in service() call
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
-return service(ContainerInterface::class);
+return service('service_container');
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();
}
}
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);
}
}
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,
]);
}
}
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);
}
}
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()));
}
}
Change deprecated BinaryFileResponse::create() to use __construct() instead
use Symfony\Component\HttpFoundation;
class SomeClass
{
public function run()
{
- $binaryFile = BinaryFileResponse::create();
+ $binaryFile = new BinaryFileResponse(null);
}
}
Changes first argument of PropertyAccessor::__construct() to flags from boolean
use Symfony\Component\PropertyAccess\PropertyAccessor;
class SomeClass
{
public function run()
{
- $propertyAccessor = new PropertyAccessor(true);
+ $propertyAccessor = new PropertyAccessor(PropertyAccessor::MAGIC_CALL | PropertyAccessor::MAGIC_GET | PropertyAccessor::MAGIC_SET);
}
}
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());
}
}
Move metadata from loadValidatorMetadata() to property/getter/class attributes
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.',
- ]));
- }
}
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'],
+ ];
}
}
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]],
+ ];
}
}
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')
+ }}
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;
}
}
Change $this->authorizationChecker->isGranted([$a, $b]) to $this->authorizationChecker->isGranted($a) || $this->authorizationChecker->isGranted($b), also updates AbstractController usages
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
final class SomeController
{
public function __construct(
private AuthorizationCheckerInterface $authorizationChecker
) {
}
public function hasAccess(): bool
{
- if ($this->authorizationChecker->isGranted(['ROLE_USER', 'ROLE_ADMIN'])) {
+ if ($this->authorizationChecker->isGranted('ROLE_USER') || $this->authorizationChecker->isGranted('ROLE_ADMIN')) {
return true;
}
return false;
}
}
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;
}
}
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');
}
}
Change Twig template short name to bundle syntax in render calls from controllers
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class BaseController extends Controller
{
function indexAction()
{
- $this->render('appBundle:Landing\Main:index.html.twig');
+ $this->render('@app/Landing/Main/index.html.twig');
}
}
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();
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']);
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();
}
}
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();
Changes Process string argument to an array
use Symfony\Component\Process\Process;
-$process = new Process('ls -l');
+$process = new Process(['ls', '-l']);
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 = "");
Adds $form->isSubmitted() validation to all $form->isValid() calls in Form in Symfony
-if ($form->isValid()) {
+if ($form->isSubmitted() && $form->isValid()) {
// ...
}
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);
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]);
Changes getFilters(), getFunctions() and getTests() in TwigExtension to #[AsTwigFilter], #[AsTwigFunction] and #[AsTwigTest] marker attributes above local class methods
-use Twig\Extension\AbstractExtension;
+use Twig\Attribute\AsTwigFilter;
+use Twig\Attribute\AsTwigFunction;
use Twig\Environment;
-class SomeClass extends AbstractExtension
+class SomeClass
{
- public function getFilters()
- {
- return [
- new \Twig\TwigFilter('filter_name', [$this, 'localMethod'], ['needs_environment' => true]),
- ];
- }
-
- public function getFunctions()
- {
- return [
- new \Twig\TwigFunction('function_name', [$this, 'localMethod'], ['needs_environment' => true]),
- ];
- }
-
+ #[AsTwigFilter(name: 'filter_name', needsEnvironment: true)]
+ #[AsTwigFunction(name: 'function_name', needsEnvironment: true)]
public function localMethod(Environment $env, $value)
{
return $value;
}
}
Changes @Accessor annotation to #[Accessor] attribute with specific "getter" or "setter" keys
use JMS\Serializer\Annotation\Accessor;
class User
{
- /**
- * @Accessor("getValue")
- */
+ #[Accessor(getter: 'getValue')]
private $value;
}
Changes @AccessType annotation to #[AccessType] attribute with specific key
use JMS\Serializer\Annotation\AccessType;
-/** @AccessType("public_method") */
+#[AccessType(values: ['public_method'])]
class User
{
}
Change $container->get("some_name") in tests 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);
}
}
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)
{
}
}
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()
{
}
}
Remove service from Sensio @Route
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
final class SomeClass
{
/**
- * @Route(service="some_service")
+ * @Route()
*/
public function run()
{
}
}
Turns old event name with EXCEPTION to ERROR constant in Console in Symfony
-"console.exception"
+RectorPrefix202608\Symfony\Component\Console\ConsoleEvents::ERROR
Turns old option names to new ones in FormTypes in Form in Symfony
use Symfony\Component\Form\FormBuilder;
$formBuilder = new FormBuilder;
-$formBuilder->add("...", ["precision" => "...", "virtual" => "..."];
+$formBuilder->add("...", ["scale" => "...", "inherit_data" => "..."];
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);
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,
]);
}
}
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);
}
}
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]]);
}
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;
}
}
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;
}
}
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'));
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],
]);
}
}
Turns redirect to route to short helper method in Controller in Symfony
-$this->redirect($this->generateUrl("homepage"));
+$this->redirectToRoute("homepage");
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)
{
- return $this->getRequest()->getContent();
+ return $request->getContent();
}
}
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();
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],
]);
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']),
];
}
}
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');
+ }
}
Enable "framework.validation.enable_attributes" config, to load validation rules from attributes
$container->loadFromExtension('framework', [
'validation' => [
- 'enable_attributes' => false,
+ 'enable_attributes' => true,
],
]);
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');
};
Merge name === type service registration, $services->set(SomeType::class, SomeType::class)
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
- $services->set(\App\SomeClass::class, \App\SomeClass::class);
+ $services->set(\App\SomeClass::class);
};
Remove service that is passed as arg, but already autowired via constructor
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->defaults()
->autowire();
- $services->set(\App\SomeClass::class)
- ->arg('$someService', ref(\App\SomeService::class));
+ $services->set(\App\SomeClass::class);
};
final class SomeClass
{
public function __construct(private SomeService $someService)
{
}
}
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);
};
Instead of per service public() call, use it once in $services->defaults()->public()
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
- $services->set(SomeCommand::class)
- ->public();
+ $services->defaults()->public();
- $services->set(AnotherCommand::class)
- ->public();
-
- $services->set(NextCommand::class)
- ->public();
+ $services->set(SomeCommand::class);
+ $services->set(AnotherCommand::class);
+ $services->set(NextCommand::class);
};
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);
};
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/*');
};
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);
}
}
Cast responses in PHPUnit assert message to string, as required by PHPUnit
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(), $response->getContent());
+ $this->assertSame(200, $response->getStatusCode(), (string) $response->getContent());
}
}
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());
}
}
Make use of specific ParameterBag::get*() method with native return type declaration
use Symfony\Component\HttpFoundation\Request;
class SomeClass
{
public function run(Request $request)
{
- $debug = (bool) $request->query->get('debug', false);
+ $debug = $request->query->getBoolean('debug');
}
}
Add trait getter return type based on setter with @required annotation or #[\Symfony\Contracts\Service\Attribute\Required] attribute
use stdClass;
trait SomeTrait
{
private $service;
- public function getService()
+ public function getService(): stdClass
{
return $this->service;
}
/**
* @required
*/
public function setService(stdClass $stdClass)
{
$this->stdClass = $stdClass;
}
}
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) {
}
}
}
Turns status code numbers to constants
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernel;
class SomeController
{
public function index(Request $request): bool
{
- return $request->getRequestType() === HttpKernel::MASTER_REQUEST;
+ return $request->isMasterRequestType();
}
}
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
{
- public function methodToBeCalled()
+ /**
+ * @return string[]
+ */
+ public static function getSubscribedEvents(): array
{
+ return ['some_event' => 'methodToBeCalled'];
}
-}
-// in config.yaml
-services:
- SomeListener:
- tags:
- - { name: kernel.event_listener, event: 'some_event', method: 'methodToBeCalled' }
+ public function methodToBeCalled()
+ {
+ }
+}
Inline class route prefix to all method routes, to make single explicit source for route paths
use Symfony\Component\Routing\Annotation\Route;
/**
- * @Route("/api", name="api_")
+ * @Route(name="api_")
*/
class SomeController
{
/**
- * @Route("/action")
+ * @Route("/api/action")
*/
public function action()
{
}
}
Event subscriber methods hooked in getSubscribedEvents() must return void, as the event is passed by reference and returning it has no effect
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\Event;
final class SomeEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return ['some_event' => 'onEvent'];
}
- public function onEvent(Event $event): Event
+ public function onEvent(Event $event): void
{
- return $event->setSomething('value');
+ $event->setSomething('value');
}
}
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;
}
}
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)
{
}
}
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');
}
}
From $container->get(SomeType::class) in controllers to constructor injection (step 1/x)
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
final class SomeCommand extends Controller
{
+ public function __construct(private SomeType $someType)
+ {
+ }
+
public function someMethod()
{
- $someType = $this->get(SomeType::class);
+ $someType = $this->someType;
}
}
Converts typical Symfony services like $this->get("validator") in commands/controllers to constructor injection (step 3/x)
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\Validator\Validator\ValidatorInterface;
final class SomeController extends Controller
{
+ public function __construct(private ValidatorInterface $validator)
+
public function someMethod()
{
- $someType = $this->get('validator');
+ $someType = $this->validator;
}
}
From $container->get(SomeType::class) in commands to constructor injection (step 2/x)
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
final class SomeCommand extends ContainerAwareCommand
{
+ public function __construct(private SomeType $someType)
+ {
+ }
+
public function someMethod()
{
- $someType = $this->get(SomeType::class);
+ $someType = $this->someType;
}
}