PHPackages                             liquidrazor/liquid-regex - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. liquidrazor/liquid-regex

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

liquidrazor/liquid-regex
========================

An intuitive, simple and powerful Regex library for PHP.

v0.1.0(7mo ago)06MITPHPPHP &gt;=8.3

Since Sep 25Pushed 6mo agoCompare

[ Source](https://github.com/LiquidRazor/LiquidRegex)[ Packagist](https://packagist.org/packages/liquidrazor/liquid-regex)[ RSS](/packages/liquidrazor-liquid-regex/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (3)Used By (0)

LiquidRazor Regex
=================

[](#liquidrazor-regex)

An intuitive, small, and fast **regular expression helper for PHP 8.3+** with clean result objects and a few ergonomic utilities around PCRE.

> Package: `liquidrazor/liquid-regex` • License: MIT

---

✨ Features
----------

[](#-features)

- **Fluent, tiny API** for matching and replacing.
- **Lazy, rewindable match results** with `Iterator`, `ArrayAccess`, `Countable`, and `JsonSerializable` support.
- **Deterministic result shapes** via `ResultTypes` (numeric, associative, or both) and a `STRICT` filter.
- **PCRE helpers** to check version/JIT support and validate pattern syntax.
- **Exceptions you can catch** with informative messages bubbled from PCRE.

---

🚧 Requirements
--------------

[](#-requirements)

- PHP **8.3** or newer
- PCRE (bundled with PHP)

---

📦 Installation
--------------

[](#-installation)

```
composer require liquidrazor/regex
```

The library is namespaced under `LiquidRazor\Regex` and PSR‑4 autoloaded per `composer.json`.

---

🧠 Concepts at a Glance
----------------------

[](#-concepts-at-a-glance)

### `Regex` — main entry point

[](#regex--main-entry-point)

The `Regex` class is the main façade. It also memoizes compiled instances by pattern:

```
use LiquidRazor\Regex\Regex;

$re = Regex::compiled('/(?P[a-z]+)/i');
```

From there you can **match** or **replace** (see examples below).

### `ResultTypes` — control your result shape

[](#resulttypes--control-your-result-shape)

Choose how match arrays are exposed:

```
use LiquidRazor\Regex\Result\ResultTypes;

// Types
ResultTypes::INDEXED;      // numeric keys only (0, 1, 2, ...)
ResultTypes::ASSOCIATIVE;  // named keys only ('foo', 'bar', ...)
ResultTypes::BOTH;         // default: include both kinds

// Modifier
ResultTypes::STRICT;       // when used, filters to "pure" keys only:
//   - with INDEXED: keeps only truly integer keys (0,1,2...)
//   - with ASSOCIATIVE: keeps only truly string, non-numeric keys
```

This lets you request exactly the view you need (e.g., only named groups). You can bit‑OR flags:

```
$flags = ResultTypes::ASSOCIATIVE | ResultTypes::STRICT;
```

### `Flags` (PCRE capture flags)

[](#flags-pcre-capture-flags)

Extra capture behavior forwarded to PCRE:

```
use LiquidRazor\Regex\Lib\Flags;

Flags::OffsetCapture;   // include offsets for each capture
Flags::UnmatchedAsNull; // unmatched subpatterns become null
```

---

🚀 Quick start
-------------

[](#-quick-start)

### 1) Find the first match

[](#1-find-the-first-match)

```
use LiquidRazor\Regex\Regex;
use LiquidRazor\Regex\Result\ResultTypes;

$re = Regex::compiled('/(?P[a-z]+)/i');

$result = $re->match(
    haystack: "Hello, World!",
    resultType: ResultTypes::ASSOCIATIVE | ResultTypes::STRICT // named keys only
);

if ($result->didMatch) {
    // ArrayAccess
    $first = $result[0]; // or $result['word'] in ASSOCIATIVE mode

    // Countable
    $count = count($result);

    // Iteration (rewindable)
    foreach ($result as $k => $v) {
        // ...
    }

    // JSON
    $json = json_encode($result, JSON_PRETTY_PRINT);
}
```

### 3) Replace

[](#3-replace)

```
use LiquidRazor\Regex\Regex;
use LiquidRazor\Regex\Result\Replace\Result;

$re = Regex::compiled('/(\d+)/');
$replace = $re->replace('abc 123 xyz 45', '#');

$replace->pattern;   // the pattern used
$replace->count;     // number of replacements performed
(string)$replace;    // casts to the replaced string (or JSON if array)
```

`LiquidRazor\Regex\Result\Replace\Result` implements `Stringable`. If the replacement result is an array (e.g., when replacing in arrays), `__toString()` returns JSON.

---

🎛️ Controlling result shapes
----------------------------

[](#️-controlling-result-shapes)

The `LiquidRazor\Regex\Result\Matches\Result` object exposes a lazy, memoized sequence of match entries. You decide which keys appear using `ResultTypes`:

- `INDEXED`: keeps only integer keys (0,1,2…). With `STRICT`, **filters out** any non-integer keys.
- `ASSOCIATIVE`: keeps only named group keys. With `STRICT`, **filters out** numeric-looking strings.
- `BOTH`: includes both numeric and associative keys (default). Combine with `STRICT` to prune mixed keys.

The object supports:

- `Iterator` (rewindable)
- `ArrayAccess` (read-only; attempting to mutate throws `ImmutableException`)
- `Countable`
- `JsonSerializable`

```
// Read-only access (mutations throw)
$value = $result['name'] ?? $result[0];
```

If there was **no match**, the `Result` is empty with `didMatch === false` (safe to iterate/count/JSON-encode).

---

🧩 PCRE helpers
--------------

[](#-pcre-helpers)

Use the `Pcre` static utility for environment checks:

```
use LiquidRazor\Regex\Pcre;

Pcre::versionString();   // "PCRE x.y (major.minor)"
Pcre::isJitSupported();  // bool
Pcre::isValid('/^[a-z]+$/i'); // quick sanity check for "/.../flags"-style patterns
```

> Note: `isValid()` only checks a basic `/.../flags` shape, also does compile the pattern and checks the result. If compilation fails, it returns false.

---

⚠️ Exceptions
-------------

[](#️-exceptions)

The library centralizes PCRE errors through `LiquidRazor\Regex\Exception` classes:

- `PcreException` – wraps `preg_last_error()` &amp; message
- `Exception` – currently extends `PcreException` for convenience
- `ImmutableException` – thrown on attempts to mutate read-only results

In practice, most API calls either return a `Result` object or throw on **internal** PCRE errors (e.g., bad backtrack limit).

```
use LiquidRazor\Regex\Exception\PcreException;

try {
    $re = Regex::compiled('/(?P[a-z]+)/i');
    $res = $re->match('...');
} catch (PcreException $e) {
    // inspect $e->getMessage(), $e->getCode()
}
```

---

📚 API sketch
------------

[](#-api-sketch)

> The following reflects the current source structure at a high level. Some signatures may evolve.

- `Regex::compiled(string $pattern): Regex`
- `Regex->match(string $haystack, int $resultType = ResultTypes::BOTH, Flags ...$captureFlags): LiquidRazor\Regex\Result\Matches\Result`
- `Regex->replace(string|array $subject, string|callable $replacement, int $limit = -1): LiquidRazor\Regex\Result\Replace\Result`

Result types:

- `LiquidRazor\Regex\Result\Matches\Result`
    - Properties: `pattern`, `haystack`, `didMatch`
    - Interfaces: `Iterator`, `ArrayAccess` (read-only), `Countable`, `JsonSerializable`
- `LiquidRazor\Regex\Result\Replace\Result implements Stringable`
    - Properties: `pattern`, `count`, `replaced`
    - Casting: `(string)$result` yields the final string (or JSON if array)

Helpers:

- `LiquidRazor\Regex\Pcre`
    - `versionString(): string`
    - `isJitSupported(): bool`
    - `isValid(?string $pattern): bool`

Enums / constants:

- `LiquidRazor\Regex\Lib\Flags` — `Default`, `OffsetCapture`, `UnmatchedAsNull`
- `LiquidRazor\Regex\Result\ResultTypes` — `INDEXED`, `ASSOCIATIVE`, `BOTH`, `STRICT`

---

✅ Examples
----------

[](#-examples)

### Only named groups, strictly

[](#only-named-groups-strictly)

```
use LiquidRazor\Regex\Regex;
use LiquidRazor\Regex\Result\ResultTypes;

$re = Regex::compiled('/(?P\d+)-(?P[a-z]+)/i');
$res = $re->match('42-Answer', ResultTypes::ASSOCIATIVE | ResultTypes::STRICT);

echo json_encode($res, JSON_PRETTY_PRINT);
/*
{
  "num": "42",
  "word": "Answer"
}
*/
```

### With offsets and nulls for unmatched

[](#with-offsets-and-nulls-for-unmatched)

```
use LiquidRazor\Regex\Regex;
use LiquidRazor\Regex\Lib\Flags;

$re = Regex::compiled('/(a)?(b)/');
$res = $re->match('xb', Flags::OffsetCapture, Flags::UnmatchedAsNull);

// Offsets included; the first group is null because it didn't match.
```

---

🧪 Testing
---------

[](#-testing)

You can plug this library into any test runner. The result objects are easy to snapshot by JSON encoding.

```
$this->assertJsonStringEqualsJsonString(
    '{"word":"Hello"}',
    json_encode($result, JSON_THROW_ON_ERROR)
);
```

---

🤝 Contributing
--------------

[](#-contributing)

- Open an issue for design/API discussions.
- Keep the API minimal and predictable.
- PRs welcome with tests and docs for new behavior.

---

📄 License
---------

[](#-license)

[MIT](./LICENSE) © LiquidRazor

###  Health Score

33

—

LowBetter than 74% of packages

Maintenance70

Regular maintenance activity

Popularity5

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 50% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

225d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/e78165b98196f1f473f4637d004e8346f974136b24242f9f4c6237b6a1411bd4?d=identicon)[Noramarth](/maintainers/Noramarth)

---

Top Contributors

[![hktr92](https://avatars.githubusercontent.com/u/7689151?v=4)](https://github.com/hktr92 "hktr92 (6 commits)")[![Noramarth](https://avatars.githubusercontent.com/u/4306922?v=4)](https://github.com/Noramarth "Noramarth (6 commits)")

### Embed Badge

![Health badge](/badges/liquidrazor-liquid-regex/health.svg)

```
[![Health](https://phpackages.com/badges/liquidrazor-liquid-regex/health.svg)](https://phpackages.com/packages/liquidrazor-liquid-regex)
```

###  Alternatives

[fideloper/proxy

Set trusted proxies for Laravel

7.3k174.4M550](/packages/fideloper-proxy)[fakerphp/faker

Faker is a PHP library that generates fake data for you.

3.9k358.5M3.4k](/packages/fakerphp-faker)[consolidation/robo

Modern task runner

2.7k62.9M408](/packages/consolidation-robo)[brick/money

Money and currency library

1.9k37.9M102](/packages/brick-money)[jetbrains/phpstorm-stubs

PHP runtime &amp; extensions header files for PhpStorm

1.4k27.7M67](/packages/jetbrains-phpstorm-stubs)[illuminate/support

The Illuminate Support package.

583107.1M34.3k](/packages/illuminate-support)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
