I am trying to extend the PHP5 MySQLi Library
class mysqli_ls extends mysqli
The reason I am extending the class is to add functionality and features I require that are not included by default. For the functions I create I would like to handle errors in exactly the same way as i would any of the native functions..
I would like the person using the class not have to determine if the functions are native or bespoke.
Normal Function
if ( $_mysqli->query($sql) === false ) die($_mysqli->error);
Required Bespoke Function Example
if ( $_mysqli->run_config() === false ) die($_mysqli->error);
Class
Within my class mysqli_ls that is extending mysqli, i have the following functions which i hoped would set the error message within the parent mysqli class..
public function run_config()
{
// Open Debug FH
if ($this->config['debug_log'] === TRUE)
{
if ($this->fh_debug = fopen($this->config['debug_log_path'], 'a') === FALSE)
{
$this->handle_error('Could not open Debug file handle','200',__METHOD__);
return $this->E_ERROR;
}
}
}
private function handle_error($errormsg,$errorno,$method)
{
$this->errorno = $errorno;
$this->error = $errormsg;
if ($this->config['debug_log'] === TRUE)
{
$msg = "($errorno) $errormsg";
$this->write_log('error', $method, $msg);
}
return $this->E_OK;
}
I have tried the above method which errors out with:
PHP Fatal error: mysqli_ls::handle_error(): Cannot write property
and the static call syntax which results in a syntax error as seen below:
parent::error
parent::errorno
I would like the users of the class to have the default MySQLI functionality and the extended functionality seamlessly without having to use different methods to identify errors.
Thanks in advance for any advise or input given..
EDIT: Adding the full class
class mysqli_ls extends mysqli
{
private $config = array
(
'config_load' => FALSE,
'config_path' => 'mysqli_ls.database.ini',
'debug_log' => FALSE,
'debug_log_path' => '/tmp/mysqli_ls.debug.log',
'query_log' => FALSE,
'query_log_path' => '/tmp/mysqli_ls.debug.log',
'log_date_format' => 'Y-m-d H:i:s'
);
// Expected fields for the autoload file
private $db_fields = array('hostname','username','password','database','port');
// File Handles
private $fh_debug = FALSE;
private $fh_query = FALSE;
private $fh_config = FALSE;
// Return presets
private $E_OK = TRUE;
private $E_ERROR = FALSE;
// Existing database connections
private $db_existing = array();
public $error;
public $errorno;
## ----------
public function __construct()
{
if (!function_exists('mysqli_connect')) $this->handle_error('MySQLI is not installed','100');
}
## ----------
public function run_config()
{
// Testing error handling
$this->handle_error('Could not open Debug file handle','200',__METHOD__);
// Open Debug FH
if ($this->config['debug_log'] === TRUE)
{
if ($this->fh_debug = fopen($this->config['debug_log_path'], 'a') === FALSE)
{
$this->handle_error('Could not open Debug file handle','200',__METHOD__);
return $this->E_ERROR;
}
}
// Open Query FH
if ($this->config['query_log'] === TRUE)
{
if ($this->fh_query = fopen($this->config['query_log_path'], 'a') === FALSE)
{
$this->handle_error('Could not open Debug file handle','210');
return $this->E_ERROR;
}
}
// Load database INI file
if ($this->config['config_load'] === TRUE)
{
if ( ($this->db_existing = parse_ini_file($this->config['config_path'], TRUE)) === FALSE )
{
$this->handle_error('Could not parse the database ini file','220');
return $this->E_ERROR;
}
}
// Check for format of the loaded ini file
foreach($this->db_existing as $name => $row)
{
foreach($this->db_fields as $field)
{
if ( !isset($row[$field]) )
{
$this->handle_error("Missing field ($field) in the config array for element ($name)",'230');
return $this->E_ERROR;
}
} // END foreach
} // END foreach
return $this->E_OK;
}
## ----------
public function set_config($key, $value)
{
if ( !isset($this->config[$key]) )
{
$this->handle_error('Configuration variable ($key) does not exist','300');
return $this->E_ERROR;
}
$this->config[$key] = $value;
return $this->E_OK;
}
## ----------
public function get_config()
{
return array_merge($this->config, $this->db_existing);
}
## ----------
private function write_log($type,$method,$msg)
{
$msg = date($this->config['log_date_format']) ."\t". $type ."\t". $method ."\t". $msg ."\n";
switch($type)
{
case 'error':
fwrite($this->fh_debug, $msg);
break;
case 'debug':
fwrite($this->fh_debug, $msg);
break;
case 'query':
fwrite($this->fh_query, $msg);
break;
default:
return $this->E_ERROR;
break;
}
}
## ----------
private function handle_error($errormsg,$errorno,$method)
{
$this->errorno = $errorno;
$this->error = $errormsg;
if ($this->config['debug_log'] === TRUE)
{
$msg = "($errorno) $errormsg";
$this->write_log('error', $method, $msg);
}
return $this->E_OK;
}
## ----------
## ----------
## ----------
## ----------
} // END Class
TEST Script Calling the Class
#!/usr/bin/php
<?php
require('mysqli_ls.class.php');
try
{
$_mysqli = new mysqli_ls;
}
catch (Exception $e)
{
print "\n\n". $e->getMessage() ."\n\n";
print_r($e);
}
$_mysqli->set_config('debug_log',TRUE);
$_mysqli->set_config('query_log',TRUE);
$_mysqli->set_config('config_load',TRUE);
$_mysqli->run_config();
print_r($_mysqli->get_config());
?>
EDIT: So it looks like the error variables in the MySQLi class might be readonly..Is there another way around this issue? Im thinking maybe have my own error function that checks the parent class AND my own variables.
Using the __get magic function, you can do something which will check if the parent’s error variable is set. Something like that:
Little test script: