За последние 24 часа нас посетили 23742 программиста и 1549 роботов. Сейчас ищут 1033 программиста ...

В деструкторе класса тип данных resource меняется на unknown

Тема в разделе "Прочие вопросы по PHP", создана пользователем Pran, 15 фев 2011.

  1. Pran

    Pran Активный пользователь

    С нами с:
    15 янв 2011
    Сообщения:
    39
    Симпатии:
    0
    IIS 7.5, PHP 5.3.2 NTS VC9 (FastCGI), SQL Server Driver for PHP 2.0

    Решил обернуть API SQLSRV по принципу PDO (в последнем пока нет поддержки PHPTYPE_STREAM, да и процедурку не пульнуть - пришлось отказаться от использования), однако возникает ошибка.

    Класс, сбоящий при высвобождении ресурсов:

    PHP:
    1.  
    2. <?php
    3.  
    4.     class DB_SQLSRV_Statement {
    5.  
    6.         private $rid; # Идентификатор ресурса.
    7.  
    8.         public function __construct($rid) {
    9.  
    10.             $this->rid = $rid;
    11.             echo gettype($this->rid); # тип resource
    12.         }
    13.  
    14.         public function __destruct() {
    15.  
    16.             echo gettype($this->rid); # тип unknown, однако значение сохраняется - Resource #12
    17.             exit;
    18.  
    19.             // Сбор мусора должен приводить к высвобождению ресурсов.
    20.             // Ошибка: 12 is not a valid ss_sqlsrv_stmt resource.
    21.             //
    22.             sqlsrv_free_stmt($this->rid);
    23.         }
    24.     }
    25.  
    26. ?>
    27.  
    Фабрика:

    PHP:
    1.  
    2. <?php
    3.  
    4.     // Обёртка для API php_sqlsrv.dll
    5.     //
    6.     abstract class DB_SQLSRV_Connector {
    7.  
    8.         private static $lid; # Идентификатор соединения с базой данных.
    9.  
    10.         // Конструкторы и вспомогательные методы опущены для краткости.
    11.  
    12.         final public function query($tsql, array $params = array(), array $options = array()) {
    13.  
    14.             if($rid = sqlsrv_query(self::$lid, $tsql, $params, $options)) {
    15.  
    16.                 return new DB_SQLSRV_Statement($rid);
    17.             }
    18.             else self::error();
    19.         }
    20.  
    21.         final public static function error() {
    22.  
    23.             if($error = current(sqlsrv_errors()))
    24.                 throw new DB_Exception($error['message'], $error['code']);
    25.         }
    26.     }
    27. ?>
    28.  
    Обёртка, позволяющая сменить коннектор в проекте:

    PHP:
    1.  
    2. <?php
    3.  
    4.     class DB_Manager extends DB_SQLSRV_Connector {
    5.  
    6.         final public static function getInstance() {
    7.  
    8.             static $instance = null; # Статический экземпляр существующего соединения.
    9.             $classname = get_called_class();
    10.  
    11.             return $instance ?: $instance = new $classname();
    12.         }  
    13.     }
    14.  
    15. ?>
    16.  
    Вызов:

    PHP:
    1.  
    2. <?php
    3.  
    4.     $db = DB_Manager::getInstance();
    5.     $stmt = $db->query('SELECT 1 AS sample'); # Передаётся в лапы GC, возникает ошибка.
    6.  
    7. ?>
    8.  
    Вариант с обёрнутым PDO (библиотека на C от Microsoft), разница только в возвращаемых классах:

    PHP:
    1.  
    2. <?php
    3.  
    4.     $db = DB_Manager::getInstance(); # Возвращается экземпляр PDO
    5.     $stmt = $db->query('SELECT 1 AS sample'); # Возвращается экземпляр PDOStatement.
    6.  
    7. ?>
    8.