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

Uri Laravel Package

psx/uri

psx/uri is a lightweight PHP library for parsing, normalizing, and manipulating URIs. It provides an object-oriented API for working with scheme, host, path, query, and fragment components, making URL handling in PHP applications simpler and more reliable.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require psx/uri

There is nothing to register. No service provider, no facade, no publishable config, no Artisan command. This is a plain-PHP library in the PSX\Uri namespace — you instantiate value objects directly and they are autoloaded by Composer like any other dependency.

Where to look first. Read src/Uri.php end-to-end; it is small, and it is the real documentation. Then skim src/Url.php, src/Urn.php, and src/UriInterface.php. There is no meaningful docs site for a package this size, so the class source and the PhpUnit fixtures in tests/ are what you should treat as the spec. Look at the constructor and toString() before anything else — everything else is getters over parsed components.

First use case. Replace ad-hoc parse_url() arrays with a typed object when you need to inspect and rebuild a URL: canonicalizing an inbound webhook/callback URL, pulling a fragment out of a front-end redirect target, or normalizing a URL before persisting it.

use PSX\Uri\Uri;
use PSX\Uri\Url;

$uri = new Uri('https://user:[email protected]:8443/a/b?x=1#frag');

$uri->getScheme();     // "https"
$uri->getAuthority();  // "user:[email protected]:8443"
$uri->getHost();       // "example.com"
$uri->getPort();       // 8443
$uri->getPath();       // "/a/b"
$uri->getQuery();      // "x=1"
$uri->getFragment();   // "frag"

(string) $uri;         // round-trips to the original string

If all you need is "is this a well-formed absolute URL", constructing a Url inside a try/catch is the shortest, most useful path — that is the first thing most Laravel apps will actually deploy.

Implementation Patterns

Primitives at the edges, value objects inside. Accept a string in controllers and form requests, hydrate to Uri/Url in your DTOs and domain services, and convert back to string before it crosses a persistence or queue boundary. This keeps serialization simple and avoids surprises with Laravel's job payload encoding.

Eloquent cast. Store the canonical string and return the value object:

class UriCast implements CastsAttributes
{
    public function get($model, $key, $value, $attributes): ?Uri
    {
        return $value === null ? null : new Uri($value);
    }

    public function set($model, $key, $value, $attributes): array
    {
        return [$key => $value === null ? null : (string) $value];
    }
}

Validation rule. Wrap the constructor to get a stricter "is this an absolute URL" check than Laravel's url rule, and throw ValidationException from message():

class AbsoluteUrl implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        try {
            new Url($value);
        } catch (\Throwable) {
            $fail('The :attribute must be a valid absolute URL.');
        }
    }
}

Use it alongside string and max:2048; do not rely on it alone for security decisions.

Normalization before storage. Lowercase the scheme and host, drop the default port, then (string) the object. Do this once in a Cast or in a form request's prepareForValidation(), not in every caller, and the rest of your app can compare URLs with === on the string.

Reference resolution. For link-rewriting and redirects, psx/uri implements RFC 3986 relative-reference resolution on Uri (confirm the exact method name in the version you pin). This is the real reason to choose it over parse_url — joining ../foo?x=1 against a base URL is fiddly to do correctly by hand.

API resources. Return (string) $this->url from toArray(). Clients expect JSON strings, not objects with scheme keys.

Comparison. Cast both sides to string and compare. There is no equality helper that will do the right thing for you; remember that scheme and host are case-insensitive per RFC but path is not, so normalize before comparing.

Gotchas and Tips

  • Ecosystem reality check. Four stars and zero dependents means no Stack Overflow answers, no Laravel integration, no blog posts. You are reading the source. For IDN/IRI handling, URI templates, or long-term maintenance guarantees, league/uri is the safer default in a Laravel codebase. Choose psx/uri when you want a tiny, zero-dependency parser and are comfortable owning the edge cases.
  • It is not a Laravel package. No service provider, no facade, no config/uri.php. Anything Laravel-shaped — casts, rules, helpers — you write yourself.
  • Parse failures throw. There is no false return like parse_url(). Catch exceptions at the boundary (form request, job constructor) and translate them into validation errors; do not let a UriException bubble out of an HTTP handler as a 500.
  • Query strings stay strings. getQuery() gives you the raw query, not an array. Call parse_str() yourself if you need components, and be aware it mangles repeated keys with [].
  • Port and authority nullability. getPort() returns null when absent; getAuthority() includes userinfo and port. Do not assume every getter returns a string, and do not assume a host exists on a relative URI.
  • Do not rely on mutators. These are immutable value objects with getters. If you need to change a component, rebuild the string and construct a new instance, or use a with* method only if you have verified it exists in your pinned version.
  • Serialization. Value objects do not survive serialize(), JSON columns, or queue payloads cleanly. Cast to string in jsonSerialize()/__serialize(), or store the string and hydrate on read.
  • Strict types and __toString(). Method calls and concatenation are fine, but mixing strict types and untyped signatures can bite when you pass Uri where string is expected. Cast explicitly.
  • Pin the version and check PHP compatibility. Release cadence is low; a composer.json PHP constraint can silently block an upgrade. Apache-2.0 is fine for commercial use — no licensing concerns.
  • Test the RFC 3986 examples. Write a small data-provider test over the RFC's normal/abnormal resolution cases and the URLs your app actually sees (unicode hosts, empty paths, default ports). That test suite is your real documentation and your upgrade safety net.
  • Debugging. var_dump((string) $uri) and diff against parse_url($uri) when a value looks wrong. Nine times out of ten the discrepancy is a normalization assumption you made, not a parser bug.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings