Switch from deprecated --set
option to rector.php
config.
Rector is a PHP tool that handles 2 things: instant upgrades and architecture refactorings.
What exactly Rector does and how does it work?
Read also:
Rector is a PHP CLI tool build on Symfony Components that changes your PHP code for better. It only does what you tell it to do. You can use it to instantly upgrade your application or to do architecture refactorings once for the whole codebase.
Rector won't do your job. It's here to do the boring stuff for you. Its help is similar to coding standard tools' help with code reviews - move focus from spaces and commas to architecture of the code.
You can find it on Github. It has now 6 contributors in total. I want to thank young talented PHP developer Gabriel Caruso from Brazil for his great contributions since December 2017 that pushed Rector to a brand new level.
I'll show examples on Symfony, because that's the framework I know and love the best.
Let's say you have a project on Symfony 2.7. And you have a huge service.yml
. You know that Symfony 2.8/3.0 brought an awesome autowiring feature that evolved to pure awesomenes in Symfony 3.3 and PSR-4 services feature.
Would you prefer to do this upgrade manually? No? Use Rector instead:
composer require rector/rector --dev
rector.php
vendor/bin/rector init
use Rector\Symfony\Set\SymfonySetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(SymfonySetList::SYMFONY_33);
};
/src
directory:vendor/bin/rector process src
That's it!
The great task Rector can handle is to architecture refactorings. Your code might use a framework, but that's just 50 % of the code. The other 50 % is up to you, how you decide to use it - I mean static calls, services locators, facades over dependency injections etc.
I've seen many applications built on Symfony that used very interesting patterns:
class LoggingEventSubscriber implements EventSubscriberInterface
{
public function setController($controller)
{
$this->controller = $controller;
}
public function process()
{
$logger = $this->controller->get('logger');
$logger->log('it happened!');
}
}
Let's say you'd like to remove all $this->get('logger')
and replace them with dependency injection of LoggerInterface
type. It's not strictly coupled to the Symfony (both Nette and Laravel allows this in some version) but you want to change this in the whole application.
From this:
class LectureController extends BaseController
{
public function listAction()
{
$logger = $this->get('logger');
$logger->log('it happened!');
}
}
To this:
class LectureController extends BaseController
{
/**
* @var LoggerInterface
*/
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function listAction()
{
$this->logger->log('it happened!');
}
}
Rector can handle it for you.
Do you use Laravel and want to move from facades to constructor injection? Rector can help you.
Rector parses the code to AST thanks to PHP superman nikic's php-parser.
Then it finds specific places in the code, e.g. all variables that contain Symfony\Component\HttpFoundation\Request
type and call isMethodSafe()
method.
Then it changes it into isMethodCacheable()
(see UPGRADE-4.0.md).
Such a configuration looks like this (as shown in README
):
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [
new MethodCallRename('Symfony\Component\HttpFoundation\Request', 'isMethodSafe', 'isMethodCacheable')
]);
};
Rector is not the only tool that uses nikic\php-parser
for context-aware operation on your code.
You've probably heard of PHPStan. But unfortunately it's read-only for deterministic cases = when 1 error has exactly 1 possible solution.
Another static analysis tool - vimeo/psalm by Matthew Brown, which fixes such code. Great job Matthew!
This setup and forget approach is so addictive, that Google must have it too, right?
And it does! I found 4-page case study Large-Scale Automated Refactoring Using ClangMR, that was presented by Hyrum Wright on CppCon2014 in 57 minutes. Hyrum doesn't work at Google anymore (as he wrote me), yet I still love his detailed and practical talk.
I'm still amazed by how their approach is 90% similar to Rector, just for C++.
Happy coding!
Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!