niklongstone/regex-reverse
Generate random strings that match a given PCRE-style regex. Supports common character classes (\d, \w, \s), ranges, groups, alternation, and quantifiers (*, +, ?, {n,m}). Simple API: RegRev::generate($pattern).
Installation
composer require niklongstone/regex-reverse
Requires PHP 5.3+ (though modern Laravel 8+ projects use PHP 8.x). Note: Test thoroughly in PHP 8.x due to legacy codebase.
Basic Usage (Updated for 0.4.0)
use Niklongstone\RegexReverse\RegexReverse;
$reverser = new RegexReverse();
$regex = '/^a(b|c)+d$/'; // Now supports alternation (b|c)
$matchingString = $reverser->reverse($regex);
echo $matchingString; // Outputs: "abcd" or "acd" (respects alternation)
// New: Not-in-range support
$regexWithNegation = '/^[^0-9]+$/'; // Matches strings without digits
$matchingString = $reverser->reverse($regexWithNegation);
First Use Case (Updated) Generate test data for unit tests with alternation and negation:
$testString = $reverser->reverse('/^(user|admin)_\d{3}_[a-z]{2}$/');
// Returns "user_123_ab" or "admin_456_cd" (respects alternation)
$noDigitsString = $reverser->reverse('/^[^0-9]{5,10}$/');
// Returns a string like "abcde" (no digits)
Test Data Generation with Alternation
public function testUsernameValidation()
{
$fakeUsername = (new RegexReverse())->reverse('/^(dev|test|admin)_\w{3,}$/');
$this->assertMatchesRegularExpression('/^(dev|test|admin)_\w{3,}$/', $fakeUsername);
}
Dynamic Regex Handling with Negation
public function generateNoDigitsString(string $pattern): string
{
return (new RegexReverse())->reverse('/^[^0-9]{' . $pattern . '}$/');
}
Integration with Laravel Testing (Updated)
use Illuminate\Support\Facades\Validator;
$validator = Validator::make([
'input' => (new RegexReverse())->reverse('/^[A-Z]{2}-[^a-z]+$/')
], [
'input' => 'regex:/^[A-Z]{2}-[^a-z]+$/' // Tests uppercase + non-lowercase
]);
$this->assertTrue($validator->passes());
Customize Output Length with Negation
$reverser = new RegexReverse();
$reverser->setMinLength(10);
$reverser->setMaxLength(20);
$noDigitsString = $reverser->reverse('/^[^0-9]{10,20}$/');
Seed Database with Valid Data (Alternation Example)
foreach (range(1, 5) as $i) {
$validSlug = $reverser->reverse('/^(blog|news|docs)_\w{3,}$/');
DB::table('posts')->insert(['slug' => $validSlug]);
}
Deprecated Package (Still Applies)
|) and negation ([^...]) thoroughly, as these are newer features.Edge Cases (Expanded)
/^(a|b|c){5,}$/ may produce unexpected combinations (e.g., "abacb")./^[^0-9]{3,}$/ works, but nested negations (e.g., /^[^a-[^e]]$/) may fail./^(a|b){2,3}[^c]{1,}$/ could yield edge cases like "aabd" or "bbb".Non-Deterministic Output (Still Applies)
/^(x|y)+z/ could yield "xz", "yz", or "xyyz").Validate Output (Include Negation/Alternation)
$string = $reverser->reverse('/^[^0-9]{3,}|[A-Z]{2,}$/');
if (!preg_match('/^[^0-9]{3,}|[A-Z]{2,}$/', $string)) {
throw new \RuntimeException("Generated string doesn't match regex!");
}
Fallback for Failing Regex (Updated)
try {
$string = $reverser->reverse('/^(invalid|pattern)$/');
} catch (\Exception $e) {
// Fallback: Generate a hardcoded valid string
$string = 'valid_fallback';
}
Override Default Behavior (Add Negation/Alternation Logic)
class CustomRegexReverser extends RegexReverse {
protected function generateString($pattern) {
if (str_contains($pattern, '[^')) {
// Custom logic for negation
return 'custom_no_digits_string';
}
// ... rest of logic
}
}
Combine with Faker (Negation Example)
use Faker\Factory as Faker;
$faker = Faker::create();
$regex = '/^[^0-9]{5,10}$/';
$validString = $reverser->reverse($regex);
// Alternative: Use Faker's `regexify` if supported (but test compatibility)
Laravel Service Provider Binding (No Change)
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->singleton(RegexReverse::class, function () {
return new RegexReverse();
});
}
Then inject via constructor:
public function __construct(private RegexReverse $reverser) {}
Key Additions for 0.4.0:
|) for regex groups (e.g., /^(a|b)+$/).[^...]) for excluding character ranges.How can I help you explore Laravel packages today?