Important order considerations with multiple databases in Drupal

I have been working recently with a Drupal application where it is necessary to bring in some data from a non-Drupal database. Eventually these features might roll into a module and the data may move into Drupal but for the moment it sits alone in another database.

An hour or so today disappeared into trying to figure out why various theme_ functions did not work properly. Calling theme('item_list', $list); for example returned broken pages and error messages in the log. After searching for what I was doing wrong in calling theme_ it finally hit me that the error log messages were complaining about not finding the system table and not having parts of the theme. From there it was quick to find the information (which I posted as a comment as well).

The upshot is you have to return to the 'default' database before doing theme work. Read the full version for a code examples.

For example this doesn't work properly:

<?php
  db_set_active
('mydb');

 
//Things to do with mydb

 
$content .= theme('table', $header, $rows);
 
$content .= theme('pager'NULL, 10);
 
db_set_active('default');

  return
$content;
?>

With that you'll get a broken page that doesn't display the theme properly and some errors in your php error log. If, instead you close the connection to 'mydb' before you call the theme functions. So this code does work:

<?php
  db_set_active
('mydb');

 
//Things to do with mydb

 
db_set_active('default');

 
$content .= theme('table', $header, $rows);
 
$content .= theme('pager'NULL, 10);

  return
$content;
?>

Category: 

5 Comments

init_theme() will cover you

If you call init_theme() with your database safe, theme() should generally no longer worry about the db. But when it's trying to figure out what theme to load, it does look in the system table.

Call init_theme() first?

To be sure I understand call init_theme() before changing databases?

init_theme()

I ran into this issue as well, when calling across to a different Drupal database. As josh and merlin said, init_theme() is the answer.

Normally the theme system is lazily-initiated, so init_theme() is called the first time you try to theme something, and it then pulls its data out of the database. That's why you normally never have to call it. If your first theme() call happens when you're using a different database, though, then it will initialize out of the foreign database. Calling it manually before you theme anything will make it all play nice.

init_theme() or not...

...the second approach makes a lot more sense regardless. Grab the data from the alien DB and rush as quickly as possible back to Drupal land. The ease of switching databases has made my life certainly a lot easier while keeping Drupal in sync with 5 other DBs that are live, while the Drupal version is being developed behind the scenes. Love it!

My situation exactly

Though I'm only working with a couple of databases I'm in the same boat. It is great to be able to take a horridly designed Access database, move it to MySQL, keep users using the interface they're comfortable with and all the while work on the new system, modules and share data. In my case I have a non-normalized monolithic table that should be a dozen tables. Import the data into profiles and then use MySQL to provide a view with the same name and columns as the old table and Access is none the wiser that its end days are near.