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

Php Url Builder Laravel Package

codezero/php-url-builder

A lightweight PHP library for building and manipulating URLs programmatically. Compose paths, query strings, and parameters with a simple API, making it easier to generate consistent, readable links in Laravel or any PHP project.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require codezero/php-url-builder

The package is a single-purpose utility: it wraps PHP's parse_url() in an object that exposes the URL components (scheme, user, password, host, port, path, query, fragment) as getters and setters, then rebuilds a valid URL string. Start by opening src/UrlBuilder.php (or the equivalent class in src/) — the whole API lives there in a few hundred lines, and reading it takes five minutes. Because there's only one meaningful class, there is no service provider, facade, or config to worry about.

First use case to try in tinker:

use CodeZero\UrlBuilder\UrlBuilder;

$url = UrlBuilder::make('https://example.com/blog/article?utm_source=newsletter#comments');

$url->setHost('staging.example.com');
$url->setQueryParam('utm_medium', 'email'); // or addQuery/setQuery depending on the version

echo (string) $url;
// https://staging.example.com/blog/article?utm_source=newsletter&utm_medium=email#comments

That is the day-to-day value: you rarely need the full parser — you need to take a URL that came from config/database/a user, change one or two pieces, and hand it back as a string. Reach for this package whenever you'd otherwise be hand-rolling parse_url() + http_build_query() + sprintf() glue.

Implementation Patterns

Build outbound URLs from config, not string concatenation. Webhook callbacks, OAuth redirect URIs, and signed asset links all share a base URL that varies per environment. Construct once from config('services.foo.base_url') and mutate:

$redirect = UrlBuilder::make(config('app.url'))
    ->setPath('/auth/callback')
    ->setQueryParam('provider', $provider)
    ->toString();

Query-string manipulation for pagination and filters. This is where a URL builder beats http_build_query(): you can round-trip an incoming request URL, tweak one param, and preserve the rest.

$next = UrlBuilder::make($request->fullUrl())
    ->setQueryParam('page', $request->integer('page', 1) + 1);

Keep the resulting object as the canonical representation while you mutate, and only call toString() at the boundary (Blade, redirect()->to(), HTTP client). That keeps multi-step transformations readable.

Normalize URLs at the edges of your app. Put a small wrapper in app/Support/ so the vendor class doesn't leak everywhere:

final class Url
{
    public static function normalize(string $url): string
    {
        return UrlBuilder::make($url)
            ->setScheme('https')
            ->setPort(null)          // drop :80 / :443
            ->toString();
    }
}

This gives you a single seam to swap implementations later and a single place to add project rules (lowercase host, strip tracking params, force trailing slash).

Strip tracking/volatile params before caching or hashing. Because query params are addressable individually, you can remove utm_*, fbclid, and similar keys before using the URL as a cache key or signing payload.

Test assertions get easier. Compare component-by-component instead of brittle string equality:

$url = UrlBuilder::make('http://example.com:8080/a?b=c');
$this->assertSame('example.com', $url->getHost());
$this->assertSame(8080, $url->getPort());

Laravel integration is intentionally thin. There is no binding, so instantiate directly or app()->bind() a tiny factory if you want injectability. Don't wrap it in a facade for its own sake.

Gotchas and Tips

  • parse_url() is inherited, warts and all. Relative URLs (/foo/bar), protocol-relative URLs (//cdn.example.com/x), and malformed input can produce null components. Guard with a try/catch or a validity check before trusting the object, especially for user-supplied values.
  • Default ports are not auto-stripped. Setting port 80 on an https URL or 443 on http will render literally. Normalize ports yourself if you care about canonical output; also confirm whether setPort(null) clears it in your version.
  • Encoding behavior for query params is the usual PHP question. http_build_query() uses PHP_QUERY_RFC1738 by default (spaces become +). If you're signing URLs (AWS, Stripe, OAuth), you usually want RFC 3986 (%20). Check what the package's query-building path does and, if it isn't configurable, pre-encode or build the query yourself for signature-sensitive URLs.
  • Arrays and nested query params may not round-trip the way you expect. Verify ?tags[]=a&tags[]=b survives a parse → set → rebuild cycle; if not, flatten or serialize before handing off.
  • Trailing slashes and empty paths are preserved literally. https://example.com and https://example.com/ are different strings; decide on a convention and apply it in your wrapper, not scattered across call sites.
  • Check mutability semantics. If setters mutate and return $this, chaining is fine but you must clone before branching (e.g., building two variants from one base). If they're immutable and return new instances, the reverse. A quick dd() after a chain tells you which.
  • Fragment vs query ordering matters for anything that hashes the full URL. Confirm the rebuild order (query before #fragment) matches your expectation.
  • Version pinning. Last release was March 2023 with a small maintainer footprint and near-zero dependents. That's fine for a stateless parser, but pin the minor version and keep your own wrapper class so you can replace it with a maintained alternative (e.g., league/uri) without touching call sites. Treat it as a convenience layer, not infrastructure.
  • Extension point. If you need behavior the class doesn't expose, subclass it or compose it in your wrapper rather than forking — the class is small enough that composition costs almost nothing.
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.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment