Toss a coin to your T-Regx!

Hello, back again! :) We've added a "Sponsor" button on


If you like T-Regx going in the right direction, now you have the opportunity to throw us buck or two.

And a heads up, in the new 0.9.6 release, we'll add a really smart asInt() and fluent() methods; which are already present, but will get an upgrade.

You see, match()->first() calls preg_match() and that makes sense. Also match()->fluent() calls preg_match_all(), because later fluent()->map() or fluent()->filter()->first() can be called, for example. And that also, sorta makes sense. But, unfortunately match()->fluent()->first() and match()->asInt()->first() also call preg_match_all(), and that's a bit wasteful.

So now we're introducing a change (similar to Java 8 Streams) that will call preg_match() for fluent()->first() and asInt()->first().

Release 0.9.5 - Alternation in prepared patterns!

This release brings alternation in prepared patterns!

Up to this point, there was no reasonable way to create a pattern from a variable number of inputs, for example you allow your users to input 0, 1 or more tags, which later should be used in a pattern. In procedural world, probably array_map() with preg::quote() would do the job, but wait! You don't have to code, it's already here:

Pattern::bind('^user:@id/findBy:@tags/all$', [
'id' => $user->id,
'tags' => $_GET['tags']

In other words:

Pattern::bind('My tag is: "@tags"', ['tags' => ['one', 'two', 'three']]);

creates a pattern:

/My tag is: "(one|two|three)"/

Rest assured:

  • the values are quoted with preg::quote(), to protect you from malicious code
  • the group is non-capturing (use 'My tag is: "(@tags)"' for a capturing group, to be used with group())

The alternation is really smart too - if you use i or u flag, T-Regx will perform certain optimization, for example:

Pattern::inject('Find: @ :)', [['foo', 'bar', 'FOO']], 'i');

then it wil collapse foo and FOO, since i flag is used:

/Find: (foo|bar) :)/

That's it in this release! Stay tuned :)

Release 0.9.4 - Exception changes and groupBy()

This release brings updates in exceptions (namespaces, new detailed exceptions) and a groupBy() method.


In previous release we renamed SafeRegexException to PregException. In this, we're renaming CleanRegexException to PatternException. So now, those two general exceptions sync nicely with their base methods:

try {
return preg::match('/Foo/', $subject);
} catch (PregException $e) {
try {
return pattern('Foo')->test($subject);
} catch (PatternException $e) {

They both extend RegexException - base for all exceptions thrown by T-Regx. So that's the first thing.

The second exception update - previously, every exception thrown based on preg_last_error() method was RuntimePregException. Now, each error has a dedicated exception, which can be caught separately:

try {
return preg::match($pattern, $subject);
} catch (BacktrackLimitPregException $exception) {
} catch (Utf8OffsetPregException $exception) {

The detailed list of changes is in


This release also comes with a brand new method - groupBy() which groups matches by a capturing group (name or index). It can match strings, offsets and also map them with map() and flatMap(). Additionally, it can be chained with filter() to leave out unwanted matches:

return pattern('(\d)(?<unit>cm|mm)')->match($strings)
->filter(function (Match $match) {
return $match->group(1)->toInt() % 2 == 0;
->map(function (Match $match) {
return $match->group(1)->toInt() * 100;

Release 0.9.3 - Minor changes

That's a really quick update, we just found a PHP bug report #78853, that's probably going to be fixed in future versions of PHP, but we decided to include the bugfix in T-Regx so it's fixed in PHP 7.1 (if you're using T-Regx :)

Apart from that, we added preg::last_error_msg(), which returns the same data as preg::last_error(), but in in human-readable string. There are suggestions on PHP source code, that this method might become part of standard PHP library, so we at T-Regx thought we might include it already :) And if it's not included, after all, that's still a good idea to have this method :)

And there are some breaking changes, that should increase readability, for example this exception:

try {
return preg::match('/pattern/', $word)
catch (PregException $e) {

seems a bit more intuitive than

catch (SafeRegexException $e) {

So to name the exception based on a class/method, not the module :)

And FIY, the next feature we're working at T-Regx is groupBy(), which should complete groupByCallback() functionality already present in T-Regx. So expect that method first! :)

That's it for today, thanks guys!

Release 0.9.2 - You're in for a treat!

๐Ÿ˜Ž T-Regx The Dinosaur is really proud to announce its first beta version! Despite the beta suffix, it's 100% suitable for production use. It doesn't have any known bugs - check out the issues. There is a few breaking changes (since that's a 0.* version), but there are also a looot of improvements and new feautres. What's new in this release:

Here's a release on github: (see

  • Breaking changes
    • Methods pattern()/Pattern::of() no longer "magically" guess whether a pattern is delimited or not. Pattern::of() assumes pattern is delimited, new Pattern::pcre() takes an old-school delimited pattern.
    • Constructor new Pattern() is no longer a part of T-Regx API. Use Pattern::of()/pattern()
    • Renamed Match.parseInt() to Match.toInt() (the same for MatchGroup)
    • Removed pattern()->match()->test()/fails(). From now on, use pattern()->test()/fails()
    • Removed is():
      • is()->delimited()
      • is()->usable()
      • is()->valid() is changed to valid()
    • Removed split()->ex(), changed split()->inc() to split()
  • Features
    • Added ๐Ÿ”ฅ
    • Added pattern()->match()->fluent() ๐Ÿ”ฅ
    • Added pattern()->match()->asInt()
    • Added pattern()->match()->distinct() (leaves only unique matches)
    • Added prepared pattern method Pattern::inject()/Pattern::bind() (see below)
    • In pattern()->match()->groups():
      • Added groups()->forEach()/iterate()
      • Added groups()->flatMap()
      • Added groups()->map()
      • Added group()->fluent()
      • Added groups()->names() (and namedGroups()->names())
      • Added groups()->count() (and namedGroups()->count())
    • Added match()->offsets()->fluent()
    • Added match()->group(string)->offsets()->fluent()
    • Added pattern()->forArray()->strict() which throws for invalid values, instead of filtering them out
  • SafeRegex
    • Added preg::grep_keys() ๐Ÿ”ฅ, that works exactly like preg::grep(), but filters by keys (also accepts PREG_GREP_INVERT)
  • Enhancements/updates
    • Method by()->group()->orElse() now receives lazy-loaded Match, instead of a subject
    • Added withReferences() to CompositePattern.chainedReplace()
    • Previously named Pattern::inject() is renamed to Pattern::bind()
    • The Pattern::bind() (old Pattern::inject()) still accepts values as an associative array, but new Pattern::inject() receives values without regard for the keys.
    • Fixed passing invalid types to forArray(). Previously, caused fatal error due to internal preg_grep() implementation.
  • Other
    • Now MalformedPatternException is thrown, instead of CompileSafeRegexException, when using invalid PCRE syntax.
    • Returning Match from replace()->callback() (instead of Match.text() as string)
    • Match +12 is no longer considered a valid integer for isInt()/toInt()
    • Unnamed group will be represented as null in Match.groupNames(), instead of being simply ignored
    • helper() method, Pattern and PatternBuilder now return interface PatternInterface, instead of Pattern class. Pattern class now only holds static utility methods, and PatternImpl holds the pattern implementation.
  • Maintenance

Foot note:

  • Apart from PHP type hints, every version up to this point could be run on PHP 5.3 (if one removes type hints from code, one can run T-Regx on PHP 5.3). Every error, exception, malfunction, inconsistency was handled correctly by T-Regx. From this version on (0.9.2), handling of the errors and inconsistencies is dropped, since T-Regx now only supports PHP 7.1.

Hope you guys will like and enjoy it!

Don't forget about T-Regx

Some of you might have noticed that not many new features have been added to 0.9.2 release candidate, since few weeks. But rest assured! :D Work on T-Regx hasn't slowed a bit! We've just put more effort on a more side-part of T-Regx.

Thanks to the keen eye of T-Regx user, Andreas Leathley, it stroke us that phpDoc in public methods of preg class (so preg::match(), preg::replace(), etc.) were not only outdated, they were incorrect at times. Thanks Andreas! :)

At first, we only wanted to correct the mistakes, but I quickly realized that mere phpDoc inherited from preg_*() methods is not enough :/ That could be easily found on, what T-Regx users could really benefit from is a really extensive, rich, long, detailed and robust documentation.

That's why we've spent a little over a week to create an application that's capable of generating a complex and rich phpDoc for preg class (of course we'll use it for more classes in T-Regx). Main updates for the documentation will include:

  • Robust description of every parameter of every preg_*()
  • Detailed description of every flag used (e.g. PREG_OFFSET_CAPTURE)
  • Rich description of each method, it's relation, similarities and differences to other methods

And it will be much easier to maintain, because every class will have a phpDoc that's not written, but generated.

I'm pretty certain T-Regx is going to have a documentation you've never seen before :D

Of course, there are also some minor changes:

  • We've added pattern()->match()->group()->fluent()
  • Added callback for pattern()->match()->group()->first()
  • Updated detailed description in

Keep looking forward to T-Regx 0.9.2! :)

The best Stargazers' Revolutions

I have imagined this moment for a long time. Is it real? Could it be T-Regx got 60 stars ? :D

But what's new.

There is preg_grep() function for filtering an array by a pattern, unfortunately there's no flag or another method to filter it by keys. There is a T-Regx method forArray()->filterByKeys(), but there was no such solution in SafeRegex.

That's why we added preg::grep_keys, which works exactly like preg_grep() but filters an array by keys, instead of values. It's going to be release in 0.9.2.

List of all changes incoming in 0.9.2 is available in, with fluent(), unique(), in-place replacements and more.

"The best Stargazers!" Reloaded

Holy guacamole! There were only 30 stars a few weeks ago and we have 40 already!? :D You guys gave us even more reason to release T-Regx 0.9.2 even sooner! Two new features are coming:

  • In-group replacing ๐Ÿ˜ฒ You can now replace a single group inside your subject (not only in replace(), in any method with Match details)
  • Additional prepared patterns method - Pattern::bind()

So keep an eye for 0.9.2 release.

Match details update

Most changes in T-Regx since the last Blog post were to Match details. We added user data (getUserData()/setUserData()) which can be used in chained calls (e.g. filter()->map()).

The second change is isInt()/parseInt() which allow you to handle "real" integers safetly - without the fear of "PHP smart" integers (e.g. PHP thinks that "1e3" is 1000). T-Regx understands that robust applications can't allow numbers to be 10e4 - it should be treated as an invalid integer by default!

And last,|string) is now validated (T-Regx was waiting a bit for this change!). We believe that using an invalid group name is a sign of a bug, so using group(-1) or group('!@#') now throws \InvalidArgumentException, as it's more suitable than assuming that -1 is just an unmatched group.