Skip to content

Pattern Builder

The Pattern value object provides a fluent API for building regex patterns with type-safe modifier configuration.

Use create() when you have a raw expression without delimiters:

use Cline\Relex\ValueObjects\Pattern;
use Cline\Relex\Relex;
// Create pattern from expression
$pattern = Pattern::create('\d+');
// Use with Relex
Relex::match($pattern, 'abc123')->result(); // "123"

You can also specify a custom delimiter:

// Using # as delimiter (useful when pattern contains /)
$pattern = Pattern::create('http://\w+', '#');

Use from() when you have a complete pattern with delimiters and modifiers:

$pattern = Pattern::from('/\d+/i');
// Modifiers are parsed automatically
$pattern->hasModifier(Modifier::CaseInsensitive); // true

The Relex class provides convenience methods:

// Same as Pattern::create()
$pattern = Relex::compile('\d+');
// Same as Pattern::from()
$pattern = Relex::pattern('/\d+/im');

Readable method names for adding modifiers:

$pattern = Pattern::create('\w+')
->caseInsensitive() // i - Case-insensitive matching
->multiline() // m - ^ and $ match line boundaries
->singleLine() // s - Dot matches newlines
->extended() // x - Whitespace ignored, # comments
->utf8() // u - UTF-8 mode
->anchored() // A - Anchored at start
->dollarEndOnly() // D - $ only matches end of string
->ungreedy() // U - Quantifiers lazy by default
->duplicateNames() // J - Allow duplicate named groups
->study(); // S - Optimize pattern

Single-letter shortcuts matching PCRE conventions:

$pattern = Pattern::create('\w+')
->i() // Case-insensitive
->m() // Multiline
->s() // Single-line (dotall)
->x() // Extended
->u(); // UTF-8

Add modifiers directly using the Modifier enum:

use Cline\Relex\Enums\Modifier;
$pattern = Pattern::create('\w+')
->withModifier(Modifier::CaseInsensitive)
->withModifier(Modifier::Utf8);
// Add multiple at once
$pattern = Pattern::create('\w+')
->withModifiers(
Modifier::CaseInsensitive,
Modifier::Multiline,
Modifier::Utf8
);
$pattern = Pattern::from('/\w+/imu')
->withoutModifier(Modifier::Multiline);
$pattern->modifierString(); // "iu"
ModifierMethodShorthandDescription
icaseInsensitive()i()Letters match both cases
mmultiline()m()^ and $ match line boundaries
ssingleLine()s()Dot matches newlines
xextended()x()Whitespace ignored, # comments
uutf8()u()UTF-8 mode
Aanchored()-Pattern anchored at start
DdollarEndOnly()-$ only matches end of string
Uungreedy()-Quantifiers lazy by default
JduplicateNames()-Allow duplicate named groups
Sstudy()-Optimize pattern analysis
$pattern = Pattern::from('/(?<name>\w+)/imu');
$pattern->expression(); // "(?<name>\w+)"
$pattern->delimiter(); // "/"
$pattern->modifierString(); // "imu"
$pattern->toString(); // "/(?<name>\w+)/imu"
$pattern = Pattern::from('/\w+/im');
$pattern->hasModifier(Modifier::CaseInsensitive); // true
$pattern->hasModifier(Modifier::Utf8); // false
$pattern->modifiers(); // [Modifier::CaseInsensitive, Modifier::Multiline]
$pattern = Pattern::create('(?<year>\d{4})-(?<month>\d{2})-(\d{2})');
$pattern->groupNames(); // ["year", "month"]
$pattern->groupCount(); // 3
$pattern->hasNamedGroups(); // true
use Cline\Relex\ValueObjects\Pattern;
Pattern::isValid('/\d+/'); // true
Pattern::isValid('/[invalid'); // false
use Cline\Relex\Exceptions\PatternCompilationException;
try {
Pattern::validate('/[invalid');
} catch (PatternCompilationException $e) {
echo $e->getMessage(); // "Regex compilation failed..."
}
Relex::isValid('/\d+/'); // true
Relex::validate('/\d+/'); // throws on invalid

Pattern objects are immutable. All modifier methods return a new instance:

$original = Pattern::create('\d+');
$modified = $original->caseInsensitive();
$original->hasModifier(Modifier::CaseInsensitive); // false
$modified->hasModifier(Modifier::CaseInsensitive); // true

Patterns implement Stringable and can be used directly as strings:

$pattern = Pattern::create('\d+')->utf8();
echo $pattern; // "/\d+/u"
echo $pattern->toString(); // "/\d+/u"
// Pass directly to preg_* functions
preg_match($pattern, 'abc123', $matches);
$email = Pattern::create('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
->caseInsensitive();
$url = Pattern::create('https?://[^\s]+', '#')
->caseInsensitive();
$date = Pattern::create('(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})');
$multiline = Pattern::create('^.*error.*$')
->multiline()
->caseInsensitive();
$verbose = Pattern::create('
(?<year>\d{4}) # Year (4 digits)
- # Separator
(?<month>\d{2}) # Month (2 digits)
- # Separator
(?<day>\d{2}) # Day (2 digits)
')->extended();