Skip to main content

Access control

Access control is your application's job. By default binding resolves any row — Polyslug does not own your tenant or publish state.

polyslugResolveQuery — the resolution gate

Override polyslugResolveQuery() to inject those scopes. A model outside the scope then resolves to a 404 that is indistinguishable from a nonexistent one — no existence oracle — and the gate is enforced uniformly across bound routes, the polymorphic resolver, and /go short links:

use Illuminate\Database\Eloquent\Builder;

public function polyslugResolveQuery(Builder $query): Builder
{
return $query->where('tenant_id', currentTenant()->id)->where('published', true);
}

The default implementation is a no-op, so this is opt-in — but for a multi-tenant or draft-carrying model it is the required isolation contract, not an optimization. Every resolution path funnels through it, including polyslugResolveByKey(), which is what makes the /go short-link route gated too. Since 0.18.7 polyslug:sitemap reads each configured type through it as well, so a row the gate hides is never submitted.

polyslugIsRoutable — the output filter

polyslugIsRoutable(?string $locale = null): bool is the companion for output. Return false to keep an unpublished model — or one specific locale — out of your hreflang sets and sitemaps:

public function polyslugIsRoutable(?string $locale = null): bool
{
return $this->status === 'published';
}

The two are complementary and you usually want both: polyslugResolveQuery() decides what a visitor may reach, polyslugIsRoutable() decides what you advertise. A draft filtered only from the sitemap is still reachable by anyone who guesses the URL. A draft blocked only at resolution stays out of the sitemap polyslug:sitemap writes, but a sitemap your own code builds still lists it unless polyslugIsRoutable() says no.

Do not rely on token opacity

An identity encoder chooses how much the URL reveals, but no encoder is an authorization check. A leaked or shared URL still carries a valid token, so the gate above is what decides whether it resolves.

See also the multi-tenant SaaS and marketplace recipes, which wire both hooks end to end.