rawr/t-regx

PHP regular expression brought up to modern standards.

Maintainers

Details

github.com/t-regx/T-Regx

Source

Issues

Fund package maintenance!
Danon


README

T-Regx

Build status Unit tests latest: 0.41.5 dependencies: 0

T-Regx | Regular Expressions library

PHP regular expressions brought up to modern standards.

See documentation at t-regx.com.

last commit commit activity Commits since Unit tests Unit tests Code Climate FQN PRs Welcome Gitter

OS Arch OS Arch OS Arch OS Arch

PHP Version PHP Version PHP Version PHP Version PHP Version PHP Version PHP Version

  1. Installation
  2. Examples
  3. Documentation
  4. T-Regx fiddle - Try online
  5. API
    1. For standard projects -pattern()
    2. For legacy projects - preg::match_all()
  6. Overview
    1. Prepared patterns
    2. Working with the developer
    3. Clean API
    4. Fatal errors
    5. Clean Code
    6. Exceptions vs. errors
  7. Comparison
    1. Exceptions over warnings/errors
    2. Working with the developer
    3. Written with clean API in mind
    4. Philosophy of Uncle Bob and "Clean Code"
  8. Plans for the future
  9. Sponsors
  10. License

Buy me a coffee!

Installation

Installation for PHP 7.1 and later (PHP 8 as well):

composer require rawr/t-regx

T-Regx only requires mb-string extension. No additional dependencies or extensions are required.

Examples

Illustration of methods match(), test() and count().

$pattern = Pattern::of("ups"); // pattern("ups") also works
$matcher = $pattern->match('yay, ups');

foreach ($matcher as $detail) {
   $detail->text();    // (string) "ups";
   $detail->offset();  // (int) 0
}

if (!$matcher->test()) {
   echo "No occurrances found";
} else {
   echo "Found {$matcher->count()} occurrences";
}

Documentation

Full API documentation is available at t-regx.com. List of changes is available in ChangeLog.md.

Quick links:

Try it online, in your browser!

Open T-Regx fiddle and start playing around right in your browser. Try now!

API

Choose the interface:

  • I choose the modern regex API:

    Scroll to see - pattern()->test(), pattern()->match(), pattern()->replace()

  • I choose to keep PHP methods (but protected from errors/warnings):

    Scroll to see - preg::match_all(), preg::replace_callback(), preg::split()

For standard projects, we suggest pattern(). For legacy projects, we suggest preg::match_all().

  • Standard T-Regx

    $pattern = Pattern::of("ups"); // pattern("ups") also works
    $matcher = $pattern->match('yay, ups');
    
    if (!$matcher->test()) {
      echo "Unmatched subject :/";
    }
    
    foreach ($matcher as $detail) {
      $detail->text();    // (string) "ups";
      $detail->offset();  // (int) 0
    }
    
    $pattern->replace('well, ups')->with('heck') // (string) "well, heck";
  • Legacy API

    try {
        preg::match_all('/?ups/', 'ups', $match, PREG_PATTERN_ORDER);
        echo $match[0][0];
    } catch (\TRegx\Exception\MalformedPatternException $exception) {
        echo "Invalid pattern";
    }

Why T-Regx stands out?

💡 See documentation at t-regx.com

  • Prepared patterns

    Using user data isn't always safe with PCRE (even with preg_quote()), as well as just not being that convenient to use. T-Regx provides dedicated solution for building patterns with unsafe user input. Choose Pattern::inject() for simply including user data as literals. Use Pattern::mask() to convert user-supplied masks into full-fledged patterns, safely. Use Pattern::template() for constructing more complex patterns.

    function makePattern($name): Pattern {
      if ($name === null) {
        return Pattern::of("name[:=]empty");
      }
      return Pattern::inject("name[:=]@;", [$name]); // inject $name as @
    }
    
    $gibberish = "(my?name)";
    $pattern = makePattern($gibberish);
    
    $pattern->test('name=(my?name)'); // (bool) true
  • Working with the developer

    • Simple methods
      • T-Regx exposes functionality by simple methods, which return int, string, string[] or bool, which aren't nullable. If you wish to do something with your match or pattern, there's probably a method for that, which does exactly and only that.
    • Strings:
    • Groups:
      • When using preg::match_all(), we receive an array, of arrays, of arrays. In contrast, T-Regx returns an array of groups: Group[]. Object Group contains all the information about the group.

      • Group errors:

        • When invalid group named is used get('!@#'), T-Regx throws \InvalidArgumentException.
        • When attempt to read a missing group, T-Regx throws NonexistentGroupException.
        • When reading a group that happens not to be matched, T-Regx throws GroupNotMatchedException.
  • Written with clean API

    • Descriptive, simple interface
    • Unicode support out-of-the-box
    • No Reflection used, No (...varargs), No (boolean arguments, true), (No flags, 1), [No [nested, [arrays]]]
    • Inconsistencies between PHP versions are eliminated in T-Regx
  • Protects you from fatal errors

    Certain arguments cause fatal errors with preg_() methods, which terminate the application and can't be caught. T-Regx will predict if given argument would cause a fatal error, and will throw a catchable exception instead.

  • T-Regx follows the philosophy of Uncle Bob and "Clean Code"

    Function should do one thing, it should do it well. A function should do exactly what you expect it to do.

  • Compatible with other tools and libraries

    Granted, Pattern::of() accepts undelimited pattern ((Foo){3,4}}) is not suitable with other PHP libraries, which work with delimited patterns (/(Foo){3,4}/), for example Laravel and Routing. For that case, use PcrePattern::of() which accepts plain-old standard PHP syntax.

  • Exceptions over warnings/errors

    • Unlike PHP methods, T-Regx doesn't use warnings/notices/errors for unexpected inputs:
      try {
        preg::match_all('/([a3]+[a3]+)+3/', 'aaaaaaaaaaaaaaaaaaaa 3');
      } catch (\TRegx\SafeRegex\Exception\CatastrophicBacktrackingException $exception) {
        // caught
      }
    • Detects malformed patterns in and throws MalformedPatternException. This is impossible to catch with preg_last_error().
      try {
        preg::match('/?ups/', 'ups');
      } catch (\TRegx\Exception\MalformedPatternException $exception) {
        // caught
      }
    • Not every error in PHP can be read from preg_last_error(), however T-Regx throws dedicated exceptions for those events.

Comparison

Ugly api

or

Pretty api

Current work in progress

Current development priorities, regarding release of 1.0:

  • Separate SafeRegex and CleanRegex into to two packages, so users can choose what they need #103
  • Add documentation to each T-Regx public method #17 [in progress]
  • Revamp of t-regx.com documentation [in progress]
  • Release 1.0

Sponsors

T-Regx is developed thanks to

JetBrains

License

T-Regx is MIT licensed.