Не видны $GLOBALS[XXX] при регистрации обработчиков сессий

Bloody Eagle

Новичок
Не видны $GLOBALS[XXX] при регистрации обработчиков сессий

День добрый.
Пишу систему авторизации на сессиях. Сессии будут хранится в БД PostgreSQL. В качестве интерфейса к БД используется DbSimple. По соображениям единообразия вся работа с SQL завернута в класс:
PHP:
<?php
 	class SQL extends Error { //в Error - простенькая система накопления сообщений о состояниях обьекта
		protected 	$host;
		protected 	$base;
		protected 	$user;
		protected 	$password;
		protected 	$typeSQL;
		protected 	$debug = true;

	        public 	$link;//Обьект DBSimple для работы с БД

		private	$connect_string;

		public function __construct($host, $base, $user, $pass, $type = 'Postgresql'){
			parent::__construct();
			$this->typeSQL = $type;
			$this->base = $base;
			$this->host = $host;
			$this->user = $user;
			$this->password = $pass;
			
			$this->connect_string = $this->typeSQL.'://'.$this->user.':'.$this->password.'@'.$this->host.'/'.$this->base;
			$this->link = DbSimple_Generic::connect($this->connect_string);
			$this->link->setErrorHandler('SQL::databaseErrorHandler');
			$this->link->setLogger('SQL::SQLConsoleLogger');
			$this->link->setIdentPrefix(TABLE_PREFIX);//Задаем префикс БД
			$this->link->query("SET CLIENT_ENCODING TO 'UTF8'");
			$this->link->query("SET DATESTYLE TO 'European, German'");
		}

		static function databaseErrorHandler($message, $info)
		{
		    // Выводим подробную информацию об ошибке.
		    debug("SQL Error: $message", 'SQL', '#FF0000'); 
		    debug($info, 'SQL', '#FF0000');
		    echo "SQL Error: <pre>$message</pre>";
		    $this->debug("SQL Error: $message");
		    exit();
		}
		
		static function SQLConsoleLogger($db, $sql) {
    		if ($GLOBALS['odDebug'])
	   			debug($sql, 'SQL query\'s log');
		}  

	}
?>
Экземпляр объекта SQL создается членом другого класса + ссылка на него создается в глобальной области видимости примерно так:
PHP:
class Portal extends Error {
		.
		.
		.
 		protected $sql;
		.
		.
 		protected $session;

		function __construct(){
 			parent::__construct();
			
			$this->sql = new SQL(DB_HOST, DB_NAME, DB_USER, DB_PASS);
			$GLOBALS['SQL'] = $this->sql; 
 			
 			$this->session = new Session();
		.
		.
		.
Класс сессий реализован следующим образом:
PHP:
<?php
class Session
{

    public function __construct(){
	ini_set('session.save_handler', 'user');

	session_set_save_handler(array('Session', 'open'),
                         array('Session', 'close'),
                         array('Session', 'read'),
                         array('Session', 'write'),
                         array('Session', 'destroy'),
                         array('Session', 'gc')
                         );
	if (session_id() == "") session_start();
   }

    public static function open() {
       
        if (isset($GLOBALS['SQL']))
	  return true;
        else
          return false;
    }

    public static function close() {
        return true;
    }

    public static function read($id) {//упрощенная ф-ция, в оригинале проверяется IP и др. параметры браузера
        $query = 'SELECT * FROM ?_sessions WHERE sid = ?';
        if ($result = $GLOBALS['SQL']->link->selectRow($query, $id)) 
     	  return $result['data'];
        return '';
    }

    public static function write($id, $data) {
        $query = 'REPLACE INTO ?_sessions VALUES(?, ?, ?)';
        return ($result = $GLOBALS['SQL']->link->query($query, $id, time(), $data));
    }
    public static function destroy($id) {
        $query = 'DELETE FROM ?_sessions WHERE sid = ?'
        return ($result = $GLOBALS['SQL']->link->query($query, $id));
    }

    public static function gc($max) {
        $query = 'DELETE FROM ?_sessions WHERE exp < ?';
        return ($result = $GLOBALS['SQL']->link->query($query, time() - $max));
    }
}
?>
Так вот, при регистрации обработчиков сессии выдается сообщение, что в массиве GLOBALS отсутствует индекс SQL, хотя обьект sql создается ДО установки обработчика. Ошибку выдает на функции записи сессии.

Что то я уже начал тормозить - никак не пойму в чем дело. Если есть какие соображения - просьба поделится.
Перед вызовом session_set_save_handler $GLOBALS['SQL'] существует, а вот при старте сессии - ошибка...
PHP 5.2.6, Apache/2.2.9 (Fedora)
 

Фанат

oncle terrible
Команда форума
систама авторизации которая завернута в класс сессий, в который завернут класс дбсимпле, который завернут в класс скл, который завернут в класс еррор и $GLOBALS - это жесть из жести, как мне кажется
 

Gorynych

Посетитель PHP-Клуба
Bloody Eagle

PHP:
...$GLOBALS['SQL']->link->query($query, $id, time(), $data));
страшно смотрится... А написали бы вы синглетончик для однозначного получения БД-объекта, все бы и смотрелось получше и, скорее всего, не косячило на обдумывании того, гдде, когда и что именно определено...

у меня такое ощущение, что проблема в первичной попытке проинициалисзировать глобальную переменную внутри метода класса (не всегда понятно когда на самом деле что там проинициализировалось).

возможно изначальное обращение вне классов к глобальной переменной $SQL (да хоть $SQL=false;) поможет, но лично меня эстетически шокирует обращение к методу обеъекта, являющегося публичным данным глобального объекта... Бр-рр-р :)
 

Bloody Eagle

Новичок
Согласен - смотрится монструозно, но время поджимает, переписывать времени особо нет :(
До запуска сессий $SQL уже проинициализирован (проверял), а вот в обработчике болт... Даже внутри конструктора класса Session $SQL тоже определен и доступен, а внутри функции-обработчика он испаряется.
А написали бы вы синглетончик для однозначного получения БД-объекта
Думаете будет разница? Т.к. с базой работают и другие классы, то в любом случае придется делать что то типа такого:
PHP:
$SQL = Singleton::getInstance();
#а далее в обьектах юзать так
$GLOBALS['SQL']->query(...);
Тогда какая разница? Не буду же я каждый раз при вызове getInstance() к бд подключаться... (С синглтонами ни разу не работал) Или насколько я понял конструктор только 1 раз вызывается для него?
Или вы имели ввиду, что подключение к БД реализовать вообще отдельно от класса, а синглтон бы только ссылку на коннект отдавал?
 

Gorynych

Посетитель PHP-Клуба
на фига обращаться через $GLOBALS['SQL']->query(...); если можно будет всегда, в любом месте программы / класса / и т.п. пролучить нужный экземпляр объекьа через Singleton::getInstance(); ?

мне всегда казалось, что основной смысл этого шаблона - это однозначное получение одного и того же (и гарантировано - только его!) экземпляра класса проинициализированного однократно

-~{}~ 17.04.09 09:34:

Автор оригинала: Bloody Eagle
...Не буду же я каждый раз при вызове getInstance() к бд подключаться... (С синглтонами ни разу не работал) Или насколько я понял конструктор только 1 раз вызывается для него?
уупс... Да, у вас пробелы с этим шаблоном. Смысл - однократный вызов защищенного (или приватного) конструктора (где собственно и будет однократное соединение с БДпо первому обращению) и возвращение указателя на один и тот же объект
 

Bloody Eagle

Новичок
Спасибо, понял :)
Переписал SQL в виде синглтона - все заработало....

И чего ему не нравилось - непонятно о_О
 
Сверху