|
|
|
|
|
|
Всякое |
Работа в Drupal с несколькими базами данных
Находим в папке sites/default файл settings.php. $db_url = 'mysql://username:password@localhost/databasename'; ставим $db_url = array( 'default'=>'mysql://username:pass@localhost/databasename', 'db1'=>'mysql://username1:pass@host1/databasename1', 'db2'=>'mysql://username2:pass@host2/databasename2', /* ** Сколько угодно параметров для требуемого количества баз данных ** Индексы кроме 'default' могут быть любыми. */ ); Теперь если в сниппете, модуле, блоке или материале вам понадобятся данные из других баз, используем следующий код: /* ** Делаем активной базу с параметрами под индексом 'db1' */ db_set_active('db1'); $result = db_query("Здесь нужный вам запрос к таблицам в db1") /* ** Здесь обрабатываем результат первого запроса */ // Делаем активной базу с параметрами под индексом 'db2' db_set_active('db2'); $result = db_query("Здесь нужный вам запрос к таблицам в db2") /* ** Здесь обрабатываем результат второго запроса */ /* ** В конце ОБЯЗАТЕЛЬНО делаем активной «родную» базу, ** чтобы Drupal мог нормально завершить обработку страницы. */ db_set_active('default'); Переключаться между базами можно сколько угодно раз – после первого обращения Drupal кеширует ресурс соединения с БД в массиве $db_conns и повторного соединения не производится. Если вам недоступно редактирование файла установок, то можно установить требуемое соединение сразу в PHP-коде: /* ** Получаем глобальные переменные Drupal */ global $db_url; /* ** Добавляем свою строку подключения к БД, а родную оставляем под индексом 'default' */ $db_url = array( "default"=>$db_url, "db1"=>"mysql://username1:pass@host1/databasename1" ); /* ** Делаем активной базу с параметрами под индексом 'db1' */ db_set_active('db1'); $result = db_query("Здесь нужный вам запрос к таблицам в db1") /* ** Здесь обрабатываем результат запроса */ /* ** В конце ОБЯЗАТЕЛЬНО делаем активной «родную» базу, ** чтобы Drupal мог нормально завершить обработку страницы. */ db_set_active('default'); Указанные решения работают в D5 и D6. Единственное ограничение – тип баз данных должен быть одним для всех соединений, т.е. следующий код вызовет ошибку: $db_url = array( 'default'=>'mysqli://username:pass@localhost/databasename', 'db1'=>'pgsql://username1:pass@host1/databasename1', ); Вы получите: Cannot redeclare db_status_report() (previously declared in /var/www/mysite/includes/database.mysqli.inc:23) in /var/www/mysite.ru/includes/database.pgsql.inc Устранить данное ограничение можно только хаком ядра Drupal. Хак получается весьма объемистым. С указанной ошибкой все дело не в функции db_status_report(), а со способом которым Drupal подключает интерфейс требуемого типа баз данных. Дело в том, что названия всех функций (за исключением одной – db_check_setup) находящихся в файлах database.pgsql.inc, database.mysql.inc, database.mysqli.inc и database.mysql-common.inc совпадают, что приводит к конфликту в именах 41 функции. Поэтому использовать несколько подключений к базам разных типов можно только полностью переписав слой абстракции баз данных в Drupal. Чтобы сделать это откроем все упомянутые файлы в редакторе. Из файлов database.mysql.inc и database.mysqli.inc удаляем строчку require_once './includes/database.mysql-common.inc'; Содержимое файла database.mysql-common.inc копируем в файлы database.mysql.inc и database.mysqli.inc, а сам файл делаем пустым. Далее во всех трех файлах database.pgsql.inc, database.mysql.inc, database.mysqli.inc переименовываем все функции добавляя к их именам постфикс типа базы данных: в файле database.pgsql.inc – _pgsql; в файле database.mysql.inc – _mysql; в файле database.mysqli.inc – _mysqli. Переименовывать не надо только функцию db_check_setup – она уникальна для файла database.pgsql.inc. Открываем файл database.inc и создаем там 41(!!!) функцию со следующими именами. _db_create_field_sql() _db_create_key_sql() _db_create_keys_sql() _db_process_field() _db_process_field() _db_query() db_add_field() db_add_index() db_add_primary_key() db_add_unique_key() db_affected_rows() db_change_field() db_column_exists() db_connect() db_create_table_sql() db_decode_blob() db_distinct_field() db_drop_field() db_drop_index() db_drop_primary_key() db_drop_table() db_drop_unique_key() db_encode_blob() db_error () db_escape_string() db_fetch_array() db_fetch_object() db_field_set_default() db_field_set_no_default() db_last_insert_id() db_lock_table() db_query() db_query_range() db_query_temporary() db_rename_table() db_result() db_status_report() db_table_exists() db_type_map() db_unlock_tables() db_version() Все функции выглядят однотипно, различаясь только названием. function имя_функции () { global $db_type; $args = func_get_args(); return call_user_func_array("имя_функции_".$db_type, $args); } Несомненно, большой объем правок кода ядра может отпугнуть желающих использовать это. Есть еще один способ, требующий меньшего объема кода. Основная проблема в том, что в PHP обычно нет возможности удаления или переопределения (перегрузки) функций. Правда, одно из расширений PHP – Runkit позволяет сделать это. Если runkit подключен, то достаточно сделать небольшую вставку в код функции db_set_active(). Находим строчки: $db_type = substr($connect_url, 0, strpos($connect_url, '://')); $handler = "./includes/database.$db_type.inc"; if (is_file($handler)) { include_once $handler; } else { _db_error_page("The database type '". $db_type ."' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases."); } $db_conns[$name] = db_connect($connect_url); } и добавляем свой код: $db_type = substr($connect_url, 0, strpos($connect_url, '://')); $handler = "./includes/database.$db_type.inc"; if (is_file($handler)) { $fnames = array( '_db_create_field_sql', '_db_create_key_sql', '_db_create_keys_sql', '_db_process_field', '_db_process_field', '_db_query', 'db_add_field', 'db_add_index', 'db_add_primary_key', 'db_add_unique_key', 'db_affected_rows', 'db_change_field', 'db_column_exists', 'db_connect', 'db_create_table_sql', 'db_decode_blob', 'db_distinct_field', 'db_drop_field', 'db_drop_index', 'db_drop_primary_key', 'db_drop_table', 'db_drop_unique_key', 'db_encode_blob', 'db_error', 'db_escape_string', 'db_fetch_array', 'db_fetch_object', 'db_field_set_default', 'db_field_set_no_default', 'db_last_insert_id', 'db_lock_table', 'db_query', 'db_query_range', 'db_query_temporary', 'db_rename_table', 'db_result', 'db_status_report', 'db_table_exists', 'db_type_map', 'db_unlock_tables', 'db_version', ); foreach ($fnames as $fname) { @runkit_function_remove($fname); } include $handler; } else { _db_error_page("The database type '". $db_type ."' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases."); } $db_conns[$name] = db_connect($connect_url); } В этом случае определения всех функций баз данных будут удалены, а при подключении файла другого типа БД определены заново. Источники:db_set_active() |
|
Direqtor Home Page by ASIADATA. |
|
Отправить комментарий