2016-03-04 5 views
4

У меня есть очень общий Mysqli класс для обеспечения соединения с базой данных для остальной части приложения:Несколько Mysqli запросов с PHP одноточечного

class IabDB extends mysqli { 

private static $instance = null; 
// db connection config vars 
private $user = "xxx-lit"; 
private $pass = "xxx"; 
private $dbName = "xxx"; 
private $dbHost = "xxx"; 


private function __construct() { 
    parent::__construct($this->dbHost, $this->user, $this->pass, $this->dbName); 
    if (mysqli_connect_error()) { 
     exit('Connect Error (' . mysqli_connect_errno() . ') ' 
       . mysqli_connect_error()); 
    } 
    mysqli_set_charset($this, "utf8"); 
} 


public static function getInstance() { 
    if (!self::$instance instanceof self) { 
     self::$instance = new self; 
    } 
    return self::$instance; 
} 

В моей модели я retrive данных, как это, который работает хорошо:

$db = IabDB::getInstance(); 
    $query = $db->query("SELECT status, username, email, id FROM " . $table); 
    $items = $query->fetch_all(); 

EDIT Но когда я пытаюсь получить другой экземпляр для другого запроса, я получаю сообщение об ошибке: Вызовите функцию-член fetch_all() на null.

Поверьте мне: я попробовал его взад и вперед. Оба запроса действительны, и оба возвращают результат, если используется только один из них. Просто для полноты картины здесь является второй один с моделью вокруг:

class Model { 

    public static function getItems($table) {  
      $db = IabDB::getInstance(); 
      $query = $db->query("SELECT * FROM lit_veranstaltungen"); 
      $items = $query->fetch_all(); 
      $db->close(); 
      var_dump($items); 

}}

Так что, кажется, второе соединение нарушается как-то !?

Бонусный вопрос: насколько мне известно, очевидно, что теперь в основном смеялся над одноэлементным узором, для этой цели очень полезно?

Любая помощь и альтернативы приветствуются!

ответ

2

Вашего код работает для меня, независимо от количества экземпляров я получаю:

$db = IabDB::getInstance(); 
$query = $db->query("SELECT name FROM users limit 1"); 
$items = $query->fetch_all(); 
var_export($items); 

$db = IabDB::getInstance(); 
$query = $db->query("SELECT name FROM users limit 1,1"); 
$items = $query->fetch_all(); 
var_export($items); 

возвращает

array (0 => array (0 => 'John',),) 
array (0 => array (0 => 'Mike',),) 

Так что я предполагаю, что есть ошибка с конкретным запросом запускается. Поэтому вам нужно просто улучшить отчет об ошибках для своих запросов. Измените конструктор этого

private function __construct() { 
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); 
    parent::__construct($this->dbHost, $this->user, $this->pass, $this->dbName); 
    $this->set_charset("utf8"); 
} 

Затем убедитесь, что ваш PHP сконфигурирован как этот

error_reporting(E_ALL); 
ini_set('display_errors',1); 

, а затем запустить код.

Он либо сообщит об ошибке, либо возвращает пустой массив. В последнем случае это означает, что в базе данных нет строк в соответствии со вторыми условиями запроса. Например, для кода, как этот

$db = IabDB::getInstance(); 
$query = $db->query("SELECT name FROM users WHERE 1=0"); 
$items = $query->fetch_all(); 
var_export($items); 

$db = IabDB::getInstance(); 
$query = $db->query("SELECT name FOrM users"); 
$items = $query->fetch_all(); 
var_export($items); 

он возвращает пустой массив для первого фрагмента и ошибок для второго:

Кроме того, позвольте мне предложить вам добавить функцию, как это

public function query_params($query, $params, $types = NULL) 
{ 
    $statement = $this->prepare($query); 
    $types = $types ?: str_repeat('s', count($params)); 
    $statement->bind_param($types, ...$params); 
    $statement->execute(); 
    return $statement->get_result(); 
} 

, что позволит вам использовать подготовленные заявления, как легко, как с PDO:

$user = $db->query_params("SELECT * FROM users WHERE name = ?", ['Mike'])->fetch_assoc(); 

Что касается singleton, если вы используете процедурный PHP-код старого стиля, то синглтон в порядке. Если вы используете ООП, то лучше применять подход, основанный на зависимости от зависимостей.

+0

Спасибо за ваш подробный anser. Вы правы: на самом деле есть ошибка, но она не решает проблему, потому что ее только там, если оба запроса активны. Вы бы посмотрели мой EDIT выше? Благодаря! –

+0

Вы должны добавить отчет об ошибках mysqli, как показано в моем ответе. Это ** единственный способ решить вашу проблему. Это не помогает знать, что есть ошибка. Вам нужно знать **, какая конкретная ошибка ** это –

+0

Я поместил эту ошибку в мое редактирование выше: вызовите функцию-член fetch_all() на нуле. Но помните, что он возвращает результат, если первый запрос отключен ... –

0

Попытайтесь использовать $query->close(); после выполнения запроса.

Для этого случая синглтон - неплохая идея. Но чаще, у вас есть что-то вроде «диспетчера соединений», который создает объект mysqli при первом использовании, а затем возвращает этот объект при последовательных вызовах, имея возможность иметь несколько соединений с несколькими базами данных или с разными пользователями.

Что-то вроде этого:

class DBConnection { 
    protected static $connections = array(); 

    public static function getConnection($connection_name = 'default') { 
     if (!isset(static::$connections[$connection_name])) { 
      static::$connections[$connection_name] = // setup connection 
      // ... error handling and stuff 
     } 

     return static::$connections[$connection_name]; 
    } 
} 

Btw .: В конструкторе, я хотел бы использовать свойства Mysqli объекта для errorhandling:

http://php.net/manual/de/mysqli.connect-error.php

http://php.net/manual/de/mysqli.connect-errno.php

и http://php.net/mysqli_set_charset

+0

$ query-> close(); ничего не поможет –

1

Вы не можете сделать singleton из класса, который расширяет mysqli (или PDO), поскольку конструктор класса mysqli (и PDO) является общедоступным. Вы не можете переопределить конструктор родительского родителя и сделать его приватным в унаследованном дочернем классе! Попробуйте, и вы получите следующую ошибку:

Fatal error: Access level to DataBase::__construct() must be public (as in class mysqli)