diff options
Diffstat (limited to 'idiorm.php')
-rw-r--r-- | idiorm.php | 213 |
1 files changed, 141 insertions, 72 deletions
@@ -48,12 +48,14 @@ const WHERE_FRAGMENT = 0; const WHERE_VALUES = 1; + const DEFAULT_CONNECTION = 'default'; + // ------------------------ // // --- CLASS PROPERTIES --- // // ------------------------ // // Class configuration - protected static $_config = array( + protected static $_default_config = array( 'connection_string' => 'sqlite::memory:', 'id_column' => 'id', 'id_column_overrides' => array(), @@ -66,13 +68,15 @@ 'caching' => false, ); - // Database connection, instance of the PDO class - protected static $_db; + protected static $_config = array(); + + // Map of database connections, instances of the PDO class + protected static $_db = array(); // Last query run, only populated if logging is enabled protected static $_last_query; - // Log of all queries run, only populated if logging is enabled + // Log of all queries run, mapped by connection key, only populated if logging is enabled protected static $_query_log = array(); // Query cache, only used if query caching is enabled @@ -82,6 +86,9 @@ // --- INSTANCE PROPERTIES --- // // --------------------------- // + // Key name of the connections in self::$_db used by this instance + protected $_which_db; + // The name of the table the current ORM instance is associated with protected $_table_name; @@ -158,21 +165,23 @@ * you wish to configure, another shortcut is to pass an array * of settings (and omit the second argument). */ - public static function configure($key, $value=null) { + public static function configure($key, $value = null, $which = self::DEFAULT_CONNECTION) { + self::_setup_db_config($which); //ensures at least default config is set + if (is_array($key)) { // Shortcut: If only one array argument is passed, // assume it's an array of configuration settings foreach ($key as $conf_key => $conf_value) { - self::configure($conf_key, $conf_value); + self::configure($conf_key, $conf_value, $which); } } else { - if (is_null($value)) { + if (empty($value)) { // Shortcut: If only one string argument is passed, // assume it's a connection string $value = $key; $key = 'connection_string'; } - self::$_config[$key] = $value; + self::$_config[$which][$key] = $value; } } @@ -183,34 +192,52 @@ * ORM::for_table('table_name')->find_one()-> etc. As such, * this will normally be the first method called in a chain. */ - public static function for_table($table_name) { - self::_setup_db(); - return new self($table_name); + public static function for_table($table_name, $which = self::DEFAULT_CONNECTION) + { + self::_setup_db($which); + return new self($table_name, array(), $which); } /** * Set up the database connection used by the class. - */ - protected static function _setup_db() { - if (!is_object(self::$_db)) { - $connection_string = self::$_config['connection_string']; - $username = self::$_config['username']; - $password = self::$_config['password']; - $driver_options = self::$_config['driver_options']; - $db = new PDO($connection_string, $username, $password, $driver_options); - $db->setAttribute(PDO::ATTR_ERRMODE, self::$_config['error_mode']); - self::set_db($db); + * Default value of parameter used for compatibility with Paris, until it can be updated + * @todo After paris is updated to support multiple connections, remove default value of parameter + */ + protected static function _setup_db($which = self::DEFAULT_CONNECTION) + { + if (!is_object(self::$_db[$which])) { + self::_setup_db_config($which); + + $db = new PDO( + self::$_config[$which]['connection_string'], + self::$_config[$which]['username'], + self::$_config[$which]['password'], + self::$_config[$which]['driver_options']); + + $db->setAttribute(PDO::ATTR_ERRMODE, self::$_config[$which]['error_mode']); + self::set_db($db, $which); + } + } + + /** + * Ensures configuration (mulitple connections) is at least set to default. + */ + protected static function _setup_db_config($which) { + if (!array_key_exists($which, self::$_config)) { + self::$_config[$which] = self::$_default_config; } } /** * Set the PDO object used by Idiorm to communicate with the database. * This is public in case the ORM should use a ready-instantiated - * PDO object as its database connection. + * PDO object as its database connection. Accepts an optional string key + * to identify the connection if multiple connections are used. */ - public static function set_db($db) { - self::$_db = $db; - self::_setup_identifier_quote_character(); + public static function set_db($db, $which = self::DEFAULT_CONNECTION) { + self::_setup_db_config($which); + self::$_db[$which] = $db; + self::_setup_identifier_quote_character($which); } /** @@ -219,9 +246,10 @@ * manually using ORM::configure('identifier_quote_character', 'some-char'), * this will do nothing. */ - public static function _setup_identifier_quote_character() { - if (is_null(self::$_config['identifier_quote_character'])) { - self::$_config['identifier_quote_character'] = self::_detect_identifier_quote_character(); + protected static function _setup_identifier_quote_character($which) { + if (is_null(self::$_config[$which]['identifier_quote_character'])) { + self::$_config[$which]['identifier_quote_character'] = + self::_detect_identifier_quote_character($which); } } @@ -229,8 +257,8 @@ * Return the correct character used to quote identifiers (table * names, column names etc) by looking at the driver being used by PDO. */ - protected static function _detect_identifier_quote_character() { - switch(self::$_db->getAttribute(PDO::ATTR_DRIVER_NAME)) { + protected static function _detect_identifier_quote_character($which) { + switch(self::$_db[$which]->getAttribute(PDO::ATTR_DRIVER_NAME)) { case 'pgsql': case 'sqlsrv': case 'dblib': @@ -248,11 +276,12 @@ /** * Returns the PDO instance used by the the ORM to communicate with * the database. This can be called if any low-level DB access is - * required outside the class. + * required outside the class. If multiple connections are used, + * accepts an optional key name for the connection. */ - public static function get_db() { - self::_setup_db(); // required in case this is called before Idiorm is instantiated - return self::$_db; + public static function get_db($which = self::DEFAULT_CONNECTION) { + self::_setup_db($which); // required in case this is called before Idiorm is instantiated + return self::$_db[$which]; } /** @@ -263,13 +292,18 @@ * @example raw_execute('INSERT OR REPLACE INTO `widget` (`id`, `name`) SELECT `id`, `name` FROM `other_table`') * @param string $query The raw SQL query * @param array $parameters Optional bound parameters + * @param array * @return bool Success */ - public static function raw_execute($query, $parameters = array()) { - self::_setup_db(); + public static function raw_execute( + $query, + $parameters = array(), + $which = self::DEFAULT_CONNECTION + ) { + self::_setup_db($which); - self::_log_query($query, $parameters); - $statement = self::$_db->prepare($query); + self::_log_query($query, $parameters, $which); + $statement = self::$_db[$which]->prepare($query); return $statement->execute($parameters); } @@ -282,15 +316,19 @@ * parameters to the database which takes care of the binding) but * doing it this way makes the logged queries more readable. */ - protected static function _log_query($query, $parameters) { + protected static function _log_query($query, $parameters, $which) { // If logging is not enabled, do nothing - if (!self::$_config['logging']) { + if (!self::$_config[$which]['logging']) { return false; } + if (!isset(self::$_query_log[$which])) { + self::$_query_log[$which] = array(); + } + if (count($parameters) > 0) { // Escape the parameters - $parameters = array_map(array(self::$_db, 'quote'), $parameters); + $parameters = array_map(array(self::$_db[$which], 'quote'), $parameters); // Avoid %format collision for vsprintf $query = str_replace("%", "%%", $query); @@ -309,26 +347,41 @@ } self::$_last_query = $bound_query; - self::$_query_log[] = $bound_query; + self::$_query_log[$which][] = $bound_query; return true; } /** * Get the last query executed. Only works if the * 'logging' config option is set to true. Otherwise - * this will return null. + * this will return null. Returns last query from all connections */ - public static function get_last_query() { - return self::$_last_query; + public static function get_last_query($which = null) { + if ($which === null) { + return self::$_last_query; + } + if (!isset(self::$_query_log[$which])) { + return ''; + } + + return implode('', array_slice(self::$_query_log[$which], -1)); + // Used implode(array_slice()) instead of end() to avoid resetting interal array pointer } /** - * Get an array containing all the queries run up to - * now. Only works if the 'logging' config option is - * set to true. Otherwise returned array will be empty. + * Get an array containing all the queries run on a + * specified connection up to now. + * Only works if the 'logging' config option is + * set to true. Otherwise, returned array will be empty. + * @param string $which Key of database connection */ - public static function get_query_log() { - return self::$_query_log; + public static function get_query_log($which = self::DEFAULT_CONNECTION) { + return isset(self::$_query_log[$which]) ? self::$_query_log[$which] : array(); + } + + public static function get_connection_keys() + { + return array_keys(self::$_db); } // ------------------------ // @@ -339,9 +392,16 @@ * "Private" constructor; shouldn't be called directly. * Use the ORM::for_table factory method instead. */ - protected function __construct($table_name, $data=array()) { + protected function __construct( + $table_name, + $data = array(), + $which = self::DEFAULT_CONNECTION + ) { $this->_table_name = $table_name; $this->_data = $data; + + $this->_which_db = $which; + self::_setup_db_config($which); } /** @@ -378,7 +438,7 @@ * array of data fetched from the database) */ protected function _create_instance_from_row($row) { - $instance = self::for_table($this->_table_name); + $instance = self::for_table($this->_table_name, $this->_which_db); $instance->use_id_column($this->_instance_id_column); $instance->hydrate($row); return $instance; @@ -1118,7 +1178,7 @@ if ($part === '*') { return $part; } - $quote_character = self::$_config['identifier_quote_character']; + $quote_character = self::$_config[$this->_which_db]['identifier_quote_character']; return $quote_character . $part . $quote_character; } @@ -1135,8 +1195,9 @@ * Check the query cache for the given cache key. If a value * is cached for the key, return the value. Otherwise, return false. */ - protected static function _check_query_cache($cache_key) { - if (isset(self::$_query_cache[$cache_key])) { + protected static function _check_query_cache($cache_key, $which = self::DEFAULT_CONNECTION) + { + if (isset(self::$_query_cache[$which][$cache_key])) { return self::$_query_cache[$cache_key]; } return false; @@ -1152,8 +1213,15 @@ /** * Add the given value to the query cache. */ - protected static function _cache_query_result($cache_key, $value) { - self::$_query_cache[$cache_key] = $value; + protected static function _cache_query_result( + $cache_key, + $value, + $which = self::DEFAULT_CONNECTION + ) { + if (!isset(self::$_query_cache[$which])) { + self::$_query_cache[$which] = array(); + } + self::$_query_cache[$which][$cache_key] = $value; } /** @@ -1162,19 +1230,19 @@ */ protected function _run() { $query = $this->_build_select(); - $caching_enabled = self::$_config['caching']; + $caching_enabled = self::$_config[$this->_which_db]['caching']; if ($caching_enabled) { $cache_key = self::_create_cache_key($query, $this->_values); - $cached_result = self::_check_query_cache($cache_key); + $cached_result = self::_check_query_cache($cache_key, $this->_which_db); if ($cached_result !== false) { return $cached_result; } } - self::_log_query($query, $this->_values); - $statement = self::$_db->prepare($query); + self::_log_query($query, $this->_values, $this->_which_db); + $statement = self::$_db[$this->_which_db]->prepare($query); $statement->execute($this->_values); $rows = array(); @@ -1183,7 +1251,7 @@ } if ($caching_enabled) { - self::_cache_query_result($cache_key, $rows); + self::_cache_query_result($cache_key, $rows, $this->_which_db); } return $rows; @@ -1219,10 +1287,10 @@ if (!is_null($this->_instance_id_column)) { return $this->_instance_id_column; } - if (isset(self::$_config['id_column_overrides'][$this->_table_name])) { - return self::$_config['id_column_overrides'][$this->_table_name]; + if (isset(self::$_config[$this->_which_db]['id_column_overrides'][$this->_table_name])) { + return self::$_config[$this->_which_db]['id_column_overrides'][$this->_table_name]; } else { - return self::$_config['id_column']; + return self::$_config[$this->_which_db]['id_column']; } } @@ -1298,15 +1366,16 @@ $query = $this->_build_insert(); } - self::_log_query($query, $values); - $statement = self::$_db->prepare($query); + self::_log_query($query, $values, $this->_which_db); + $statement = self::$_db[$this->_which_db]->prepare($query); $success = $statement->execute($values); // If we've just inserted a new record, set the ID of this object if ($this->_is_new) { $this->_is_new = false; if (is_null($this->id())) { - $this->_data[$this->_get_id_column_name()] = self::$_db->lastInsertId(); + $this->_data[$this->_get_id_column_name()] = + self::$_db[$this->_which_db]->lastInsertId(); } } @@ -1362,8 +1431,8 @@ "= ?", )); $params = array($this->id()); - self::_log_query($query, $params); - $statement = self::$_db->prepare($query); + self::_log_query($query, $params, $this->_which_db); + $statement = self::$_db[$this->_which_db]->prepare($query); return $statement->execute($params); } @@ -1378,8 +1447,8 @@ $this->_quote_identifier($this->_table_name), $this->_build_where(), )); - self::_log_query($query, $this->_values); - $statement = self::$_db->prepare($query); + self::_log_query($query, $this->_values, $this->_which_db); + $statement = self::$_db[$this->_which_db]->prepare($query); return $statement->execute($this->_values); } |