Расширение MySQLI и встроенная обработка ошибок

Я пытаюсь расширить библиотеку PHP5 MySQLi.

class mysqli_ls extends mysqli

Причина, по которой я расширяю класс, состоит в том, чтобы добавить необходимые мне функциональные возможности и возможности, которые не включены по умолчанию. Для функций, которые я создаю, я хотел бы обрабатывать ошибки точно так же, как и любую из собственных функций.

Я бы хотел, чтобы человеку, использующему класс, не приходилось определять, являются ли функции родными или сделанными на заказ.

Нормальная работа

если ($_mysqli->query($sql) === false) die($_mysqli->ошибка);

Пример требуемой индивидуальной функции

если ($_mysqli->run_config() === false) die($_mysqli->ошибка);

Класс

В моем классе mysqli_ls, который расширяет mysqli, у меня есть следующие функции, которые, как я надеялся, будут устанавливать сообщение об ошибке в родительском классе mysqli.

   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;
   }

Я пробовал вышеуказанный метод, который выдал ошибку: PHP Неустранимая ошибка: mysqli_ls::handle_error(): Невозможно записать свойство

и синтаксис статического вызова, который приводит к синтаксической ошибке, как показано ниже:

parent::error
parent::errorno 

Я хотел бы, чтобы пользователи класса имели функциональные возможности MySQLI по умолчанию и расширенные функциональные возможности без необходимости использовать различные методы для выявления ошибок.

Заранее благодарим за любые советы или данные ..

РЕДАКТИРОВАТЬ: добавление полного класса

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, вызывающий класс

#!/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());

?>

РЕДАКТИРОВАТЬ: похоже, что переменные ошибки в классе MySQLi могут быть доступны только для чтения. Есть ли другой способ обойти эту проблему? Я думаю, может быть, у меня есть собственная функция ошибок, которая проверяет родительский класс И мои собственные переменные.


person Lee    schedule 19.07.2011    source источник


Ответы (2)


Использование магической функции __get , вы можете сделать что-то, что проверит, установлена ​​ли переменная ошибки родителя. Что-то такое:

class mysqli_ls extends mysqli{
  public $error;
  public $errorno;
  public $connect_error;
  public $connect_errorno;

  function __get($key){
    if(in_array($key, array('error', 'errorno', 'connect_error', 'connect_errorno'))){
      $parentValue = parent::$key;
      if(empty($parentValue)){
        return $this->$key;
      }
      return $parentValue;
    }
  }
}

Небольшой тестовый скрипт:

<?php
$test = @new mysqli2('localhost', 'badlogin', 'whatisapassword', 'anonexistentdb');
echo 'test : '.$test->connect_error;
person Arkh    schedule 26.07.2011

Вызовы методов родительского класса используют два двоеточия:

parent::error();
parent::errorno();
person christopher_b    schedule 19.07.2011
comment
Это прямой копипаст? В вашем примере вы не закрываете функцию run_config перед определением handle_error. - person christopher_b; 19.07.2011
comment
Нет, не прямое копирование и вставка. Я удалил много лишнего в середине. Скрипты работают с синтаксисом, это скорее концептуальная проблема, с которой я столкнулся. Спасибо, что указали на отсутствующий фигурный изгиб, исправленный в основном посте. - person Lee; 19.07.2011
comment
Я добавил полный класс в исходный пост. Я пытаюсь создать демо-ошибку в начале метода run_config. Спасибо за помощь. - person Lee; 19.07.2011
comment
Хм, интересно. Не уверен, как обойти это. Это может быть связано с этой ошибкой: bugs.php.net/bug.php?id= 35104 - person christopher_b; 19.07.2011