Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Reverse Regex Laravel Package

icomefromthenet/reverse-regex

Generate sample strings from regular expressions for test data and validation. ReverseRegex parses a supported subset of regex syntax (literals, groups, character classes, quantifiers, escapes, some Unicode via \X{####}) and outputs randomized matching text via PHP generators.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Add to composer.json:

    "require": {
        "icomefromthenet/reverse-regex": "dev-master"
    }
    

    Run composer update.

  2. Basic Usage: Generate a string from a simple regex in a Laravel test or helper:

    use ReverseRegex\Lexer;
    use ReverseRegex\Random\SimpleRandom;
    use ReverseRegex\Parser;
    use ReverseRegex\Generator\Scope;
    
    $lexer = new Lexer('[a-z]{5}');
    $gen = new SimpleRandom(10007);
    $parser = new Parser($lexer, new Scope(), new Scope());
    $result = $parser->parse()->getResult()->generate('', $gen);
    // Outputs: e.g., "abcde"
    
  3. First Use Case: Replace hardcoded test data in a Laravel FeatureTest:

    public function test_form_validation() {
        $fakeInput = generateFromRegex('[a-z]{5,20}'); // Dynamic test string
        $response = $this->post('/register', ['name' => $fakeInput]);
        $response->assertValid();
    }
    

Where to Look First

  • Examples: Check the GitHub repo for real-world use cases (e.g., ausphone.php, auspostcode.php).
  • Regex Support Table: Verify if your patterns are covered (e.g., [a-z], \d, {1,5}).
  • Laravel Integration: Start with a helper function (see Implementation Patterns).

Implementation Patterns

Usage Patterns

1. Test Data Generation

  • PHPUnit Data Providers:

    public function regexProvider() {
        return [
            ['[a-z]{5}', 'abcde'],
            ['\d{10}', '1234567890'],
            ['[a-z]{3}-\d{4}', 'abc-1234'],
        ];
    }
    
    public function test_generated_data_matches_regex() {
        foreach ($this->regexProvider() as [$pattern, $expected]) {
            $generated = generateFromRegex($pattern);
            $this->assertMatchesRegularExpression($pattern, $generated);
        }
    }
    
  • Pest Test Helpers:

    beforeEach(function () {
        $this->fakeName = generateFromRegex('[A-Za-z]{5,20}');
        $this->fakeEmail = generateFromRegex('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}');
    });
    
    it('validates user input', function () {
        $response = post('/register', [
            'name' => $this->fakeName,
            'email' => $this->fakeEmail,
        ]);
        expect($response)->toBeValid();
    });
    

2. Database Seeding

Use in DatabaseSeeder to populate test data:

public function run() {
    $fakeUsers = collect(range(1, 100))->map(fn($i) => [
        'name' => generateFromRegex('[A-Za-z]{5,20}'),
        'email' => generateFromRegex('[a-z0-9._%+-]+@example\.com'),
    ]);
    User::insert($fakeUsers->toArray());
}

3. API Mocking

Generate fake payloads for API tests:

$fakePayload = [
    'phone' => generateFromRegex('04\d{8}'), // Australian mobile
    'postcode' => generateFromRegex('\d{4}'), // Australian postcode
];
$this->postJson('/api/users', $fakePayload)->assertOk();

4. Validation Edge Cases

Test regex boundaries (e.g., max/min lengths):

// Test max length (e.g., Laravel's max:5 rule)
$maxLengthString = generateFromRegex('[a-z]{5}');
$this->assertEquals(5, strlen($maxLengthString));

// Test min length (e.g., Laravel's min:3 rule)
$minLengthString = generateFromRegex('[a-z]{3}');
$this->assertEquals(3, strlen($minLengthString));

Workflows

Workflow 1: Replace Hardcoded Test Data

  • Before:
    $testEmails = ['user@example.com', 'test123@domain.com'];
    
  • After:
    $testEmails = collect(range(1, 5))->map(fn($i) =>
        generateFromRegex('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}')
    );
    

Workflow 2: Dynamic Test Data in CI

Use in GitHub Actions to generate test data for every PR:

# .github/workflows/tests.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: composer install
      - run: php artisan test -- --filter "test_dynamic_data"
// TestCase
public function test_dynamic_data() {
    $dynamicData = generateFromRegex('[a-z]{10}');
    $this->assertTrue(preg_match('/^[a-z]{10}$/', $dynamicData));
}

Workflow 3: Fuzz Testing Regex

Generate malformed inputs to break regex-based validators:

public function test_regex_fuzz() {
    $malformedInput = generateFromRegex('[a-z]{100}'); // Exceed max length
    $response = $this->post('/validate', ['input' => $malformedInput]);
    $response->assertSessionHasErrors('input');
}

Integration Tips

1. Laravel Service Container

Register the generator as a singleton:

// app/Providers/AppServiceProvider.php
public function register() {
    $this->app->singleton('regex.generator', function () {
        return new class {
            public function generate(string $pattern, int $seed = null): string {
                $lexer = new Lexer($pattern);
                $gen = new SimpleRandom($seed);
                return (new Parser($lexer, new Scope(), new Scope()))
                    ->parse()
                    ->getResult()
                    ->generate('', $gen);
            }
        };
    });
}

Use in tests:

$this->app->make('regex.generator')->generate('[a-z]{5}');

2. Custom Randomizer

Extend SimpleRandom for seeded reproducibility:

class SeededRandom extends SimpleRandom {
    public function __construct(int $seed) {
        parent::__construct($seed);
    }
}

3. Validation Wrapper

Ensure generated data matches the regex:

function assertMatchesRegex(string $pattern, string $subject): void {
    $this->assertTrue(
        preg_match($pattern, $subject),
        "Generated string '$subject' does not match pattern '$pattern'"
    );
}

4. Laravel Artisan Command

Generate bulk test data via CLI:

// app/Console/Commands/GenerateTestData.php
public function handle() {
    $count = $this->option('count') ?? 10;
    for ($i = 0; $i < $count; $i++) {
        $data = generateFromRegex('[a-z]{5}-\d{4}');
        $this->info($data);
    }
}

Run:

php artisan generate:test-data --count=50

Gotchas and Tips

Pitfalls

1. Unbounded Quantifiers

  • Issue: * or + can generate strings up to PHP_INT_MAX characters, causing memory issues or infinite loops.
  • Fix: Use explicit ranges (e.g., {1,10} instead of +).
    // Bad: Unbounded
    $lexer = new Lexer('[a-z]*'); // Risk of infinite loop
    
    // Good: Bounded
    $lexer = new Lexer('[a-z]{1,10}');
    

2. Escaping Meta-Characters

  • Issue: Forgetting to escape regex metacharacters (e.g., ., *, ?) in the input pattern.
  • Fix: Escape them manually or pre-process the string:
    function escapeRegex(string $input): string {
        return preg_replace('/[.*+?^${}()|[\]\\]/', '\\$0', $input);
    }
    $safePattern = escapeRegex('file.name.txt');
    

3. Limited Unicode Support

  • Issue: \p{} (Unicode properties) and complex grapheme clusters are
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky