mremi/url-shortener
A framework-agnostic PHP library for shortening URLs through pluggable providers. It wraps popular URL-shortening services behind a simple API, supports multiple backends, and is easy to extend or integrate into existing PHP applications.
What this package actually is. mremi/url-shortener is a thin PHP client SDK that abstracts calls to third-party URL-shortening APIs (Bit.ly, the defunct Google Shortener, TinyURL, and similar). It is not a URL shortener: it does not store link mappings, issue redirects, allocate short codes, or capture click analytics. In a Laravel product, it can only ever occupy the "outbound call to a shortening vendor" slot. Everything that makes a shortener a product feature — persistence, redirect routing, branded domain, click tracking, expiry — remains ours to build. That framing matters more than any line of code in the repo.
Architecture fit. The library is framework-agnostic and Composer-installable, and its ProviderInterface abstraction is exactly the seam we would want if we were choosing between vendors. That is the strongest argument in its favour: it externalises the vendor decision behind a stable call site. The weakness is that the abstraction leaks. Provider-specific credential shapes (Bit.ly OAuth tokens, API versions, request payloads) still surface at the wiring layer, so "swap the provider" is a config change only if we never needed provider-specific capabilities in the first place — and the moment we want branded short domains, UTM injection, or click counts, we are back to vendor-specific code.
Integration feasibility. Low effort. Instantiating a provider and calling shorten() is a handful of lines; binding a configured instance as a Laravel singleton is trivial. There is no service provider, facade, or config publishing, so all wiring is manual — a minor annoyance, not a blocker. The real feasibility question is not integration cost but whether the package's supported provider set still exists. Several of its headline integrations have been retired at the API level (Google's shortener was shut down years ago; Bit.ly's older API versions have been superseded), and given the last release in September 2021, we should assume the shipped provider adapters target endpoints that may no longer be live until proven otherwise in a spike.
Technical risk. This is the crux, and the risk profile is poor:
Key questions for the team before proceeding:
ourco.link)? If yes, most adapters in this package are irrelevant and we should look at a first-party shortener or a service that supports custom domains.Verdict. The package is a reasonable reference implementation of the provider-abstraction pattern and a poor dependency. Its value is inversely proportional to how much of the shortener we need to own: at very low volume, single-vendor, internal-only links, an afternoon spike behind an internal interface is defensible. For anything customer-facing, branded, or at meaningful volume, the maintenance burden and provider-staleness risk outweigh the few hundred lines it saves.
Stack fit. Laravel is a non-issue in the sense that there is nothing Laravel-specific to fight: the package is plain PHP, installed via Composer, and bound into the container by hand. If the goal is a quick proof of concept, fit is good. If the goal is a durable production capability, fit is mediocre — the library brings its own HTTP transport, has no health checks, no retry policy, no rate-limit awareness, and no logging hooks, all of which Laravel's ecosystem would otherwise give us for free with Guzzle plus a small first-party client.
Recommended integration shape — adapter, not direct dependency. Do not let controllers or jobs touch Mremi\UrlShortener\* directly. Define an application-owned contract first:
App\Contracts\ShortLinkProvider -> create(string $url, array $opts): ShortLink
Implement it with an MremiShortLinkProvider adapter in this iteration, and leave room for a ShlinkShortLinkProvider or FirstPartyShortLinkProvider later. This is the single highest-leverage decision in the whole integration: it confines the abandoned-dependency risk to one small class that can be deleted, and it means the vendor decision and the library decision are decoupled. Everything else — persistence of the long/short mapping, idempotency keys, UTM handling, expiry — lives in our code where it is testable and supportable.
Migration path. Treat this as greenfield integration with a pre-planned exit, not as a migration. There is no incumbent to move off. The exit plan should be written at the same time as the integration: define what "we are leaving this provider" looks like, what data we retain (the long↔short mapping and creation timestamps, at minimum, so we can re-create or re-point links), and how existing short links keep resolving after any change. Note that the second half of that problem — preserving resolution of previously issued links — is not solvable with this package at all; it is a domain/DNS problem we own regardless.
Compatibility. Pin the Composer constraint tightly and verify against the target PHP version and Laravel major version in CI, not just locally; a 2021-era package predates several PHP minor releases and its transitive constraints may hold the framework back. Check specifically: (a) does it support PSR-18/PSR-17, or does it hard-require an older HTTP client that conflicts with Guzzle; (b) are its PHP ext-* and language-version requirements satisfied by our baseline; (c) does the chosen provider adapter call an endpoint that still responds. Item (c) is the one that most often fails and it is invisible in CI — it requires a live credentialled call.
Sequencing. Five steps, roughly one to two weeks of engineering time in total, most of it spent on the parts the package does not cover:
ShortLinkProvider, the Mremi… implementation, container binding, and configuration in config/services.php. Feature-flag the whole path.Maintenance. The honest number is not "zero, it's a dependency" — it is "we are now the upstream." With one release in 2021, no dependents, and a small star count, there is effectively no community maintaining this. Budget for a small but permanent maintenance tax: reviewing the adapter whenever the vendor changes its API, unpinning/patching during PHP and Laravel upgrades, and periodically asking whether the surviving code is still worth carrying. If a provider API change lands, our options are fork-and-patch or drop the dependency — both are cheapest if the adapter surface is small, which is the strongest argument for the wrapper described above.
Support. There is no vendor support and no meaningful community support. Internal ticket triage for short-link failures will land on whichever team owns the integration, with no upstream to escalate to. That is acceptable for internal-only links; it is a harder sell when the link in a customer's invoice footer is broken.
Scaling. Three ceilings, in order of when they bite:
Failure modes to plan for explicitly:
Ramp-up. For engineers, near-zero: the API surface is small and the patterns are familiar, and the wrapper keeps the unfamiliar part contained to one class. The ramp-up cost is borne by the TPM and the on-call rotation instead — specifically, understanding and owning the vendor relationship, quota model, pricing curve, and the eventual migration story. That asymmetry (cheap to build, expensive to own) is the single most important thing to communicate to stakeholders when this dependency is proposed. Treat the 2021 last-release date as the headline risk, not a footnote, and require the live-API spike before any commitment to build on it.
How can I help you explore Laravel packages today?