Ask your Symfony questions! Pay money and get answers fast! (more info)

How to use multiple databases for different customers? Symfony

  • SOLVED

Hi all,

I'm expanding my current application for multiple customers use in Symfony 1.4 using Doctrine. I want to use the same application for all customers. But for security reasons every customer needs to have their own database and login screen.

Current plan:
1. Customers from their specific IP range are directed to their own ip address using SSH
2. Symfony routes trafic to proper login screen based on which IP is requested
3. The correct customer database is selected en used in the application

How do I achieve step 2 and 3?

Thanks!

Lucas

Extra info :

3. For different databases I need to define different connections in the databases.yml, right?. How do I do this and does this affect the rest of my current application code? Do I have to rebuild all modules? Or does everything go automatically after the database selection in the beginnig?

Answers (4)

2010-04-14

Gordon Franke answers:

You can change a dns string from you database.yml with the following code in your
<em>config/ProjectConfiguration.class.php</em>

public function setup()
{
$dispatcher = $this->getEventDispatcher();
$dispatcher->connect('context.load_factories', array($this, 'dynamicInterredDatabase'));
}

static public function dynamicInterredDatabase(sfEvent $event)
{
// get interred connection configuration
$database = sfContext::getInstance()
->getDatabaseManager()
->getDatabase('interred');

// $dsn = $database->getParameter('dsn');
$newDNS = '...';
$database->setParameter('dsn', $newDns);
}


You don't need to define extra connections in your database.yml file
You can define in your schema file that some of your models use another connections (e.q. global user table)


---
# global
options:
connection: doctrine
type: INNODB
collate: utf8_unicode_ci
charset: utf8

Content:
# override default
connection: interred


Lucas van Oostrum comments:

Thanks for you quick reply, I added some extra info for point 3. In wich file do I put your answer? ProjectConfiguration?


Gordon Franke comments:

I hope this will fix your problems ;)


Lucas van Oostrum comments:

Thanks again, I'm getting there! But where do I define the different databases?


Gordon Franke comments:

In your app.yml file

connections:
costumer1:
iprange: ???
dsn: ....
costumer2:
iprange: ???
dsn: ....


get all connections

$conns = sfConfig::get('app_connections');


then loop over it

foreach($conns as $conn)
{
// check ip or range
if()
{
$dsn = $conn['dsn']
}
break;
}


untestet


Gordon Franke comments:

yes you can also manage the information in the database.

So you must get the connection information from the db to connect to the special connection. This means you must manually connect after the complete doctrine initialisation.

2010-04-14

Martin Palacio answers:

I second the Gordon's approach. Just some note: it could be better to define the clients information (IP range/DSN pairs) into a database (think about a backend application to manage such info).

In that case, you can [[LINK href="http://www.symfony-project.org/doctrine/1_2/en/02-Connections#chapter_02_multiple_connections"]]look here[[/LINK]] to add a database connection.


2010-04-14

Christian Schaefer answers:

Actually following the documentation [1] you will read the following:

<blockquote>Most of the time, all applications of a project share the same database. That's why the main database configuration file is in the project config/ directory. You can of course override the default configuration by defining a databases.yml configuration file in your application configuration directories.</blockquote>

So it is perfectly possible to have a separate database configuration (dsn) per application


[1] [[LINK href="http://www.symfony-project.org/reference/1_4/en/07-Databases"]]http://www.symfony-project.org/reference/1_4/en/07-Databases[[/LINK]]


Lucas van Oostrum comments:

Hi Guys,

I'm trying out your answers and get back to you.

Thanks,

Lucas


Christian Schaefer comments:

Hi Lucas,

I think I already gave a good enough answer to step three of your plan (the multiple database connections, one per app.yml).

About the other queston how to route to the correct application:

You have to do two things.

1. I understand you have multiple identical applications that only differ in terms of configuration. Then you have to <strong>create a plugin, enable it in your project and move your routing.yml to it</strong> (and everything else that is shared). This will have the desired effect that all routes are present in all your apps. If you include modules in your plugin you have to enable them in the settings.yml of each application.

2. <strong>Modify your frontcontroller</strong> (index.php, frontend_dev.php) to choose the correct application. So instead of having one prod and one dev controller per application you will have only one each for the whole project. In it you check the IP adress and select the appropriate application name that you dispatch to.

Hope this helps?

2010-04-21

Russ Flynn answers:

Just a quick note about your customer's database settings - you really shouldn't have them in your database.yml at all, especially if you are using version control.

It's much easier to either svn ignore databases.yml and deploy a separate one with each of your customer installations, or to keep some common settings you can do something like this in your databases.yml:


<?php require(dirname(__FILE__)."/db_info.php"); ?>

prod:
doctrine:
class: sfDoctrineDatabase
param:
dsn: pgsql://<?php echo $db["username"].":".$db["password"]."@".$db["host"]."/".$db["dbname"]; ?>


Then the db_info.php file is customised for each deployment. In fact, as a developer you don't even need to know what's in it, just tell your customer's IT department what should be in it and let them specify it.

Edit: I misread your original post - You are using the same codebase for all the customers right? Then ignore this... But keep it in mind for future apps ;)