Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

PCRE wrapping library that offers type-safe preg_* replacements.

License

NotificationsYou must be signed in to change notification settings

composer/pcre

Repository files navigation

PCRE wrapping library that offers type-safepreg_* replacements.

This library gives you a way to ensurepreg_* functions do not fail silently, returningunexpectednulls that may not be handled.

As of 3.0 this library enforcesPREG_UNMATCHED_AS_NULL usagefor all matching and replaceCallback functions,read more belowto understand the implications.

It thus makes it easier to work with static analysis tools like PHPStan or Psalm as itsimplifies and reduces the possible return values from all thepreg_* functions whichare quite packed with edge cases. As of v2.2.0 / v3.2.0 the library also comes with aPHPStan extension for parsing regular expressions and giving you even better output types.

This library is a thin wrapper aroundpreg_* functions withsome limitations.If you are looking for a richer API to handle regular expressions have a look atrawr/t-regx instead.

Continuous Integration

Installation

Install the latest version with:

$ composer require composer/pcre

Requirements

  • PHP 7.4.0 is required for 3.x versions
  • PHP 7.2.0 is required for 2.x versions
  • PHP 5.3.2 is required for 1.x versions

Basic usage

Instead of:

if (preg_match('{fo+}',$string,$matches)) {... }if (preg_match('{fo+}',$string,$matches,PREG_OFFSET_CAPTURE)) {... }if (preg_match_all('{fo+}',$string,$matches)) {... }$newString =preg_replace('{fo+}','bar',$string);$newString =preg_replace_callback('{fo+}',function ($match) {returnstrtoupper($match[0]); },$string);$newString =preg_replace_callback_array(['{fo+}' =>fn ($match) =>strtoupper($match[0])],$string);$filtered =preg_grep('{[a-z]}',$elements);$array =preg_split('{[a-z]+}',$string);

You can now call these on thePreg class:

useComposer\Pcre\Preg;if (Preg::match('{fo+}',$string,$matches)) {... }if (Preg::matchWithOffsets('{fo+}',$string,$matches)) {... }if (Preg::matchAll('{fo+}',$string,$matches)) {... }$newString = Preg::replace('{fo+}','bar',$string);$newString = Preg::replaceCallback('{fo+}',function ($match) {returnstrtoupper($match[0]); },$string);$newString = Preg::replaceCallbackArray(['{fo+}' =>fn ($match) =>strtoupper($match[0])],$string);$filtered = Preg::grep('{[a-z]}',$elements);$array = Preg::split('{[a-z]+}',$string);

The main difference is if anything fails to match/replace/.., it will throw aComposer\Pcre\PcreExceptioninstead of returningnull (or false in some cases), so you can now use the return values safely relying onthe fact that they can only be strings (for replace), ints (for match) or arrays (for grep/split).

Additionally thePreg class provides match methods that returnbool rather thanint, for stricter type safetywhen the number of pattern matches is not useful:

useComposer\Pcre\Preg;if (Preg::isMatch('{fo+}',$string,$matches))// boolif (Preg::isMatchAll('{fo+}',$string,$matches))// bool

Finally thePreg class provides a few*StrictGroups method variants that ensure match groupsare always present and thus non-nullable, making it easier to write type-safe code:

useComposer\Pcre\Preg;// $matches is guaranteed to be an array of strings, if a subpattern does not match and produces a null it will throwif (Preg::matchStrictGroups('{fo+}',$string,$matches))if (Preg::matchAllStrictGroups('{fo+}',$string,$matches))

Note: This is generally safe to use as long as you do not have optional subpatterns (i.e.(something)?or(something)* or branches with a| that result in some groups not being matched at all).A subpattern that can match an empty string like(.*) isnot optional, it will be present as anempty string in the matches. A non-matching subpattern, even if optional like(?:foo)? will anyway not be present inmatches so it is also not a problem to use these with*StrictGroups methods.

If you would prefer a slightly more verbose usage, replacing by-ref arguments by result objects, you can use theRegex class:

useComposer\Pcre\Regex;// this is useful when you are just interested in knowing if something matched// as it returns a bool instead of int(1/0) for match$bool = Regex::isMatch('{fo+}',$string);$result = Regex::match('{fo+}',$string);if ($result->matched) {something($result->matches); }$result = Regex::matchWithOffsets('{fo+}',$string);if ($result->matched) {something($result->matches); }$result = Regex::matchAll('{fo+}',$string);if ($result->matched &&$result->count >3) {something($result->matches); }$newString = Regex::replace('{fo+}','bar',$string)->result;$newString = Regex::replaceCallback('{fo+}',function ($match) {returnstrtoupper($match[0]); },$string)->result;$newString = Regex::replaceCallbackArray(['{fo+}' =>fn ($match) =>strtoupper($match[0])],$string)->result;

Note thatpreg_grep andpreg_split are only callable via thePreg class as they do not havecomplex return types warranting a specific result object.

See theMatchResult,MatchWithOffsetsResult,MatchAllResult,MatchAllWithOffsetsResult, andReplaceResult class sources for more details.

Restrictions / Limitations

Due to type safety requirements a few restrictions are in place.

  • matching usingPREG_OFFSET_CAPTURE is made available viamatchWithOffsets andmatchAllWithOffsets.You cannot pass the flag tomatch/matchAll.
  • Preg::split will also rejectPREG_SPLIT_OFFSET_CAPTURE and you should usesplitWithOffsetsinstead.
  • matchAll rejectsPREG_SET_ORDER as it also changes the shape of the returned matches. Thereis no alternative provided as you can fairly easily code around it.
  • preg_filter is not supported as it has a rather crazy API, most likely you should ratherusePreg::grep in combination with some loop andPreg::replace.
  • replace,replaceCallback andreplaceCallbackArray do not support an array$subject,only simple strings.
  • As of 2.0, the library always usesPREG_UNMATCHED_AS_NULL for matching, which offersmuchsaner/more predictable results. As of 3.0 the flag is also set forreplaceCallback andreplaceCallbackArray.

PREG_UNMATCHED_AS_NULL

As of 2.0, this library always uses PREG_UNMATCHED_AS_NULL for allmatch* andisMatch*functions. As of 3.0 it is also done forreplaceCallback andreplaceCallbackArray.

This means your matches will always contain all matching groups, either as null if unmatchedor as string if it matched.

The advantages in clarity and predictability are clearer if you compare the two outputs ofrunning this with and without PREG_UNMATCHED_AS_NULL in $flags:

preg_match('/(a)(b)*(c)(d)*/','ac',$matches,$flags);
no flagPREG_UNMATCHED_AS_NULL
array (size=4)array (size=5)
0 => string 'ac' (length=2)0 => string 'ac' (length=2)
1 => string 'a' (length=1)1 => string 'a' (length=1)
2 => string '' (length=0)2 => null
3 => string 'c' (length=1)3 => string 'c' (length=1)
4 => null
group 2 (any unmatched group preceding one that matched) is set to''. You cannot tell if it matched an empty string or did not match at allgroup 2 isnull when unmatched and a string if it matched, easy to check for
group 4 (any optional group without a matching one following) is missing altogether. So you have to check withisset(), but really you wantisset($m[4]) && $m[4] !== '' for safety unless you are very careful to check that a non-optional group follows itgroup 4 is always set, and null in this case as there was no match, easy to check for with$m[4] !== null

PHPStan Extension

To use the PHPStan extension if you do not usephpstan/extension-installer you can includevendor/composer/pcre/extension.neon in your PHPStan config.

The extension provides much better type information for $matches as well as regex validation where possible.

License

composer/pcre is licensed under the MIT License, see the LICENSE file for details.

About

PCRE wrapping library that offers type-safe preg_* replacements.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp