4

I'm having this problem about designing Doctrine database schema. Assume I have 2 databases, A and B.

I've already make database A schema, and now I need to make database B schema. In database B, one of the tables has relation to database A's table. This is the problem, how can I relate B to A?

2 Answers 2

3

@Dziamid is half right.

You technically cannot join two tables over to separate database. But you can fake it would any real intervention.

Configure multiple database connections:

//databases.yml
all:
  items_db:
    class:          sfDoctrineDatabase
    param:
      dsn:          mysql://login:passwd@localhost/items
  stores_db:
    class:          sfDoctrineDatabase
    param:
      dsn:          mysql://login:passwd@localhost/stores

Define the proper connection for each model

//schema.yml
Item:
  connection: items_db
  columns:
    store_id: integer(4)
  relations:
    Store:
      local: store_id
      foreign: id
      foreignAlias: Items

Store:
  connection: stores_db
  columns:
    name: string(255)

Now you can use your Doctrine models as you normally would:

// like this
$item = new Item();
$store = new Store();
$store->save();
$item->setStore($store);

// or like this
$item->getStore(); 

The only limitation is that you CANNOT do joins in DQL queries.

$query = Doctrine_Query::create()
    ->from('Store s')
    ->leftJoin('s.Items i')
    ->fetchAll();

But you can load relations using from Doctrine_Collections.

$stores = Doctrine::getTable('Store')->findAll(); // this returns a Doctrine_Collection
$stores->loadRelated('Items');

This works the same as the Doctrine_Query.

Sign up to request clarification or add additional context in comments.

7 Comments

Really? What about foreign key constraint?
Doctrine takes care of the data integrity (foreign keys). It's exactly what an orm is meant to do. we use this extensively in our high volume production applications. works like a charm.
You can't really ensure data integrity between databases, can you? Doctrine would have to connect to both databases when updating a table that has "relation" to another database. I haven't seen such a behaviour. Moreover, I have tried to build your schema and failed - because, like I said, doctrine generates a constraint ALTER TABLE item ADD CONSTRAINT item_store_id_store_id FOREIGN KEY (store_id) REFERENCES store(id) NOT DEFERRABLE INITIALLY IMMEDIATE; and database fails to apply it. I think this will only work on mysql MyISAM engine, which doesn't care about constrains.
If set up correctly, Doctrine won't attempt to create a foreign key, hence the issue of foreign key constraints won't apply. Doctrine is an ORM and DBA (database abstraction) Layer. It's purpose is to ensure database integrity as best as possible whenever the database is unable to do so. And yes, Doctrine will open two connections and execute two separate queries when saving or querying relations. If you had issue it's because there is an issue with your symfony/doctrine config or example. But the concept is solid and used widely. My company uses it with great success.
There is also a known issue with some symfony 1.4.x distro when using multiple doctrine database connections. Symfony/Doctrine will ignore the 'connection' attribute and always connect the last defined database. This could be causing your issue.
|
2

You can't have a relation between tables in different databases. If you do, you will end up with a foreign key constraint error. What you can do, however, is to leave a bare relation_id field and manually load related data from another connection. For example:

Item:
  columns:
    store_id: integer(4)
  #relations:
  #  Store:
  #    local: store_id
  #    foreign: id
  #    foreignAlias: Items

Store:
  columns:
    name: string(255)

class Item extends BaseItem
{
  protected $_store = null;

  public function getStore()
  {
    if (null == $this->_store)
    {
      $this->_store = Doctrine::getTable('Store')->findOneById($this->store_id);
    }
    return $this->_store;
  }

  public function setStore(Store $store)
  {
    $this->store_id = $store->id;
  }
}

Now you can work with Item and Store as if they were related:

$item = new Item();
$store = new Store();
$store->save();
$item->setStore($store);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.