DEV Community

Cover image for Automating Code Refactoring in Laravel with Rector
Nasrul Hazim Bin Mohamad
Nasrul Hazim Bin Mohamad

Posted on

Automating Code Refactoring in Laravel with Rector

Code quality and maintainability are crucial aspects of modern software development.

In this post, I’ll show you how to set up Rector for automating code refactoring in a Laravel project, combined with a streamlined CI/CD workflow using GitHub Actions.

With Rector, you can continuously refactor and upgrade your codebase while adhering to best practices. Let’s dive in!


What is Rector?

Rector is a powerful PHP refactoring tool that automates tedious upgrades and code-quality improvements.

Whether you’re migrating to a new PHP version, upgrading your Laravel framework, or ensuring your code meets modern standards, Rector simplifies these tasks with minimal manual effort.


Support my mission to empower the developer community by sponsoring my work—your contributions help me build and share valuable tools, insights, and resources: Learn more here.


Why Use Rector in Your Laravel Project?

  1. Automates Upgrades: Keep your codebase compatible with the latest Laravel or PHP versions.
  2. Improves Code Quality: Applies rules to clean up and optimize your code automatically.
  3. Saves Time: Refactors code in minutes, letting developers focus on business logic.

Setting Up Rector in Your Laravel Project

Step 1: Install Rector and Laravel-Specific Rules

Install Rector and its Laravel extension using Composer:

composer require rector/rector --dev
composer require driftingly/rector-laravel --dev
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure Rector

Create a rector.php configuration file in your project root if it’s not already present. Below is an example configuration tailored for Laravel projects:

<?php

declare(strict_types=1);

use Rector\Caching\ValueObject\Storage\FileCacheStorage;
use Rector\CodeQuality\Rector\FuncCall\CompactToVariablesRector;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;
use Rector\ValueObject\PhpVersion;
use RectorLaravel\Set\LaravelLevelSetList;

return static function (RectorConfig $rectorConfig): void {
    // Paths to analyze
    $rectorConfig->paths([
        __DIR__.'/app',
        __DIR__.'/config',
        __DIR__.'/database',
        __DIR__.'/resources',
        __DIR__.'/routes',
        __DIR__.'/tests',
    ]);

    // Skip specific rules
    $rectorConfig->skip([
        CompactToVariablesRector::class,
    ]);

    // Enable caching for Rector
    $rectorConfig->cacheDirectory(__DIR__.'/storage/rector');
    $rectorConfig->cacheClass(FileCacheStorage::class);

    // Apply sets for Laravel and general code quality
    $rectorConfig->sets([
        LaravelLevelSetList::UP_TO_LARAVEL_110,
        SetList::CODE_QUALITY,
    ]);

    // Define PHP version for Rector
    $rectorConfig->phpVersion(PhpVersion::PHP_83);
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Test Rector Locally

Run Rector locally to ensure everything is configured properly:

vendor/bin/rector process --dry-run --ansi
Enter fullscreen mode Exit fullscreen mode

The --dry-run flag previews the changes without modifying the files.

Here are an example of changes when rector executed.


Automating Rector with GitHub Actions

To keep your Laravel codebase refactored and up-to-date automatically, let’s set up a GitHub Actions workflow.

Step 1: Create a GitHub Workflow File

Add a .github/workflows/rector.yml file to your repository:

name: Rector CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - '*'

jobs:
  rector:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Set up PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: 8.3
        extensions: mbstring, xml, tokenizer, curl, json
        tools: composer
        coverage: none

    - name: Cache Composer dependencies
      uses: actions/cache@v3
      with:
        path: vendor
        key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
        restore-keys: ${{ runner.os }}-composer-

    - name: Install dependencies
      run: composer install --no-progress --no-suggest --prefer-dist

    - name: Cache Rector cache
      uses: actions/cache@v3
      with:
        path: storage/rector
        key: ${{ runner.os }}-rector-${{ hashFiles('**/rector.php') }}
        restore-keys: ${{ runner.os }}-rector-

    - name: Run Rector
      run: |
        vendor/bin/rector process --ansi

    - name: Validate Rector changes
      run: |
        git diff --exit-code
Enter fullscreen mode Exit fullscreen mode

Step 2: Explanation of the Workflow

  1. Triggers:

    • Runs on pushes to the main branch and on pull requests.
  2. Steps:

    • PHP Setup: Prepares a PHP environment with Laravel-required extensions.
    • Dependency Caching: Speeds up builds by caching vendor and Rector cache.
    • Rector Execution: Runs Rector to refactor the codebase.
    • Validation: Ensures no unexpected changes remain uncommitted.

Step 3: Monitor CI Runs

Every time a pull request is created or updated, the workflow will:

  1. Refactor code.
  2. Warn about changes if they are uncommitted.

Support my mission to empower the developer community by sponsoring my work—your contributions help me build and share valuable tools, insights, and resources: Learn more here.


Conclusion

With Rector and GitHub Actions, your Laravel project stays modern, clean, and maintainable. This automated setup saves hours of manual refactoring, keeping your codebase aligned with the latest standards. Ready to implement Rector in your project? Let me know how it goes, or feel free to share your experience!

Happy coding! 🚀


Photo by Milad Fakurian on Unsplash

Top comments (0)