DEV Community

Peter Fox
Peter Fox

Posted on • Originally published at Medium on

Fix your Type Hints with Configurable Rules and PHP Rector


Photo by Conny Schneider on Unsplash

Making your own rules to work with Rector PHP can be a bit of a learning curve. That said we don’t have to create new rules to have a big impact on our code. Some rules in the Rector ecosystem can even be configured to make our code base better with minimal effort, you’ll begin to wonder how you could have ever lived without it.

Swapping out a Class Type hint for another

In this article I’m going to show you with one rule how you can fix a ridiculously common problem when using the PHP Package Carbon. Carbon is kind of the defacto Date Time library for the PHP language.

Now most people will instantly type hint everything in their applications as \Carbon\Carbon because that’s the class type. It’s how you create instances most of the time, it’s also the main type. If you didn’t know though there is also \Carbon\CarbonImmutable which is also a class type but both behave differently. I won’t get into the whole different of mutable and immutable, googling it will help you understand that better. The point is you might want to swap between Carbon and CarbonImmutable at some point in the future as often CarbonImmutable is less problematic.

So let’s now look at how we can swap between the two versions using Rector. Please note I won’t explain how to setup Rector here. I have another article for that.

We’ll add the RenameClassRector rule to our Rector config. Rather than use the withRules() method we’ll instead use the withConfiguredRule() method. This allows us to supply an array to the rule, specifying the fully qualified names that we want to find and what to replace it with. We can see how that comes together in the config file below.

// rector.php
<?php

use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\Name\RenameClassRector;

return RectorConfig::configure()
    ->withConfiguredRule(RenameClassRector::class, [
        'Carbon\\Carbon' => 'Carbon\\CarbonImmutable',
    ]);
Enter fullscreen mode Exit fullscreen mode

Then once we’ve run the rector command we can see what’s been affected. Hopefully you have an output that’s updated all instances. This is great! But actually, we can improve this.

-function now(): \Carbon\Carbon
+function now(): \Carbon\CarbonImmutable
{
- return new \Carbon\Carbon();
+ return new \Carbon\CarbonImmutable();
}
Enter fullscreen mode Exit fullscreen mode

Swapping out a Class Type hint for an Interface

If you know the Carbon package well enough there’s actually a \Carbon\CarbonInterface and both \Carbon\Carbon and \Carbon\CarbonImmutable implement this. Well we can actually use this rule with interfaces as well.

// rector.php
<?php

use Rector\Config\RectorConfig;
use Rector\Renaming\Rector\Name\RenameClassRector;

return RectorConfig::configure()
    ->withConfiguredRule(RenameClassRector::class, [
        'Carbon\\Carbon' => 'Carbon\\CarbonInterface',
        'Carbon\\CarbonImmutable' => 'Carbon\\CarbonInterface',
    ]);
Enter fullscreen mode Exit fullscreen mode

The RenameClassRector rule is actually incredibly clever and will only update the parts that can be changed to an interface. For instance, no name changes should occur with the new keyword.

Again we can run the Rector command and hopefully it all works as expected.

-function now(): \Carbon\Carbon
+function now(): \Carbon\CarbonInterface
{
    return new \Carbon\Carbon();
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In conclusion, configuring rules with PHP Rector provides a powerful and efficient way to manage type hints and other code transformations in your project. By leveraging configurable rules like RenameClassRector, you can seamlessly swap out class type hints, or even replace them with interfaces, all with minimal effort. This not only improves your codebase’s flexibility but also ensures consistency across your project. Adding Rector to your Continuous Integration setup with these rules can have a huge impact on your development styles.

If you want to see more configurable rules I suggest looking at the Type Declaration at getrector.com.

I’m Peter Fox, a software developer in the UK who works with Laravel. Thank you for reading my article, I’ve got many more to read at https://articles.peterfox.me. I’m also now Sponsorable on GitHub. If you’d like to encourage me to write more articles like this please do consider dropping a small one-off donation.

Top comments (0)