PHPackages                             vincentvanwijk/fluent-regex - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. vincentvanwijk/fluent-regex

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

vincentvanwijk/fluent-regex
===========================

A package to fluently create regular expressions

v0.1.0(4mo ago)791[2 PRs](https://github.com/VincentVanWijk/fluent-regex/pulls)MITPHPPHP ^8.1CI failing

Since Mar 16Pushed 4mo ago2 watchersCompare

[ Source](https://github.com/VincentVanWijk/fluent-regex)[ Packagist](https://packagist.org/packages/vincentvanwijk/fluent-regex)[ Docs](https://github.com/vincentvanwijk/fluent-regex)[ RSS](/packages/vincentvanwijk-fluent-regex/feed)WikiDiscussions main Synced today

READMEChangelog (3)Dependencies (13)Versions (7)Used By (0)

Fluent Regex
============

[](#fluent-regex)

A powerful Laravel package that provides an elegant, fluent interface for building regular expressions in PHP. Say goodbye to cryptic regex syntax and hello to readable, maintainable pattern matching.

[![Latest Version on Packagist](https://camo.githubusercontent.com/0f91387ee1d71c3e9d34e6f5c8f7d85a04b1e3c58d2a48da4f36f99af36212d6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f76696e63656e7476616e77696a6b2f666c75656e742d72656765782e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vincentvanwijk/fluent-regex)[![GitHub Tests Action Status](https://camo.githubusercontent.com/5df8ee8850d8e721b8d3b24d3da40a543323f76f3a8f59a5eed615e99d919aba/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f76696e63656e7476616e77696a6b2f666c75656e742d72656765782f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/vincentvanwijk/fluent-regex/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/eadc185969a2f94011ba1e2e24f5a263a7974c46bad5729d8d76ba126e598317/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f76696e63656e7476616e77696a6b2f666c75656e742d72656765782f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/vincentvanwijk/fluent-regex/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![PHPStan](https://github.com/VincentVanWijk/fluent-regex/actions/workflows/phpstan.yml/badge.svg)](https://github.com/VincentVanWijk/fluent-regex/actions/workflows/phpstan.yml)[![codecov](https://camo.githubusercontent.com/8a074e5dc2d65d32da0716e60fb526c46f349da23d5943d2bf3caeaa5840571a/68747470733a2f2f636f6465636f762e696f2f67682f56696e63656e7456616e57696a6b2f666c75656e742d72656765782f6272616e63682f6d61696e2f67726170682f62616467652e737667)](https://codecov.io/gh/VincentVanWijk/fluent-regex)[![Total Downloads](https://camo.githubusercontent.com/72397442d9e4b114900b25ffc39fed6d67886ae805808db82c57588fe638e9e0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f76696e63656e7476616e77696a6b2f666c75656e742d72656765782e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vincentvanwijk/fluent-regex)

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Documentation](#documentation)
    - [Character Matching](#character-matching)
    - [Quantifiers](#quantifiers)
    - [Anchors &amp; Boundaries](#anchors--boundaries)
    - [Groups &amp; Captures](#groups--captures)
    - [Backreferences](#backreferences)
    - [Lookahead &amp; Lookbehind](#lookahead--lookbehind)
    - [Character Classes](#character-classes)
    - [Special Characters &amp; Tokens](#special-characters--tokens)
    - [Mode Modifiers](#mode-modifiers)
    - [Substitution &amp; Replacement](#substitution--replacement)
- [Modifiers](#modifiers)
- [Configuration](#configuration)
- [Advanced Usage](#advanced-usage)
- [Testing](#testing)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [Security](#security)
- [Credits](#credits)
- [License](#license)

Features
--------

[](#features)

✨ **Readable Syntax** - Write regex patterns using intuitive, chainable methods 🔒 **Automatic Escaping** - Special characters are escaped automatically 🎯 **Type Safety** - Full IDE autocomplete support and type hints 🧪 **Thoroughly Tested** - Comprehensive test coverage 🎨 **Laravel Integration** - Seamless integration with Laravel applications ⚡ **Full Regex Support** - Complete implementation of PHP regex features including:

- Named and numbered capture groups with backreferences
- Lookahead and lookbehind assertions (positive and negative)
- Atomic groups and possessive quantifiers
- Conditional patterns and recursion
- POSIX character classes
- Mode modifiers (case-insensitive, multiline, etc.)
- Unicode and hexadecimal character support

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Laravel 9.0 or higher

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require vincentvanwijk/fluent-regex
```

Optionally, publish the configuration file:

```
php artisan vendor:publish --tag="fluent-regex-config"
```

Quick Start
-----------

[](#quick-start)

```
use VincentVanWijk\FluentRegex\Facades\FluentRegex;

// Create a regex to match an email address
$regex = FluentRegex::create('contact@example.com')
    ->alphaNumeric()->oneOrMoreTimes()
    ->exactly('@')
    ->letter()->oneOrMoreTimes()
    ->exactly('.')
    ->letter()->betweenNTimes(2, 4);

// Test the pattern
if ($regex->test()) {
    echo "Valid email!";
}

// Get the regex string
echo $regex->get(); // /[a-zA-Z0-9]+@[a-zA-Z]+\.[a-zA-Z]{2,4}/mu
```

Documentation
-------------

[](#documentation)

### Character Matching

[](#character-matching)

#### Basic Matching

[](#basic-matching)

```
// Match exact strings (automatically escaped)
->exactly('hello')              // hello
->exactly('regex!')             // regex\!

// Match any single character
->anyCharacter()                // .

// Match specific character sets
->anyCharacterOf('abc')         // [abc]
->anyCharacterOf('0-9')         // [0\-9]

// Negated character sets (using not modifier)
->not->anyCharacterOf('abc')    // [^abc]
```

#### Letter &amp; Number Matching

[](#letter--number-matching)

```
->letter()                      // [a-zA-Z]
->lowerCaseLetter()             // [a-z]
->upperCaseLetter()             // [A-Z]
->digit()                       // \d (equivalent to [0-9])
->not->digit()                  // \D (non-digit)
->alphaNumeric()                // [a-zA-Z0-9]
->hexDigit()                    // [0-9A-Fa-f]
```

#### Character Ranges

[](#character-ranges)

```
->range('a', 'z')               // [a-z]
->range('0', '9')               // [0-9]
->not->range('A', 'Z')          // [^A-Z]
```

### Quantifiers

[](#quantifiers)

Quantifiers specify how many times a pattern should match. All quantifiers support lazy and possessive modes.

```
// Basic quantifiers
->zeroOrOneTime()               // ?
->zeroOrMoreTimes()             // *
->oneOrMoreTimes()              // +

// Specific counts
->nTimes(3)                     // {3}
->nTimesOrMore(3)               // {3,}
->betweenNTimes(3, 6)           // {3,6}

// Quantifiers with strings
->zeroOrOneTime('a')            // a?
->oneOrMoreTimes('x')           // x+
->nTimesOf('b', 5)              // b{5}

// Lazy quantifiers (match as few as possible)
->lazy->oneOrMoreTimes()        // +?
->lazy->zeroOrMoreTimes()       // *?

// Possessive quantifiers (no backtracking)
->possessive->oneOrMoreTimes()  // ++
->possessive->zeroOrMoreTimes() // *+
```

### Anchors &amp; Boundaries

[](#anchors--boundaries)

```
// Line and string anchors
->startOfLine()                 // ^ (affected by multiline mode)
->endOfLine()                   // $ (affected by multiline mode)
->startOfString()               // \A (not affected by multiline)
->endOfString()                 // \Z (not affected by multiline)
->absoluteEndOfString()         // \z (strict end, no trailing newline)

// Word boundaries
->wordBoundary()                // \b
->nonWordBoundary()             // \B
```

### Groups &amp; Captures

[](#groups--captures)

#### Capture Groups

[](#capture-groups)

```
// Numbered capture group
->captureGroup(function ($regex) {
    return $regex->digit()->oneOrMoreTimes();
})  // (\d+)

// Named capture group
->namedCaptureGroup('year', function ($regex) {
    return $regex->digit()->nTimes(4);
})  // (?\d{4})

// Non-capturing group
->nonCaptureGroup(function ($regex) {
    return $regex->exactly('http')->zeroOrOneTime('s');
})  // (?:https?)
```

#### Advanced Groups

[](#advanced-groups)

```
// Atomic group (prevents backtracking)
->atomicGroup(function ($regex) {
    return $regex->digit()->oneOrMoreTimes();
})  // (?>\d+)

// Conditional pattern
->conditional(1,
    function ($regex) { return $regex->exactly('yes'); },
    function ($regex) { return $regex->exactly('no'); }
)  // (?(1)yes|no)

// Recursion
->recurse()                     // (?R) - recurse entire pattern
->recurseGroup(1)               // (?1) - recurse group 1
```

### Backreferences

[](#backreferences)

Reference previously captured content:

```
// Match repeated words: "the the" or "is is"
FluentRegex::create('the the')
    ->captureGroup(fn($r) => $r->wordCharacter()->oneOrMoreTimes())
    ->whiteSpace()
    ->backreference(1);         // \1

// Using named backreferences
FluentRegex::create('hello hello')
    ->namedCaptureGroup('word', fn($r) => $r->letter()->oneOrMoreTimes())
    ->whiteSpace()
    ->namedBackreference('word');  // \k
```

### Lookahead &amp; Lookbehind

[](#lookahead--lookbehind)

Assert patterns without consuming characters:

```
// Positive lookahead - assert that pattern follows
->positiveLookAhead(function ($regex) {
    return $regex->digit();
})  // (?=\d)

// Negative lookahead - assert that pattern does NOT follow
->negativeLookAhead(function ($regex) {
    return $regex->whiteSpace();
})  // (?!\s)

// Positive lookbehind - assert that pattern precedes
->positiveLookBehind(function ($regex) {
    return $regex->exactly('$');
})  // (?negativeLookBehind(function ($regex) {
    return $regex->digit();
})  // (?
```

### Character Classes

[](#character-classes)

#### Meta Sequences

[](#meta-sequences)

```
->whiteSpace()                  // \s (space, tab, newline)
->nonWhiteSpace()               // \S
->wordCharacter()               // \w ([a-zA-Z0-9_])
->not->wordCharacter()          // \W
->uniCodeCharacter()            // \X (any Unicode sequence)
```

#### POSIX Character Classes

[](#posix-character-classes)

```
->punctuation()                 // [[:punct:]]
->blank()                       // [[:blank:]] (space and tab only)
->controlCharacter()            // [[:cntrl:]]
->graphicCharacter()            // [[:graph:]] (visible characters)
->printableCharacter()          // [[:print:]] (visible + spaces)
```

### Special Characters &amp; Tokens

[](#special-characters--tokens)

```
// Whitespace characters
->newLine()                     // \R (any newline sequence)
->lineFeed()                    // \n
->carriageReturn()              // \r
->tabCharacter()                // \t
->verticalTab()                 // \v
->formFeed()                    // \f

// Special characters
->nullCharacter()               // \0
->alarm()                       // \a (bell)
->escapeCharacter()             // \e

// Character by code
->hexCharacter('41')            // \x41 (matches 'A')
->unicodeCharacter('00A9')      // \u00A9 (matches ©)
->controlCharacter('C')         // \cC (Ctrl+C)

// Alternation
->or('cat', 'dog', 'bird')      // cat|dog|bird

// Comments (ignored by regex engine)
->comment('Match the domain')   // (?#Match the domain)

// Raw regex (for advanced users)
->raw('[a-z]{2,}')              // [a-z]{2,}
```

### Mode Modifiers

[](#mode-modifiers)

Change regex behavior inline:

```
// Case sensitivity
->caseInsensitive()             // (?i)
->caseSensitive()               // (?-i)

// Dot behavior
->dotMatchesNewlines()          // (?s) - dot matches any character including newlines
->dotExcludesNewlines()         // (?-s)

// Multiline mode
->inlineMultilineMode()         // (?m)
->disableInlineMultilineMode()  // (?-m)

// Free-spacing mode (ignore whitespace, allow comments with #)
->freeSpacingMode()             // (?x)
->disableFreeSpacingMode()      // (?-x)

// Multiple modifiers at once
->setModeModifiers('im')        // (?im)
->setModeModifiers('i', 's')    // (?i-s)
```

### Substitution &amp; Replacement

[](#substitution--replacement)

```
$regex = FluentRegex::create('Hello World');

// Basic replacement
$result = $regex->digit()->replace('X');

// Replace with backreferences
$result = $regex->captureGroup(fn($r) => $r->wordCharacter()->oneOrMoreTimes())
    ->replace('[$1]');  // Wrap each word in brackets

// Replace with callback
$result = $regex->wordCharacter()->oneOrMoreTimes()
    ->replaceCallback(fn($matches) => strtoupper($matches[0]));

// Replace and get count
['result' => $text, 'count' => $n] = $regex->digit()->replaceWithCount('X');

// Split by pattern
$parts = $regex->whiteSpace()->oneOrMoreTimes()->split();

// Test if pattern matches
if ($regex->digit()->test()) {
    echo "Contains digits!";
}
```

Modifiers
---------

[](#modifiers)

Modifiers temporarily change behavior for the next method call:

### The `not` Modifier

[](#the-not-modifier)

Negates character classes:

```
->not->letter()                 // [^a-zA-Z]
->not->digit()                  // \D
->not->anyCharacterOf('aeiou')  // [^aeiou]
```

### The `lazy` Modifier

[](#the-lazy-modifier)

Makes quantifiers match as few characters as possible:

```
->lazy->oneOrMoreTimes()        // +?
->lazy->zeroOrMoreTimes()       // *?
->lazy->betweenNTimes(2, 5)     // {2,5}?

```

### The `possessive` Modifier

[](#the-possessive-modifier)

Makes quantifiers possessive (no backtracking):

```
->possessive->oneOrMoreTimes()  // ++
->possessive->zeroOrMoreTimes() // *+
```

**Note:** Modifiers automatically reset after each method call.

Configuration
-------------

[](#configuration)

Configure default behavior in `config/fluent-regex.php`:

```
return [
    // Delimiter used at the start and end of the regex
    'delimiter' => '/',

    // Multiline mode: ^ and $ match line boundaries (not just string boundaries)
    'multiLineMode' => true,

    // Unicode mode: pattern strings are treated as UTF-16
    'unicodeMode' => true,
];
```

You can override these per-instance:

```
$regex = FluentRegex::create('test', '#')  // Custom delimiter
    ->disableMultilineFlag()
    ->disableUnicodeFlag();
```

Advanced Usage
--------------

[](#advanced-usage)

### Email Validation

[](#email-validation)

```
$email = FluentRegex::create('user@example.com')
    ->startOfString()
    ->alphaNumeric()->oneOrMoreTimes()
    ->anyCharacterOf('._-')->zeroOrMoreTimes()
    ->exactly('@')
    ->alphaNumeric()->oneOrMoreTimes()
    ->exactly('.')
    ->letter()->betweenNTimes(2, 4)
    ->endOfString();

if ($email->test()) {
    echo "Valid email!";
}
```

### URL Matching

[](#url-matching)

```
$url = FluentRegex::create($input)
    ->startOfString()
    ->exactly('http')
    ->exactly('s')->zeroOrOneTime()
    ->exactly('://')
    ->nonCaptureGroup(fn($r) =>
        $r->alphaNumeric()->oneOrMoreTimes()
            ->anyCharacterOf('.-')->zeroOrMoreTimes()
    )
    ->oneOrMoreTimes()
    ->endOfString();
```

### Phone Number Extraction

[](#phone-number-extraction)

```
$phone = FluentRegex::create($text)
    ->nonCaptureGroup(fn($r) => $r->digit()->nTimes(3))
    ->anyCharacterOf('-.')->zeroOrOneTime()
    ->digit()->nTimes(3)
    ->anyCharacterOf('-.')->zeroOrOneTime()
    ->digit()->nTimes(4);

$matches = $phone->matchAll();
```

### Password Validation with Lookaheads

[](#password-validation-with-lookaheads)

```
// At least 8 chars, one uppercase, one lowercase, one digit
$password = FluentRegex::create($input)
    ->startOfString()
    ->positiveLookAhead(fn($r) => $r->anyCharacter()->zeroOrMoreTimes()->upperCaseLetter())
    ->positiveLookAhead(fn($r) => $r->anyCharacter()->zeroOrMoreTimes()->lowerCaseLetter())
    ->positiveLookAhead(fn($r) => $r->anyCharacter()->zeroOrMoreTimes()->digit())
    ->anyCharacter()->nTimesOrMore(8)
    ->endOfString();
```

### Creating from File

[](#creating-from-file)

```
$regex = FluentRegex::createFromFile('/path/to/file.txt')
    ->exactly('search term')
    ->match();
```

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

Run tests with coverage:

```
composer test-coverage
```

Run static analysis:

```
composer analyse
```

Fix code style:

```
composer format
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Vincent van Wijk](https://github.com/VincentVanWijk)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance74

Regular maintenance activity

Popularity11

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 82.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~529 days

Total

3

Last Release

146d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/dd0106ffddce82597e557e36a0bef38478619bd14b968a9829aa64ea8833a0fa?d=identicon)[VincentVanWijk](/maintainers/VincentVanWijk)

---

Top Contributors

[![VincentVanWijk](https://avatars.githubusercontent.com/u/10919865?v=4)](https://github.com/VincentVanWijk "VincentVanWijk (57 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (5 commits)")[![MichelBras](https://avatars.githubusercontent.com/u/11941051?v=4)](https://github.com/MichelBras "MichelBras (2 commits)")

---

Tags

laravelvincentvanwijkfluent-regex

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/vincentvanwijk-fluent-regex/health.svg)

```
[![Health](https://phpackages.com/badges/vincentvanwijk-fluent-regex/health.svg)](https://phpackages.com/packages/vincentvanwijk-fluent-regex)
```

###  Alternatives

[spatie/laravel-pdf

Create PDFs in Laravel apps

1.0k4.8M46](/packages/spatie-laravel-pdf)[codewithdennis/filament-select-tree

The multi-level select field enables you to make single selections from a predefined list of options that are organized into multiple levels or depths.

329530.5k29](/packages/codewithdennis-filament-select-tree)[worksome/exchange

Check Exchange Rates for any currency in Laravel.

124603.0k](/packages/worksome-exchange)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[stephenjude/laravel-wallet

A simple wallet implementation for Laravel

26611.9k](/packages/stephenjude-laravel-wallet)[tarfin-labs/event-machine

Event-driven state machines for Laravel with event sourcing, type-safe context, and full audit trail.

199.4k](/packages/tarfin-labs-event-machine)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
