mirror of
https://github.com/stancl/tenancy-docs.git
synced 2025-12-12 10:14:03 +00:00
510 lines
20 KiB
HTML
510 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta name="description" content="Tenancy Initialization with stancl/tenancy — A Laravel multi-database tenancy package that respects your code..">
|
|
|
|
<meta property="og:site_name" content="stancl/tenancy documentation"/>
|
|
<meta property="og:title" content="Tenancy Initialization | stancl/tenancy documentation"/>
|
|
<meta property="og:description" content="Tenancy Initialization with stancl/tenancy — A Laravel multi-database tenancy package that respects your code.."/>
|
|
<meta property="og:url" content="https://tenancy.samuelstancl.me/docs/2.x/tenancy-initialization"/>
|
|
<meta property="og:image" content="/assets/img/logo.png"/>
|
|
<meta property="og:type" content="website"/>
|
|
|
|
<meta name="twitter:image:alt" content="stancl/tenancy documentation">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
|
|
|
|
<title>Tenancy Initialization | stancl/tenancy documentation</title>
|
|
|
|
<link rel="home" href="https://tenancy.samuelstancl.me/docs">
|
|
<link rel="icon" href="/favicon.ico">
|
|
|
|
|
|
<!-- Insert analytics code here -->
|
|
|
|
<link href="https://fonts.googleapis.com/css?family=Nunito+Sans:300,300i,400,400i,700,700i,800,800i" rel="stylesheet">
|
|
<link rel="stylesheet" href="/assets/build/css/main.css?id=0e3d47a146ef55ad0760">
|
|
|
|
</head>
|
|
|
|
<body class="flex flex-col justify-between min-h-screen bg-grey-lightest text-grey-darkest leading-normal font-sans">
|
|
<header class="flex items-center shadow bg-white border-b h-24 mb-8 py-4" role="banner">
|
|
<div class="container flex items-center max-w-4xl mx-auto px-4 lg:px-8">
|
|
<div class="flex items-center">
|
|
<a href="/" title="stancl/tenancy documentation home" class="inline-flex items-center">
|
|
|
|
|
|
<h1 class="text-lg md:text-2xl text-blue-darkest font-semibold hover:text-blue-dark my-0 pr-4">stancl/tenancy documentation</h1>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="flex flex-1 justify-end items-center text-right md:pl-10">
|
|
</div>
|
|
|
|
<div class="flex flex-1 justify-end items-center text-right md:pl-10">
|
|
<select id="versionSelect">
|
|
<option
|
|
value="/https://tenancy.samuelstancl.me/docs1.x"
|
|
>
|
|
1.x
|
|
</option>
|
|
<option
|
|
value="/https://tenancy.samuelstancl.me/docs2.x"
|
|
selected
|
|
>
|
|
2.x (beta)
|
|
</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<button class="flex justify-center items-center bg-blue border border-blue h-10 mr-4 px-5 rounded-full lg:hidden focus:outline-none"
|
|
onclick="navMenu.toggle()"
|
|
>
|
|
<svg id="js-nav-menu-show" xmlns="http://www.w3.org/2000/svg"
|
|
class="fill-current text-white h-9 w-4" viewBox="0 0 32 32"
|
|
>
|
|
<path d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2 s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2 S29.104,22,28,22z"/>
|
|
</svg>
|
|
|
|
<svg id="js-nav-menu-hide" xmlns="http://www.w3.org/2000/svg"
|
|
class="hidden fill-current text-white h-9 w-4" viewBox="0 0 36 30"
|
|
>
|
|
<polygon points="32.8,4.4 28.6,0.2 18,10.8 7.4,0.2 3.2,4.4 13.8,15 3.2,25.6 7.4,29.8 18,19.2 28.6,29.8 32.8,25.6 22.2,15 "/>
|
|
</svg>
|
|
</button>
|
|
|
|
</header>
|
|
|
|
<main role="main" class="w-full flex-auto">
|
|
<section class="container max-w-4xl mx-auto px-6 md:px-8 py-4">
|
|
<div class="flex flex-col lg:flex-row">
|
|
<nav id="js-nav-menu" class="nav-menu hidden lg:block">
|
|
<ul class="list-reset my-0">
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/getting-started"
|
|
class="lvl0 nav-menu__item hover:text-blue"
|
|
>
|
|
Getting Started
|
|
</a>
|
|
|
|
|
|
<ul class="list-reset my-0">
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/installation"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Installation
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/storage-drivers"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Storage Drivers
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/difference-between-this-package-and-others"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
This Package vs Others
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/configuration"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Configuration
|
|
</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/usage"
|
|
class="lvl0 nav-menu__item hover:text-blue"
|
|
>
|
|
Usage
|
|
</a>
|
|
|
|
|
|
<ul class="list-reset my-0">
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/creating-tenants"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Creating Tenants
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/tenant-routes"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Tenant Routes
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/tenant-storage"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Tenant Storage
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/tenant-manager"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Tenant Manager
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/console-commands"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Console Commands
|
|
</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/digging-deeper"
|
|
class="lvl0 nav-menu__item hover:text-blue"
|
|
>
|
|
Digging Deeper
|
|
</a>
|
|
|
|
|
|
<ul class="list-reset my-0">
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/middleware-configuration"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Middleware Configuration
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/custom-database-names"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Custom Database Names
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/filesystem-tenancy"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Filesystem Tenancy
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/jobs-queues"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Jobs & Queues
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/event-system"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Event System
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/tenancy-initialization"
|
|
class="lvl1 active font-semibold text-blue nav-menu__item hover:text-blue"
|
|
>
|
|
Tenancy Initialization
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/application-testing"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Application Testing
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/writing-storage-drivers"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Writing Storage Drivers
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/development"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Development
|
|
</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/integrations"
|
|
class="lvl0 nav-menu__item hover:text-blue"
|
|
>
|
|
Integrations
|
|
</a>
|
|
|
|
|
|
<ul class="list-reset my-0">
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/telescope"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Telescope
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/horizon"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Horizon
|
|
</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<p class="nav-menu__item text-grey-dark">Tips</p>
|
|
|
|
|
|
<ul class="list-reset my-0">
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/https-certificates"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
HTTPS Certificates
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/misc-tips"
|
|
class="lvl1 nav-menu__item hover:text-blue"
|
|
>
|
|
Misc
|
|
</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/stay-updated"
|
|
class="lvl0 nav-menu__item hover:text-blue"
|
|
>
|
|
Stay Updated
|
|
</a>
|
|
|
|
</li>
|
|
<li class="list-reset pl-4">
|
|
|
|
<a href="https://tenancy.samuelstancl.me/docs/2.x/https://github.com/stancl/tenancy"
|
|
class="lvl0 nav-menu__item hover:text-blue"
|
|
>
|
|
GitHub
|
|
</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<div class="w-full lg:w-3/5 break-words pb-16 lg:pl-4" v-pre>
|
|
<h1 id="tenancy-initialization">Tenancy Initialization</h1>
|
|
<p>Tenancy can be initialized by calling <code>tenancy()->init()</code>. The <code>InitializeTenancy</code> middleware calls this method automatically.</p>
|
|
<p>You can end a tenancy session using <code>tenancy()->end()</code>. This is useful if you need to run multiple tenant sessions or a mixed tenant/non-tenant session in a single request/command.</p>
|
|
<p>The <code>tenancy()->init()</code> method calls <code>bootstrap()</code>.</p>
|
|
<p>This method switches database connection, Redis connection (if Redis tenancy is enabled), cache and filesystem root paths.</p>
|
|
<p>This page goes through the code that actually makes this happen. You don't have to read this page to use the package, but it will give you insight into the magic that's happening in the background, so that you can be more confident in it.</p>
|
|
<h2 id="database-tenancy">Database tenancy</h2>
|
|
<p><code>bootstrap()</code> runs the following method:</p>
|
|
<pre><code class="language-php">public function switchDatabaseConnection()
|
|
{
|
|
$this->database->connect($this->getDatabaseName());
|
|
}</code></pre>
|
|
<p>If <code>tenancy.database_name_key</code> is set and present in the current tenant's data, the <code>getDatabaseName()</code> returns the stored database_name. Otherwise it returns the prefix + uuid + suffix.</p>
|
|
<pre><code class="language-php">public function getDatabaseName($tenant = []): string
|
|
{
|
|
$tenant = $tenant ?: $this->tenant;
|
|
if ($key = $this->app['config']['tenancy.database_name_key']) {
|
|
if (isset($tenant[$key])) {
|
|
return $tenant[$key];
|
|
}
|
|
}
|
|
return $this->app['config']['tenancy.database.prefix'] . $tenant['uuid'] . $this->app['config']['tenancy.database.suffix'];
|
|
}</code></pre>
|
|
<p>This is passed as an argument to the <code>connect()</code> method. This method creates a new database connection and sets it as the default one.</p>
|
|
<pre><code class="language-php">public function connect(string $database)
|
|
{
|
|
$this->createTenantConnection($database);
|
|
$this->useConnection('tenant');
|
|
}
|
|
|
|
public function createTenantConnection(string $database_name)
|
|
{
|
|
// Create the `tenant` database connection.
|
|
$based_on = config('tenancy.database.based_on') ?: config('database.default');
|
|
config()->set([
|
|
'database.connections.tenant' => config('database.connections.' . $based_on),
|
|
]);
|
|
// Change DB name
|
|
$database_name = $this->getDriver() === 'sqlite' ? database_path($database_name) : $database_name;
|
|
config()->set(['database.connections.tenant.database' => $database_name]);
|
|
}
|
|
|
|
public function useConnection(string $connection)
|
|
{
|
|
// $this->database = Illuminate\Database\DatabaseManager
|
|
$this->database->setDefaultConnection($connection);
|
|
$this->database->reconnect($connection);
|
|
}</code></pre>
|
|
<h2 id="redis-tenancy">Redis tenancy</h2>
|
|
<p>The <code>bootstrap()</code> method calls <code>setPhpRedisPrefix()</code> if <code>tenancy.redis.tenancy</code> is <code>true</code>.</p>
|
|
<p>This method cycles through the <code>tenancy.redis.prefixed_connections</code> and sets their prefix to <code>tenancy.redis.prefix_base</code> + uuid.</p>
|
|
<pre><code class="language-php">public function setPhpRedisPrefix($connections = ['default'])
|
|
{
|
|
// [...]
|
|
foreach ($connections as $connection) {
|
|
$prefix = $this->app['config']['tenancy.redis.prefix_base'] . $this->tenant['uuid'];
|
|
$client = Redis::connection($connection)->client();
|
|
try {
|
|
// [...]
|
|
$client->setOption($client::OPT_PREFIX, $prefix);
|
|
} catch (\Throwable $t) {
|
|
throw new PhpRedisNotInstalledException();
|
|
}
|
|
}
|
|
}</code></pre>
|
|
<h2 id="cache-tenancy">Cache tenancy</h2>
|
|
<p><code>bootstrap()</code> calls <code>tagCache()</code> which replaces the <code>'cache'</code> key in the service container with a different <code>CacheManager</code>.</p>
|
|
<pre><code class="language-php">public function tagCache()
|
|
{
|
|
// [...]
|
|
$this->app->extend('cache', function () {
|
|
return new \Stancl\Tenancy\CacheManager($this->app);
|
|
});
|
|
}</code></pre>
|
|
<p>This <code>CacheManager</code> forwards all calls to the inner store, but also adds tag which "scope" the cache and allow for selective cache clearing:</p>
|
|
<pre><code class="language-php">class CacheManager extends BaseCacheManager
|
|
{
|
|
public function __call($method, $parameters)
|
|
{
|
|
$tags = [config('tenancy.cache.tag_base') . tenant('uuid')];
|
|
if ($method === 'tags') {
|
|
if (\count($parameters) !== 1) {
|
|
throw new \Exception("Method tags() takes exactly 1 argument. {count($parameters)} passed.");
|
|
}
|
|
$names = $parameters[0];
|
|
$names = (array) $names; // cache()->tags('foo') https://laravel.com/docs/5.7/cache#removing-tagged-cache-items
|
|
return $this->store()->tags(\array_merge($tags, $names));
|
|
}
|
|
return $this->store()->tags($tags)->$method(...$parameters);
|
|
}
|
|
}</code></pre>
|
|
<h2 id="filesystem-tenancy">Filesystem tenancy</h2>
|
|
<p><code>bootstrap()</code> calls <code>suffiexFilesystemRootPaths()</code>. This method changes <code>storage_path()</code> and the roots of disks listed in <code>config('tenancy.filesystem.disks)</code>. You can read more about this on the <a href="https://tenancy.samuelstancl.me/docs/2.x/filesystem-tenancy">Filesystem Tenancy</a> page.</p>
|
|
<pre><code class="language-php">public function suffixFilesystemRootPaths()
|
|
{
|
|
// [...]
|
|
$suffix = $this->app['config']['tenancy.filesystem.suffix_base'] . tenant('uuid');
|
|
// storage_path()
|
|
$this->app->useStoragePath($old['path'] . "/{$suffix}");
|
|
// Storage facade
|
|
foreach ($this->app['config']['tenancy.filesystem.disks'] as $disk) {
|
|
// [...]
|
|
if ($root = \str_replace('%storage_path%', storage_path(), $this->app['config']["tenancy.filesystem.root_override.{$disk}"])) {
|
|
Storage::disk($disk)->getAdapter()->setPathPrefix($root);
|
|
} else {
|
|
$root = $this->app['config']["filesystems.disks.{$disk}.root"];
|
|
Storage::disk($disk)->getAdapter()->setPathPrefix($root . "/{$suffix}");
|
|
}
|
|
}
|
|
// [...]
|
|
}</code></pre> </div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<script src="/assets/build/js/main.js?id=559633482baac87a89b5"></script>
|
|
|
|
<script>
|
|
const navMenu = {
|
|
toggle() {
|
|
const menu = document.getElementById('js-nav-menu');
|
|
menu.classList.toggle('hidden');
|
|
menu.classList.toggle('lg:block');
|
|
document.getElementById('js-nav-menu-hide').classList.toggle('hidden');
|
|
document.getElementById('js-nav-menu-show').classList.toggle('hidden');
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<footer class="bg-white text-center text-sm mt-12 py-4" role="contentinfo">
|
|
<ul class="flex flex-col md:flex-row justify-center list-reset">
|
|
<li class="md:mr-2">
|
|
© <a href="https://github.com/stancl" title="Samuel Štancl">Samuel Štancl</a> 2019.
|
|
</li>
|
|
|
|
<li>
|
|
Built with <a href="http://jigsaw.tighten.co" title="Jigsaw by Tighten">Jigsaw</a>
|
|
and <a href="https://tailwindcss.com" title="Tailwind CSS, a utility-first CSS framework">Tailwind CSS</a>.
|
|
</li>
|
|
</ul>
|
|
</footer>
|
|
<script>
|
|
document.getElementById('versionSelect').addEventListener('change', function () {
|
|
window.location = document.getElementById('versionSelect').value;
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|