vincentvanwijk/fluent-regex 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

vincentvanwijk/fluent-regex

Composer 安装命令:

composer require vincentvanwijk/fluent-regex

包简介

A package to fluently create regular expressions

README 文档

README

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 GitHub Tests Action Status GitHub Code Style Action Status PHPStan codecov Total Downloads

Table of Contents

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

  • PHP 8.1 or higher
  • Laravel 9.0 or higher

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

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

Character 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 & 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

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

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 & 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 & Captures

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);
})  // (?<year>\d{4})

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

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

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<word>

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('$');
})  // (?<=\$)

// Negative lookbehind - assert that pattern does NOT precede
->negativeLookBehind(function ($regex) {
    return $regex->digit();
})  // (?<!\d)

Character Classes

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

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

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

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 & 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 temporarily change behavior for the next method call:

The not Modifier

Negates character classes:

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

The lazy Modifier

Makes quantifiers match as few characters as possible:

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

The possessive Modifier

Makes quantifiers possessive (no backtracking):

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

Note: Modifiers automatically reset after each method call.

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

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 = FluentRegex::create($input)
    ->startOfString()
    ->exactly('http')
    ->exactly('s')->zeroOrOneTime()
    ->exactly('://')
    ->nonCaptureGroup(fn($r) =>
        $r->alphaNumeric()->oneOrMoreTimes()
            ->anyCharacterOf('.-')->zeroOrMoreTimes()
    )
    ->oneOrMoreTimes()
    ->endOfString();

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

// 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

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

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

Please see CHANGELOG for more information on what has changed recently.

Contributing

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

Security

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

Credits

License

The MIT License (MIT). Please see License File for more information.

vincentvanwijk/fluent-regex 适用场景与选型建议

vincentvanwijk/fluent-regex 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 9 次下载、GitHub Stars 达 7, 最近一次更新时间为 2023 年 03 月 01 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「vincentvanwijk」 「fluent-regex」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 vincentvanwijk/fluent-regex 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 vincentvanwijk/fluent-regex 我们能提供哪些服务?
定制开发 / 二次开发

基于 vincentvanwijk/fluent-regex 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 9
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 7
  • 点击次数: 9
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 7
  • Watchers: 2
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-03-01