Использование одного класса внутри другого

Valdisss

Новичок
Использование одного класса внутри другого

Собственно суть.
Скажем есть класс для работы с СУБД, условно назовём его экземпляр $DB.
Есть второй класс, который занимается пользователями (создание, редактирование, удаление), условно назовём его экземпляр $Users.

При создании пользователя необходимо внутри класса $Users использовать класс $DB. МОжно конечно лбъявить $DB глобальным и тогда переменная $DB будет доступна внутри массива $GLOBALS[]. Но, к сожалению, Zend Studio, не отображает методы, если задаётся строка такого вида $GLOBALS['DB'], например $DB->connect() в Zend Studio 5 дописывается, а $GLOBALS['DB']->connect() нет.

СОбственно вопрос
можно ли сделать $DB глобальной так, чтобы внутри другого класса обращаться к ней как к $DB, а не как $GLOBALS['DB'].

СПасибо.
 

Valdisss

Новичок
Автор оригинала: x-yuri
1. можно присваивать $DB полю объекта
2. можно сделать $DB - статическим классом

-~{}~ 29.01.09 00:21:

3. http://ru.wikipedia.org/wiki/Синглтон
За ссылку спасибо, ещё просьба покажите, как присваивать $DB полю объекта.

Если я правильно понял в классе $users есть атрибут public $db. Мы делаем такое действие $users->db = $DB.
ну и затем внутри класса $users используем $this->db. Поправьте если не понял.
 

x-yuri

Новичок
ты, наверное спрашиваешь как получить объект: global, $GLOBALS, через параметр метода (но использованием глобальных переменных не стоит заниматься повсеместно), db::get_instance (в случае Singleton)

И где его получать: скорее всего в конструкторе

-~{}~ 29.01.09 00:38:

еще можешь почитать http://wiki.agiledev.ru/doku.php?id=ooad:manage_dependencies_in_php_code (для сложных проектов)
 

Valdisss

Новичок
Автор оригинала: x-yuri
ты, наверное спрашиваешь как получить объект: global, $GLOBALS, через параметр метода (но использованием глобальных переменных не стоит заниматься повсеместно), db::get_instance (в случае Singleton)

И где его получать: скорее всего в конструкторе

-~{}~ 29.01.09 00:38:

еще можешь почитать http://wiki.agiledev.ru/doku.php?id=ooad:manage_dependencies_in_php_code (для сложных проектов)
В вашем примере, я имею ввиду ссылку, показывается грубо говоря наследование.
Задача простая по сути, и вся проблема в лени, чтобы Zend Studio отображал метожы, а не я их писал. Просто подскажите как сделать так чтобы переменная $DB, являющаяся экхемпляром класса, была видна в другом классе просто как $db или $this->db. Не хотелось бы наследовать $users от $DB, чтобы уйти от связности и не хотелось бы использовать глобальные переменные.
 

Beavis

Banned
Valdisss
По ссылке много примеров как из одного объекта получить доступ к другому. Чем конкретно тебя не устраивает каждый из предложенных способов?
 

x-yuri

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

Просто подскажите как сделать так чтобы переменная $DB, являющаяся экхемпляром класса, была видна в другом классе просто как $db
наверное, использовать @var или @type перед объявлением переменной (в функции или классе). Сам не пробовал

Не хотелось бы наследовать $users от $DB, чтобы уйти от связности и не хотелось бы использовать глобальные переменные.
наследоваться точно не нужно *STOP*

в принципе, для небольшого проекта, глобальная переменная с бд - приемлемо
 

fixxxer

К.О.
Партнер клуба
для _небольшого_ проекта я бы скорее сделал как то так

function db($set = NULL) {
static $instance;
if (isset($set)) $instance = $set;
return $instance;
}

по сути тот же синглтон =) ну по хорошему то либо синглтон, либо регистри (кроме дб ж наверняка что то нужно), либо гонять контекст по конструкторам.
 

x-yuri

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

Valdisss

Новичок
x-yuri
Так я не против глобальной переменной, проблема стала в том, что Zend Studio не даёт подсказок на переменную $GLOBALS['DB'], а на переменную $DB даёт. ПОд переменной я понимаю экземпляр класса для работы с СУБД.
Вот спрошу Вас так, пример кода как я понимаю
Код:
final clas Users
{
protected $db;

            public function __construct()
            {
                   $this->db = new MySUBD();
            }

}
мне скажите, пожалуйста, это корректная запись. Если корректная, что в ней плохого. ПРосто мне ещё не совсем просто вогнать в смысл синглтона, только примерно понимаю, но как я понял смысл такой же, в результате создаётся экземпляр класса.
Ещё есть пара мелких вопросов:
1) Чем плохи глобальные переменные
2) Если скажем в проекте идёт разделение полномочий, правильно ли создавать пользователя не только в таблице авторизации, но и ещё грантовать его права на таблицы, нужно ли это? Если так не делать, то по суди все пользователи работают с одинаковыми правами и теоретически могу таблицу удалить.
 

fixxxer

К.О.
Партнер клуба
а ну то есть тебя волнует прежде всего твоя мегаиде с мегакомплитами.
ясно
 

x-yuri

Новичок
не стоит в каждом классе вызывать конструктор MySUBD, он ведь скорее всего создает соединение с БД. А если ты кроме класса User еще какой-нибудь класс инстанциируешь - у тебя будут 2 соединения с БД. Поэтому если создают экземпляр БД, то один раз. Это можно, например, сделать в том же файле, в котором хранится класс БД, либо в методе get_instance синглтона, либо в функции db fixxxer'а ))

чтобы появлялось автодополнение нужно вставить специальный комментарий:
/* @var $<название переменной> <название класса> */
либо в методе (после комментария автодополнение должно заработать), либо перед объявлением поля класса

синглтон гарантирует, что у тебя будет только один экземпляр объекта. Глобальные переменные плохи тем, что ты можешь случайно перезаписать их значение. Поэтому если их и использовать - то в небольших проектах и не для всего подряд, а, например, для объекта бд, массива с настройками (больше в голову ничего не приходит). Кроме того, если у тебя есть привычка использовать переменные до инициализации и register_globals = On, то с помощью параметров $_GET можно задать начальные значения твоим глобальным переменным и может даже взломать сайт

2) можно, конечно, для каждой группы пользователей твоего сайта создать по пользователю БД, но это усложнит тебе работу. Возможно, это будет целесообразно для сильно секьюрных сайтов или больших проектов

еще один вариант доступа к бд - статический класс - объект хранится внутри него в статическом поле (объект создается автоматически). При этом доступ к бд осуществляется как-то так: db::query('SELECT ...') и т.д. Преимущество - не надо явно создавать объект

по мере увеличения сложности проектов эти решения стоит применять так:
глобальная переменная
функция, синглтон, статический класс
регистри

-~{}~ 29.01.09 03:57:

что с синглтоном непонятно? в википедии даже заготовка для синглтона есть
 

zerkms

TDD infected
Команда форума
function db($set = NULL) {
static $instance;
if (isset($set)) $instance = $set;
return $instance;
}

по сути тот же синглтон =)
ни капли не синглтон. синглтон - порождающий паттерн. а твоя реализация сама ничего не инстанциирует.
 

x-yuri

Новичок
zerkms а вот здесь ты точно придираешься
"по сути" (с) fixxxer
"singleton гарантирует, что у класса только один экземпляр, и предоставляет единственную точку доступа к нему" (с) Gof

но не во всех языках можно гарантировать такое.

Даже больше, Singleton может позволять передавать внутрь экземпляр объекта, чтобы обеспечить возможность тестирования (http://wiki.agiledev.ru/doku.php?id=ooad:manage_dependencies_in_php_code), при этом гарантия, конечно, ликвидируется.

И в конце концов, передать что-то левое в синглтон можно только специально, в отличие от глобальной переменной
 

fixxxer

К.О.
Партнер клуба
>ни капли не синглтон.

ок

function db() {
static $instance;
if (!isset($instance)) $instance = new DB;
return $instance;
}
 

zerkms

TDD infected
Команда форума
x-yuri
верно. гарантирует. а озвученная реализация не гарантировала этого.

к тому же, из тех же гоф:
Паттерн Singleton
Название и классификация паттерна
Одиночка - паттерн, порождающий объекты.
а там была скорее какая-то вариация реестра.
 

Valdisss

Новичок
x-yuri
ВОт наконец-то мы на начинаем понимать друг друга. Спасибо. Но есть ньюансы :)))
Ну я бы хотел сказать, сразу, что register_globals у меня в значение Off, и я его менять не собираюсь. В таком случаем кроме риска затереть глобальную переменную, есть ли ещё минусы её использования?
2) /* @var $<название переменной> <название класса> */
то есть в моём случае если я переменную $DB объявляю глобальной, этот вариант выглядит так
/* @var $GLOBALS['DB'] MySUBD */
поправьте пожалуйста если не понял.
3) Опять же вопрос то есть суть моего синглтона сводится к такому коду:
Код:
final class Factory
{
private $db;

static public function mySUBD()
{
           if($this->db===null)
           {
                 return new MySUBD();
           }
           else
           {
                    return $this->db;
            }
}
}
и я так понимаю далее внутри любого другого класса, мы используем такую конструкцию Factory::mySUBD()->execQuery("...");, например
Код:
class Users
{
...
public function addUser()
{
Factory::mySUBD()->execQuery("...");
}
...
}
Опять же если не понял исправьте.

3)
2) можно, конечно, для каждой группы пользователей твоего сайта создать по пользователю БД, но это усложнит тебе работу. Возможно, это будет целесообразно для сильно секьюрных сайтов или больших проектов
Нужна безопасность, что посоветуете. Я предполоажу допустим создать хотя бы трёх пользователей разных типов и грантовать им разные права. Назовём их admin, client, operator. у а далее в зависимости от подключившегося пользователя работать с СУБД от admin, client или user. Это нормальный вариант? Тогда вроде геморра нет, но и не отследить какой человек, если что нанём таблице вред и что с ней делал.
 

Духовность™

Продвинутый новичок
register_globals у меня в значение Off, и я его менять не собираюсь. В таком случаем кроме риска затереть глобальную переменную, есть ли ещё минусы её использования?
register_globals к озвученной проблеме никак не относится.

Опять же если не понял исправьте.
Какая нафиг фактори? нахрен она здесь нужна?
Достаточно в классе Database прописать
PHP:
    public static function getInstance()
    {
        if (!self::$instance)
        {
            $class = __CLASS__;
            self::$instance = new $class();
        }

        return self::$instance;
    }
И в любом месте, где нужен объект Database делать вызов
PHP:
$db = Database::getInstance();
Нужна безопасность, что посоветуете. Я предполоажу допустим создать хотя бы трёх пользователей разных типов и грантовать им разные права. Назовём их admin, client, operator. у а далее в зависимости от подключившегося пользователя работать с СУБД от admin, client или user.
это тоже никоим боком к теме не относится
 
Сверху