PHP code example of saifulferoz / multi-tenancy-bundle
1. Go to this page and download the library: Download saifulferoz/multi-tenancy-bundle library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
saifulferoz / multi-tenancy-bundle example snippets
use Feroz\MultiTenancyBundle\Doctrine\Attribute\TenantShared;
use Feroz\MultiTenancyBundle\Tenant\TenantInterface;
#[ORM\Entity]
#[TenantShared] // omain label
#[ORM\Column]
public bool $active = true;
public function getId(): string|int { return $this->id; }
public function getIdentifier(): string { return $this->identifier; }
public function isActive(): bool { return $this->active; }
}
use Feroz\MultiTenancyBundle\Doctrine\Attribute\TenantAware;
use Feroz\MultiTenancyBundle\Doctrine\Attribute\TenantShared;
use Feroz\MultiTenancyBundle\Doctrine\TenantOwnedTrait;
use Feroz\MultiTenancyBundle\Security\TenantOwnedInterface;
#[ORM\Entity]
#[TenantAware] // scoped to one tenant
class Invoice implements TenantOwnedInterface
{
use TenantOwnedTrait; // column + accessor
}
#[ORM\Entity]
#[TenantShared] // global reference data
class Currency {}
public function __construct(private TenantContextInterface $tenants) {}
public function index(): Response
{
$tenant = $this->tenants->getTenant(); // throws if none resolved
}
$this->tenants->runFor($tenant, function () {
// reads and writes are scoped to $tenant here
});
use Feroz\MultiTenancyBundle\Security\TenantMembershipInterface;
use Feroz\MultiTenancyBundle\Security\TenantMembershipProviderInterface;
final class MembershipProvider implements TenantMembershipProviderInterface
{
public function findMembership(
string $userIdentifier,
TenantInterface $tenant,
): ?TenantMembershipInterface {
// null means "not a member here", which reads as "not authenticated
// here" — that is the intended meaning, not an error.
return $this->repository->findOneBy([
'user' => $userIdentifier,
'tenant' => $tenant->getId(),
]);
}
}
interface TenantMembershipInterface
{
public function getUserIdentifier(): string;
public function getTenantId(): string|int;
/** @return list<string> tenant-local role names */
public function getRoles(): array;
/** @return list<string> effective permissions, already flattened */
public function getPermissions(): array;
public function isActive(): bool;
}
$this->denyAccessUnlessGranted('post.publish', $post); // yes
$this->denyAccessUnlessGranted('ROLE_EDITOR'); // no
use Feroz\MultiTenancyBundle\Security\TenantOwnedInterface;
#[ORM\Entity]
#[TenantAware]
class Post implements TenantOwnedInterface
{
#[ORM\Column(name: 'tenant_id')]
public ?int $tenantId = null;
public function getTenantId(): string|int|null
{
return $this->tenantId;
}
}
use Feroz\MultiTenancyBundle\Security\Api\TenantIssuerAware;
class Tenant implements TenantInterface, TenantIssuerAware
{
#[ORM\Column(nullable: true)]
public ?string $issuer = null; // https://kc.example.com/realms/acme
public function getIssuer(): ?string { return $this->issuer; }
}
final class PathPrefixTenantResolver implements TenantResolverInterface
{
public function __construct(private TenantRegistryInterface $registry) {}
public function supports(ResolutionContext $context): bool
{
// No Request outside HTTP — console commands and message handlers
// share this interface, so never assume one exists.
return $context->isHttp();
}
public function resolve(ResolutionContext $context): ?TenantInterface
{
if (!preg_match('#^/t/([a-z0-9-]+)#', $context->request->getPathInfo(), $m)) {
return null; // "not applicable" — try the next resolver
}
return $this->registry->findByIdentifier($m[1]);
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.