Mysqli & the Fuel backup module
I've just realised that CI's dbutil class isn't compatible with the mysqli driver, which in turn makes the Backup module ineffective.
Is there a workaround? I thought of using parallel db configs where everything but the backup module use mysqli but even so I get deprecation messages from PHP about using the mysql driver. Even if this worked, I'm not sure if it's a valid solution.
Comments
I've got live and dev environments and both use mysqli. However, the live DB, I've only just noticed, is Percona 5.6.17-66.0 (a MySQL drop-in), but the dev server uses vanilla MySQL 5.6.17 with WAMP
#1 Live (Linux, PHP 5.4.37) error is: #2 Dev (WAMP, PHP 5.5.12) error: ..and I've just tried it on a Mac dev environment with MySQL 5.6.20 (mysqli), PHP 5.5.20 and it gives the same error as #1
I've noticed the backup mod didn't work on another (LAMP) site using MySQL 5.5.42, PHP 5.4.32, again using mysqli.
However, using the mysql connector it's OK.
http://stackoverflow.com/questions/24197844/database-utility-backups-not-working-with-mysqli-codeignitor
http://stackoverflow.com/questions/27116299/how-to-extend-the-codeigniter-database-utility-class
The accepted solution in the last link may be worth trying by perhaps extending the DB_utility class as a fuel/application/libraries/MY_DB_utility and replacing the following method:
public function dbutil() { /* snip for brevity */ $class = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_utility'; $filename = APPPATH.'libraries/'.$class.EXT; require_once($filename); /* snip for brevity */ }
I haven't tested this yet and hope that you can simply extend it that way like most of the other CI classes.
class MY_DB_mysqli_utility extends CI_DB_utility { function __construct() { parent::__construct(); log_message('debug', 'Extended DB mysqli utility class instantiated!'); } /** * List databases * * @access private * @return bool */ function _list_databases() { return "SHOW DATABASES"; } // -------------------------------------------------------------------- /** * Optimize table query * * Generates a platform-specific query so that a table can be optimized * * @access private * @param string the table name * @return object */ function _optimize_table($table) { return "OPTIMIZE TABLE " . $this->db->_escape_identifiers($table); } // -------------------------------------------------------------------- /** * Repair table query * * Generates a platform-specific query so that a table can be repaired * * @access private * @param string the table name * @return object */ function _repair_table($table) { return "REPAIR TABLE " . $this->db->_escape_identifiers($table); } /** * Backup * * @param array $params Preferences * @return mixed */ function _backup($params = array()) { if (count($params) === 0) { return FALSE; } // Extract the prefs for simplicity extract($params); // Build the output $output = ''; foreach ((array) $tables as $table) { // Is the table in the "ignore" list? if (in_array($table, (array) $ignore, TRUE)) { continue; } // Get the table schema $query = $this->db->query('SHOW CREATE TABLE ' . $this->db->_escape_identifiers($this->db->database . '.' . $table)); // No result means the table name was invalid if ($query === FALSE) { continue; } // Write out the table schema $output .= '#' . $newline . '# TABLE STRUCTURE FOR: ' . $table . $newline . '#' . $newline . $newline; if ($add_drop === TRUE) { $output .= 'DROP TABLE IF EXISTS ' . $this->db->_protect_identifiers($table) . ';' . $newline . $newline; } $i = 0; $result = $query->result_array(); foreach ($result[0] as $val) { if ($i++ % 2) { $output .= $val . ';' . $newline . $newline; } } // If inserts are not needed we're done... if ($add_insert === FALSE) { continue; } // Grab all the data from the current table $query = $this->db->query('SELECT * FROM ' . $this->db->_protect_identifiers($table)); if ($query->num_rows() === 0) { continue; } // Fetch the field names and determine if the field is an // integer type. We use this info to decide whether to // surround the data with quotes or not $i = 0; $field_str = ''; $is_int = array(); while ($field = $query->result_id->fetch_field()) { // Most versions of MySQL store timestamp as a string $is_int[$i] = in_array(strtolower($field->type), array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'), TRUE); // Create a string of field names $field_str .= $this->db->_escape_identifiers($field->name) . ', '; $i++; } // Trim off the end comma $field_str = preg_replace('/, $/', '', $field_str); // Build the insert string foreach ($query->result_array() as $row) { $val_str = ''; $i = 0; foreach ($row as $v) { // Is the value NULL? if ($v === NULL) { $val_str .= 'NULL'; } else { // Escape the data if it's not an integer $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v; } // Append a comma $val_str .= ', '; $i++; } // Remove the comma at the end of the string $val_str = preg_replace('/, $/', '', $val_str); // Build the INSERT string $output .= 'INSERT INTO ' . $this->db->_protect_identifiers($table) . ' (' . $field_str . ') VALUES (' . $val_str . ');' . $newline; } $output .= $newline . $newline; } return $output; } }
/* load the MX_Loader class */ require FUEL_PATH."core/Loader.php"; class MY_Loader extends Fuel_Loader { public function dbutil() { if (! class_exists('CI_DB')) { $this->database(); } $CI =& get_instance(); // for backwards compatibility, load dbforge so we can extend dbutils off it // this use is deprecated and strongly discouraged $CI->load->dbforge(); require_once(BASEPATH . 'database/DB_utility.php'); // START custom >> // path of default db utility file $default_utility = BASEPATH . 'database/drivers/' . $CI->db->dbdriver . '/' . $CI->db->dbdriver . '_utility.php'; // path of my custom db utility file $my_utility = APPPATH . 'libraries/MY_DB_' . $CI->db->dbdriver . '_utility.php'; // set custom db utility file if it exists if (file_exists($my_utility)) { $utility = $my_utility; $extend = 'MY_DB_'; } else { $utility = $default_utility; $extend = 'CI_DB_'; } // load db utility file require_once($utility); // set the class $class = $extend . $CI->db->dbdriver . '_utility'; // << END custom $CI->dbutil = new $class(); } }