Reputation: 13
I recently started working with Symfony 4 and I'm looking forward to setting default database depending on subdomain.
It's about an application i need to deploy for multiple customers, and each one have their specific database.
i started working with connections like below. the idea would be to set once and for all the default connection with a variable from the env, but I don't know how.
Am I doing this the right way?
doctrine:
dbal:
default_connection: customer1
connections:
customer1:
url: '%env(DATABASE_CUSTOMER1_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
customer2:
url: '%env(DATABASE_CUSTOMER2_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
Upvotes: 1
Views: 1185
Reputation: 105
I've been there. You don't need to use separate connections, or environments. Adding a new environment would be adding a ton of cache files.
You can set environment variables at web server level depending in the subdomain, you can use VirtualDocumentRoot in apache, or just a server alias with wildcards in Nginx.
Define an environment variable for each subdomain in your webserver and you'll be able to use it in your config files.
Upvotes: 0
Reputation: 1
Did you try something like that ?
In your bootstrap :
// load all the .env files
// (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
$d = new Dotenv(false);
$d->loadEnv(dirname(__DIR__).'/.env');
$s = dirname(__DIR__).'/.env.'.filter_input(INPUT_SERVER, 'SERVER_NAME');
if (is_readable($s) ) {
$d->load($s);
}
And create different .env.server_name with
# your server_name database
DATABASE_URL=mysql://user:secret@localhost/mydb
Symfony Profiler
Upvotes: 0
Reputation: 512
Another way is to create separate environments and corresponding index_*.php
files to which you point your webserver. Pretty much create 2 new copies of application entry index.php
file - public/index_customer1.php
and public/index_customer2.php
. Inside you change environment which Symfony uses:
<?php
...
$kernel = new AppKernel('customer1', false); # or new AppKernel('customer2', false)
...
?>
And now you need to have separate configuration of Doctrine
for both of these environments. In config/packages/customer1/config.yml
:
imports:
- { resource: '../prod/' } # imports default prod env config
doctrine: # specify different database connection for whole env
dbal:
default_connection: default
connections:
default:
url: '%env(DATABASE_CUSTOMER1_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
and in config/packages/customer2/config.yml
imports:
- { resource: '../prod/' }
doctrine:
dbal:
default_connection: default
connections:
default:
url: '%env(DATABASE_CUSTOMER2_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
https://symfony.com/doc/master/configuration/environments.html
And you need to configure your webserver to point to different index.php
, based on domain.
Upvotes: 1
Reputation: 512
You are on the right track from configuration point of view. But keep in mind those connections are not triggered by the subdomain of the HTTP request but are simply just connecting to different database server based on call in actual PHP code.
Your env
DATABASE_CUSTOMER?_URL
variable should be specifying connection to MySQL instance, something like 'mysql://user:secret@localhost/mydb'
And doctrine configuration YAML should be formatted a bit differently and should include EntityManager
config.
doctrine:
dbal:
default_connection: customer1
connections:
customer1:
url: '%env(DATABASE_CUSTOMER1_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
customer2:
url: '%env(DATABASE_CUSTOMER2_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
orm:
default_entity_manager: customer1
entity_managers:
customer1:
connection: customer1
customer2:
connection: customer2
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
You now can specify which Connection/EntityManager you want to use. You can differentiate between them eg. in your Controllers by http host.
public function someAction(Request $request)
{
if ($request->getHttpHost() === 'customer2url.com') {
$em = $this->getDoctrine()->getManager('customer2');
} else {
$em = $this->getDoctrine()->getManager();
}
}
or call repository
$this->getDoctrine()->getRepository(Entity::class, 'customer1')
Upvotes: 0