Download the PHP package rasuvaeff/yii3-tenancy without Composer
On this page you can find all versions of the php package rasuvaeff/yii3-tenancy. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download rasuvaeff/yii3-tenancy
More information about rasuvaeff/yii3-tenancy
Files in rasuvaeff/yii3-tenancy
Package yii3-tenancy
Short Description Multi-tenancy core for Yii3: tenant resolution, request context, and scoping primitives
License BSD-3-Clause
Homepage https://github.com/rasuvaeff/yii3-tenancy
Informations about the package yii3-tenancy
rasuvaeff/yii3-tenancy
Multi-tenancy core for Yii3: tenant resolution from the request
(header/subdomain/path), a request-scoped CurrentTenant context, and scoping
primitives. Deliberately no ORM auto-scoping magic — explicit primitives
and recipes instead.
Using an AI coding assistant? llms.txt contains a compact API reference you can share with the model. Contributors: see AGENTS.md. Projects using the llm/skills Composer plugin also get this package's agent skill synced into
.agents/skills/automatically on install.
Requirements
| Requirement | Version |
|---|---|
| PHP | 8.3 – 8.5 |
| PSR-7 / PSR-15 / PSR-17 / PSR-16 | any implementation |
Installation
For persistent tenant storage add the DB backend (planned:
rasuvaeff/yii3-tenancy-db) or bind your own TenantProvider.
Usage
Resolution middleware
Place it in the middleware pipeline before authentication — the tenant usually determines the user store. On success the tenant is published twice:
CurrentTenantservice (constructor-inject it anywhere);Tenant::classrequest attribute.
Unresolved/unknown key → 404; suspended tenant → 403. Both are policies
(TenantPolicy::Reject | TenantPolicy::PassThrough).
Resolvers
| Resolver | Source | Example |
|---|---|---|
HeaderTenantResolver |
X-Tenant-Id header (configurable) |
X-Tenant-Id: acme |
SubdomainTenantResolver |
first label under a configured base domain | acme.example.com |
PathTenantResolver |
first segment after a configured prefix | /t/acme/dashboard |
CompositeTenantResolver |
chain, first non-null wins | header, then subdomain |
Every resolver validates the extracted key against Tenant::isValidId()
(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}\z/) and returns null on mismatch —
keys taken from requests are untrusted input. Nested subdomains
(a.b.example.com) and lookalike hosts (acmeexample.com) resolve to null.
Reading the current tenant
For console/test contexts where one process handles several tenants use
RequestCurrentTenant::override().
Tenant-scoped cache
clear()delegates to the inner cache and wipes all tenants — PSR-16 has no prefix-scoped clear. Do not call it in tenant-scoped code paths.
DI configuration (Yii3)
Ships config/di.php + config/params.php via config-plugin. The core
binds CurrentTenant, the resolvers, and the middleware. TenantProvider
is deliberately not bound — exactly one source binds it: a backend package
or your application:
Override params as needed:
Recipes: wiring into the rasuvaeff/* ecosystem
Components
Tenant
| Property | Type | Description |
|---|---|---|
id |
string |
validated: /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}\z/ |
name |
string |
optional display name |
status |
TenantStatus |
Active (default) / Suspended |
attributes |
array<string, mixed> |
free-form tenant metadata |
CurrentTenant / RequestCurrentTenant
Readers depend on the CurrentTenant interface (get(), find(),
isResolved()); the middleware depends on the concrete RequestCurrentTenant
(set() once per request, override() for console/tests).
TenantResolutionMiddleware
| Parameter | Type | Default | Description |
|---|---|---|---|
resolver |
TenantResolver |
— | key extraction |
provider |
TenantProvider |
— | key → Tenant lookup |
currentTenant |
RequestCurrentTenant |
— | publication target |
responseFactory |
ResponseFactoryInterface |
— | builds 404/403 |
unresolvedPolicy |
TenantPolicy |
Reject |
unresolved/unknown key |
suspendedPolicy |
TenantPolicy |
Reject |
suspended tenant |
Security
- Tenant keys extracted from requests are untrusted input — every resolver validates against a strict whitelist pattern before lookup.
- Subdomain resolution matches only against the configured base domain, never
the raw
Hostvalue alone; nested labels are rejected. - There is no implicit "default tenant" fallback — unresolved requests are
rejected unless you explicitly opt into
passthrough. - The package performs no I/O, SQL, or shell access itself.
Examples
See examples/ for a runnable script.
| Script | Shows | Needs server? |
|---|---|---|
resolve-tenant.php |
Resolution, request attribute, 404/403 policies | no |
Development
No PHP/Composer on the host — run in Docker via the composer:2 image:
Or with Make: make build, make cs-fix, make psalm, make test.
License
BSD-3-Clause. See LICENSE.md.
All versions of yii3-tenancy with dependencies
psr/http-factory Version ^1.0
psr/http-message Version ^2.0
psr/http-server-handler Version ^1.0
psr/http-server-middleware Version ^1.0
psr/simple-cache Version ^3.0