Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ant Path Matcher Laravel Package

dflydev/ant-path-matcher

PHP implementation of Ant-style path matching. Compile glob-like patterns using **, * and ? wildcards into matchers, then test paths against them. Useful for routing, file filtering, and access rules where simple prefix checks fall short.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

dflydev/ant-path-matcher is a headless, framework-agnostic utility: it compiles Ant-style glob patterns (? = one character, * = zero or more characters within a path segment, ** = zero or more path segments) and matches them against string paths. It has no I/O, no configuration, no service container coupling, and no global state. That makes it architecturally "free" — it can be bound behind a one-method interface in our domain or support layer without leaking a third-party type into application code.

The realistic use cases in a Laravel codebase are narrow but real:

  • Config-driven path allow/deny rules (middleware that exempts /api/**/health, **/_debug/**).
  • Multi-tenant or per-plan route/resource scoping where rules are authored by ops, not developers.
  • Asset, cache, and publish exclusion lists in build or deploy tooling.
  • Feature-flag targeting by URL/namespace (e.g., App\Modules\**\Listeners\*).

The critical architectural question is that Laravel already ships this: Str::is() accepts wildcard patterns, and Symfony\Component\Finder\Glob::toRegex() provides glob semantics. The only genuine capability gap is segment-awareness — in Ant semantics * does not cross /, while Laravel's Str::is('*.php', 'a/b/c.php') returns true because it naively expands * to .*. If our rules need "match one segment only" semantics, this package earns its place; if not, we are adding a dependency for ergonomics.

Integration feasibility

High. Installation is a single composer require dflydev/ant-path-matcher; there is no service provider, no publishable config, no migration, no facade, and no Laravel package discovery. Integration is roughly 20–40 lines: an application-owned PathMatcher interface, an adapter delegating to Dflydev\AntPathMatcher\AntPathMatcher, and a container binding. Testing is trivial because the unit is a pure function — no database, HTTP, or clock to fake.

The absence of Laravel auto-discovery is a mild positive here: it means the package cannot silently alter framework behavior, and it keeps our coupling surface to a single class.

Technical risk

Risk Severity Notes
Maintenance abandonment High 6 stars, 0 dependents, last release Jan 2023. Effectively a single-maintainer library with no downstream pressure to fix bugs.
No community triage High Zero dependents means edge-case bugs (Windows separators, trailing slashes, unicode) are unlikely to be reported or fixed upstream.
PHP version drift Medium A Jan-2023 release is unlikely to be validated against PHP 8.3/8.4; implicit-nullable and dynamic-property deprecations are plausible. Must be verified, not assumed.
ReDoS / pattern injection Medium Ant patterns are compiled to regex. If patterns are ever sourced from tenant config or user input, catastrophic backtracking and pathological patterns become an availability risk.
Semantic mismatch with Str::is Medium Migrating existing *-based rules to Ant semantics silently tightens matching (no crossing /), which can flip a deny-rule to a no-op — a security-relevant regression class.
Vendor lock-in Low ~200 lines of deterministic logic; a clean-room reimplementation is a plausible one-day task.

Net: low technical risk, non-trivial sustainability risk. The code is small enough that the real exposure is ownership, not correctness.

Key questions

  1. Which concrete requirement does this satisfy that Str::is() cannot — i.e., do we actually need segment-scoped *?
  2. Who owns the vendored copy if upstream goes dark — do we accept a fork-maintenance obligation, or wrap and reimplement?
  3. Are patterns always developer/ops-authored, or can tenants or end users supply them? (Determines whether we need input validation and a complexity ceiling.)
  4. What is the verified PHP support matrix, and does it pass our CI on 8.2/8.3/8.4 with deprecations treated as errors?
  5. Do any existing Str::is() rules need to keep their old, looser semantics? If so, we need two matchers, not one.
  6. Is case sensitivity and / vs \ separator handling on Windows deploy targets a requirement?

Integration Approach

Stack fit

Fits cleanly into Laravel 9–12 / PHP 8.1+. It is a leaf dependency with no transitive graph to speak of, so it will not conflict with framework or Symfony versions. It composes naturally with the container and with Laravel's config repository, so the recommended shape is:

  • App\Support\PathMatcher interface (our type, not theirs).
  • AntPathMatcherAdapter implementing it via the vendor class.
  • Bound as a singleton; patterns resolved from config/ and cached with the config cache.
  • All call sites depend on the interface, never the vendor namespace.

Migration path

  1. Inventory every existing Str::is(), fnmatch(), preg_match() or glob()-based path rule and record its current effective semantics (* crossing separators is the common surprise).
  2. Introduce the interface first, with an adapter that initially delegates to Str::is() — no behavior change, no new dependency.
  3. Swap the adapter to the Ant matcher behind a feature flag, with a differential test suite asserting old-vs-new outcomes across a fixture corpus of real paths.
  4. Ship and observe, then remove the flag; keep the differential fixtures as regression tests.

This sequencing decouples "we adopted a pattern-matching abstraction" from "we adopted this specific package," which is the whole point given the sustainability profile.

Compatibility

  • Semantics: Ant * and ? stop at /; Laravel's * does not. This is the single most likely source of production surprise and must be covered by the differential fixtures above.
  • Case sensitivity: Ant matching is case-sensitive by default; verify no rule relies on case-insensitive behavior (notably on case-insensitive filesystems in local dev).
  • Separators: validate behavior with leading /, trailing /, doubled separators, and Windows \ if any deploy target is Windows-based.
  • Input hygiene: normalize paths (trim, collapse separators, strip query strings) at the adapter boundary so semantics do not depend on caller discipline.
  • Return type: the library returns booleans; do not expose any richer PathMatcher/StringMatcher types from the vendor namespace across our boundary.

Sequencing

Phase 1: spike + differential harness against Str::is() (1–2 days). Phase 2: interface + adapter + container binding, feature-flagged. Phase 3: migrate call sites one at a time, highest-risk rules (security deny-lists) last and with explicit review. Phase 4: delete the flag, document the semantics in an ADR, and record the fork-maintenance decision.

Operational Impact

Maintenance

Low ongoing code maintenance, moderate ownership burden. There is nothing to configure and nothing to upgrade aggressively, but we should assume upstream will not ship PHP-version fixes. Concretely: pin a specific version, add a CI job that runs the dependency's test surface (or our own coverage of it) on every PHP minor we adopt, and record a standing decision to fork into app/Support if the package fails on a future PHP release. Treat this as a vendored utility with an owner, not as a maintained OSS dependency.

Support

No vendor support, no active issue triage. Support burden falls entirely on the owning team. Mitigate by keeping the surface to one interface, so the blast radius of a swap is a single file. Onboarding cost is genuinely low — the semantics are documented Ant conventions that most engineers recognize.

Scaling

Negligible runtime cost: boolean regex evaluation per pattern-path pair, no I/O, no allocation-heavy work. Two caveats at scale:

  • No evident regex caching in the original port — each match() call compiles. If a request evaluates dozens of rules, cache compiled results per (pattern, path) or precompile at boot when config is built.
  • Fan-out: matching 1 path against N patterns is O(N). Fine for tens; for hundreds of tenant rules, index patterns by literal prefix before matching.

Memory and CPU impact are immaterial relative to framework boot.

Failure modes

  • Silent over-permission (highest impact): a deny rule written with pre-migration * semantics becomes narrower under Ant semantics and stops matching paths it used to block. This is a security regression with no error signal — hence the differential fixtures and ordering deny-lists last.
  • Regex compilation errors on malformed patterns surface as exceptions at request time; validate patterns at config load, not at match time.
  • ReDoS if patterns are externally sourced; enforce pattern length/complexity limits and never accept tenant-authored patterns without validation.
  • PHP deprecation noise escalating to CI failure after a runtime upgrade; caught by the version-matrix job.
  • Abandonment: no failure event, just slow rot — addressed by the pin plus fork-on-trigger policy.

Ramp-up

Under a day for any PHP engineer. The domain knowledge required is Ant glob semantics, which is the only non-obvious part and should be captured in a short ADR alongside the differential test fixtures. No infrastructure, no credentials, no external services to provision — the onboarding story is a genuine strength of this package.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log