Skip to main content

Release 0.9.7 - Match as vanilla array!

There was a lot of changes in the code, so I reckon we could release twice in the same week, because why not :)

So what are the changes?

Bare with me.

The concept#

Capturing groups in T-Regx have a really rich API (probably the richest out there), with a lot of variables. Most importantly T-Regx handles:

  • Invalid groups (e.g. negative index -1 or malformed group !@#$), which always throw exception
  • Missing groups (e.g. group 4 used in pattern, that only has 2 groups; same for named) which conditionally throws exceptions
  • Optional groups (e.g. (origin/)?master), which is really tricky to distinguish with PCRE
  • Matched groups (which can be tricky, if the matched group is an empty string "")

Because of that, syntax of groups is not the shortest:

pattern('(origin/)?master')->match('master')->first(function (Match $match) {
$match->group(1)->text(); // for example
});

But we know that T-Regx users mostly care about the last group, Matched groups, so they would like to use them with as simple syntax as possible. That makes sense.

The idea#

At first, there was an idea of Match details implementing \ArrayAccess, so this syntax would be possible:

pattern('(origin/)?master')->match('master')->first(function (Match $match) {
$match[1]; // same as above
});

Well, that syntax does look good, at first, but it comes at a price. A high price.

Why we ditched the \ArrayAccess idea:

  • Unnecessary set and unset methods
  • Methods that work for arrays (array_key_exist()) won't work with \ArrayAccess
  • empty($match[1]) returns true, even if the group 1 was matched ("" and "0" yes is falsy)
  • isset($match[-2]) couldn't throw an exception for a malformed group
  • There's a bug in PHP, that causes $match['100'] to be treated as $match[100] (cast to int any numeric value).

The solution#

So, instead, we got an idea: What if $match was a real PHP array. Every method or notation that works for arrays, will also work.

pattern('(origin/)?master')->match('master')->asArray()->first(function (array $match) {
$match[1]; // same as above
});

The structure of the array is perfectly identical to what preg_match() would return :)