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

Splat Laravel Package

phlak/splat

Splat is a lightweight PHP library for matching strings against wildcard patterns. It provides simple, expressive helpers for route-style matching, capturing wildcard segments, and filtering paths or values, making it useful for routing, file matching, and other pattern-based tasks.

Deep Wiki
Context7

Getting Started

phlak/splat is a small, dependency-light, static utility for matching strings against glob-like patterns. It does not touch the filesystem — think fnmatch() / Laravel's Str::is(), not glob().

Install and verify

composer require phlak/splat
composer show phlak/splat   # confirm PHP constraint and namespace

Where to look first

  1. vendor/phlak/splat/README.md — the pattern-syntax table is the source of truth (wildcards, character classes, brace expansion).
  2. The public API is tiny; expect static methods on PHLAK\Splat\Splat: match(), filter(), and capture().
  3. Skim the tests in vendor/phlak/splat/tests for edge-case behavior (anchoring, separators, escaping) before relying on it in production.

First use case — filter or validate a list of filenames/keys:

use PHLAK\Splat\Splat;

Splat::match('*.php', 'index.php');                        // true
Splat::match('*.php', 'index.txt');                        // false

Splat::filter('*.md', [
    'README.md',
    'composer.json',
    'CHANGELOG.md',
]);                                                        // ['README.md', 'CHANGELOG.md']

If your real problem is "find files on disk," pair Splat with Symfony Finder or Laravel's File facade for traversal, and use Splat only to match the resulting paths.

Implementation Patterns

Custom Laravel validation rule

Wrap match() in a rule so pattern-based validation is reusable and testable:

use Illuminate\Contracts\Validation\Rule;
use PHLAK\Splat\Splat;

class MatchesPattern implements Rule
{
    public function __construct(private string $pattern) {}

    public function passes($attribute, $value): bool
    {
        return is_string($value) && Splat::match($this->pattern, $value);
    }

    public function message(): string
    {
        return 'The :attribute must match the pattern ' . $this->pattern;
    }
}

Collection pipelines

Splat's filter() is convenient, but inside a larger chain it is often cleaner to treat match() as the predicate:

$matching = collect($files)
    ->filter(fn (string $f) => Splat::match($pattern, $f))
    ->values();

Extracting structured segments with capture()

Use this for filenames, cache keys, or route-like strings where the wildcard portion is the value you care about:

// Treat capture() as returning the wildcard substrings, in order.
[$slug] = Splat::capture('*.blade.php', 'welcome.blade.php');

// Structured names: 2024-12-06-report.pdf
[$year, $month, $day, $name] = Splat::capture(
    '*-*-*-*.pdf',
    '2024-12-06-report.pdf'
);

Always guard against a failed capture (empty array) before destructuring user input.

Middleware / path exclusion lists

A common day-to-day pattern is centralizing "skip these paths" logic:

protected array $except = ['health*', 'admin/**', '*.well-known*'];

public function handle($request, Closure $next)
{
    foreach ($this->except as $pattern) {
        if (Splat::match($pattern, ltrim($request->path(), '/'))) {
            return $next($request);
        }
    }

    // ...
}

Normalize paths once (leading slash, \ → /) before matching.

Configuration key matching

Useful for filtering flat config arrays exported from config() or .env-style maps:

$stripeKeys = Splat::filter('services.stripe.*', array_keys($flatConfig));

Encapsulate behind your own service

Splat is static-only and intentionally thin. If you use it in many places, wrap it:

final class PatternMatcher
{
    public function matches(string $pattern, string $value): bool
    {
        return Splat::match($pattern, $value);
    }
}

This gives you one place to swap in fnmatch() or Symfony's Glob later, and one place to normalize separators and case.

Integration tips

  • Prefer Splat::filter() for one-off array filtering and match() inside existing loops/pipelines.
  • Keep patterns in config or constants rather than inline strings so they can be tested.
  • For large input sets (thousands of paths per request), benchmark before using it in a hot loop — see gotchas.

Gotchas and Tips

  • It is not glob(). No filesystem access, no hidden-file rules, no directory walking. Dotfiles are matched by * because that is just a character; if you want shell-like dotfile exclusion, filter manually.
  • Anchoring. Patterns generally must match the entire subject. If you want "contains" semantics, wrap the pattern: *foo*. Confirm in the README/tests, and write a test for the exact behavior you depend on.
  • Directory separators. Determine whether * crosses / (and whether ** exists for recursive segments). If you're matching paths, normalize \ to / on Windows and test mixed separators explicitly.
  • Escaping literals. If your patterns can contain user data, escape *, ?, {, }, [, ], and the escape character itself. Otherwise a crafted input can broaden a match unexpectedly. Do not treat patterns as security allowlists without understanding this.
  • Brace expansion is combinatorial. {a,b}{c,d}{e,f} expands multiplicatively. Keep brace sets small and avoid building patterns from unbounded user input.
  • Case sensitivity. Expect case-sensitive, byte-wise matching. Lowercase both pattern and subject if you need case-insensitive behavior, or wrap the call.
  • Greedy wildcards in capture(). Patterns like *.* are ambiguous. Assert the exact capture shape with a test before using it to parse filenames.
  • Failed captures. capture() can return an empty array or fewer elements than expected. Validate length before destructuring.
  • Performance. The library converts globs to regex internally. In hot paths or when filtering thousands of strings, either cache the compiled form (if exposed) or pre-filter with a cheaper check (extension, prefix) before calling Splat.
  • Path traversal. ../ is just characters to Splat. If patterns gate file access, resolve and validate the real path separately.
  • Maintenance surface. Last release December 2024, MIT, ~100 stars. It's stable and small; if you hit a quirk, vendoring or forking is realistic. Pin the version in composer.json and cover your usage with tests so an upstream change is visible.
  • Debugging. When a match fails unexpectedly, reduce the pattern to the smallest failing case (*, ?, one brace, one character class at a time). Most issues are anchoring, separator handling, or unescaped specials — not the library itself.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource