While building multi-tenancy packages for Laravel 5 I had to find out how to make the paths and namespaces dynamic.
This would involve:
- views; adding a template directory dynamically that is available in the root namespace
- lang; adding a language directory dynamically that is available in the root namespace
- routes; adding a routes file dynamically
- config; merging additional configuration files from a dynamic location
- vendor; allowing custom vendors and packages to be available from a dynamic location
views
Using a service provider you can use the following in your boot()
method for views to be available in the root namespace (view('your-view')
instead of view('package::your-view')
):
$this->app['view']->addLocation('/your/new/location');
lang
Using a service provider you can use the following in your boot()
method where $path
is the new path for your root namespace translations:
$app->bindShared('translation.loader', function($app) use ($path)
{
return new \Illuminate\Translation\FileLoader($app['files'], $path);
});
$app->bindShared('translator', function($app)
{
$translator = new \Illuminate\Translation\Translator($app['translation.loader'], $app['config']['app.locale']);
$translator->setFallback($app['config']['app.fallback_locale']);
return $translator;
});
routes
Routes is by far the easiest. Simply include them using a require_once
or by using the Laravel method: \File::requireOnce()
.
config
I used a directory that would allow a tenant to overrule core configs. Please advice there are no security nor sanity checks here so access should be limited.
Using a service provider you can use the following in your boot()
method
foreach (\File::allFiles('/path/to/configs') as $path) {
$key = \File::name($path);
$app['config']->set($key, array_merge(require $path, $app['config']->get($key, [])));
}
This will merge existing configurations by overruling their values with the provided config files.
vendor
Really interesting is the possibility to use dynamically loaded classes. In order to do this you will need to use the ClassLoader
addDirectories()
method in your service provider
\Illuminate\Support\ClassLoader::addDirectories(['/path/to/vendors']);
additional considerations
The above code can be implemented using service providers. In order for a server provider to work you must add them to the config/app.php
file under the providers
array. Not doing so will not enable any of the code in the service provider.