Форум программистов, компьютерный форум, киберфорум
PHP: ООП
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/9: Рейтинг темы: голосов - 9, средняя оценка - 5.00
 Аватар для alpex
603 / 578 / 103
Регистрация: 16.07.2012
Сообщений: 1,762

работа с бд

06.12.2012, 20:20. Показов 1940. Ответов 10

Студворк — интернет-сервис помощи студентам
Хочу написать скрипт для работы с бд.

Цель - он должен работать с любым типом бд и легко встраиваться в любые приложения.

За основу выбрал PDO, так как в принципе функции для работы с любой базой одинаковы, за исключением подключения, решил сделать следующим образом :
класс mapper в котором будет непосредственно обертка для pdo;
классы-драйвера, с подключением к бд, т.е получающие обьект класса pdo
и класс db, через который будет осуществлятся доступ ко всей этой структуре

Т.е работа примерно должна выглядеть так
Идет обращение к классу db, который в зависимости от параметров записанных в конфигурационном файле, создает обьект класса-драйвера (mysql, sqlite и т.д), который возвращает обьект класса pdo в класс db. Далее этот обьект из класса передается в качестве аргумента в класс mapper при создании екземрляра. Екземпляр класса mapper сохраняется в статическом свойстве класса db, ну и соответственно, при последуюших обращениях возвращается это свойство с обьектом mapper.

В итоге писал писал и добисался до такого
Кликните здесь для просмотра всего текста
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class RK_DB
{
    private static $mapper = NULL;
    
    public static function init()
    {
        if (!self::$mapper instanceof RK_Mapper){
            $database = classes\RK_Config::getDatabase();
            
            $classname = '\\core\\database\\driver\\' . 'RK_' . ucfirst($database['driver']);
            
            if (class_exists($classname, TRUE)){
                
                $rc = new \ReflectionClass($classname);
                if (!$rc->implementsInterface('\\core\\database\\driver\\RK_IDriver'))
                    throw new \Exception ('Class' . $classname . ' does not implement \core\database\driver\RK_IDriver');
                
                $connect = $rc->newInstance($database);
                $pdo = $connect->getDriver();
                self::$mapper = new RK_Mapper($pdo);
            }
        }
        
        return self::$mapper;
    }
}

Получился класс просто с одним статическим методом, т.е для получения обьекта просто нужно обратиться к методу init() \core\database\RK_DB::init() не создавая обьекта класса db.

Так вот вопрос правильный ли у меня ход мыслей в этом направлении?

И вообще можно ли делать такие классы в которых не создаются обьекты, как это может повлиять при дальнейшем расширении?

И нужно ли обращаться из этого класса к классу Config или может конфигурационные настройки необходимо передавать каким то другим способом?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.12.2012, 20:20
Ответы с готовыми решениями:

Работа - проведение обучающих семинаров по C#. Работа по выходным дням ( сб-вс - 32 часа). От 30 000р.
Обязанности - проведение обучающих семинаров по C# Базовый (начальный уровень). Опыт преподавания не обязателен, главное чтобы вы не...

Нужна летиратура, в которой бы описывались работа с событиями, работа с элементами управления
Помогите пожалуйста найти летиратуру, в которой бы описывались работа с событиями,работа со всеми элементами управления(toolbox).И если...

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

10
 Аватар для Василий Макогон
270 / 226 / 11
Регистрация: 20.04.2012
Сообщений: 817
07.12.2012, 11:04
что бы получать разные драйверы нужна фабика, а не сингелтон. сингелтон вобще применительно к разработке классов для СУБД не приемлем.

легко встраиваться в любые приложения
как то не вяжется с этим:
PHP
1
$database = classes\RK_Config::getDatabase();
зашивать подключение к БД в классе - очень плохая практика.
в идеале API должно выглядеть так:
PHP
1
2
3
$mysql = Database::getDriverMysql($host, $name, $pass);
$mysql2 = Database::getDriverMysql($host2, $name2, $pass2);
$oracle = Database::getDriverOracle($host, $name, $pass);
0
 Аватар для alpex
603 / 578 / 103
Регистрация: 16.07.2012
Сообщений: 1,762
07.12.2012, 12:11  [ТС]
Цитата Сообщение от Василий Макогон Посмотреть сообщение
как то не вяжется с этим:
PHP
1
$database = classes\RK_Config::getDatabase();
да на счет этого я уже понял что это была ошибка, сейчас решил переписать передавая данные конфигурации в конструктор


Цитата Сообщение от Василий Макогон Посмотреть сообщение
что бы получать разные драйверы нужна фабика, а не сингелтон.
ну у меня и получается своеобразная фабрика, классы подключения называются RK_Mysql, RK_Sqlite и т.д, на вход подается массив $database в котором в ячейке драйвер лежит тип используемой бд(mysql, sqlite и т.д), ну и я в этой строке в зависимости от типа драйвера соответсвенно обращаюсь к определенному классу,
Цитата Сообщение от alpex Посмотреть сообщение
PHP
1
$classname = '\\core\\database\\driver\\' . 'RK_' . ucfirst($database['driver']);
мне почему то показалось , что так будет лучше чем делать switch-case с явным указанием драйверов, плюс такой метод позволяет вообще не влезать в этот метод при добавлении новых драйверов, или я тут что то напутал?

Добавлено через 22 минуты
Цитата Сообщение от Василий Макогон Посмотреть сообщение
сингелтон вобще применительно к разработке классов для СУБД не приемлем.
ну а каким образом без синглтона добиться что бы был создан только один обьект, или ложить его в регистр, а потом брать оттуда, или передавать его из класса в класс?

Добавлено через 5 минут
вообщем у меня сейчас поучилось так,
Кликните здесь для просмотра всего текста
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
class RK_DB
{
    
    /**
     * Обьект класса RK_DB
     * @var object
     */
    private static $instance = NULL;
    
    /**
     * Массив с конфигурационными параметрами
     * @var array
     */
    private $database;
    
    /**
     * Обьект класса RK_Mapper
     * @var object
     */
    private $mapper;
    
    /**
     * Обьект класса PDO
     * @var object
     */
    private $pdo;
    
    
    /**
     * RK_DB::getInstance()
     * Возвращает обьект класса RK_DB, если он создан или создает его
     * 
     * @param mixed $database
     * @return object RK_DB::$instance обьект класса RK_DB
     */
    public static function getInstance(array $database = NULL)
    {
        if (self::$instance === NULL)
            self::$instance = new self($database);
            
        return self::$instance;
    }
    
    /**
     * RK_DB::getMapper()
     * Метод возвращает свойство с обьектом класса RK_Mapper
     * 
     * @return object $mapper обьект класса RK_Mapper
     */
    public function getMapper()
    {
        return $this->mapper;
    }
    
    /**
     * RK_DB::__construct()
     * Конструктор класса
     * 
     * @param array $database конфигурационные параметры подключения
     */
    private function __construct($database){
        
        $this->database = $database;
        $this->createDriver();
        $this->createMapper();
    }
    
    /**
     * RK_DB::createDriver()
     * Метод получает обьект класса PDO для драйвера переданного в массиве параметров
     * 
     * @return void
     */
    private function createDriver()
    {
        // если конфигурационных параметров не передано бросаем исключение
        if ($this->database === NULL)
            throw new \Exception ('Parameters $database invalid!' . print_r($this->database));
        
        // в зависимости от конфигурации формируем имя класса для соответсвующего драйвера    
        $classname = '\\core\\database\\driver\\' . 'RK_' . ucfirst($this->database['driver']);
        
        // если класса нет то исключение бросит автолоад
        if (class_exists($classname, TRUE)){
        
        //если класс соответствующего драйвера существует создаем отражение класса драйвера       
            $rc = new \ReflectionClass($classname);
            
            // если класс не наследует интерфейс бросаем исключение
            if (!$rc->implementsInterface('\\core\\database\\driver\\RK_IDriver'))
                throw new \Exception ('Class' . $classname . ' does not implement \core\database\driver\RK_IDriver');
            
            // создаем обькет класса драйвера   
            $connect = $rc->newInstance($this->database);
            
            // получаем обьект класса PDO для соответствующего драйвера
            $this->pdo = $connect->getDriver();
        }
    }
    
    /**
     * RK_DB::createMapper()
     * Метод создает обьект класса RK_Mapper передавая обьект PDO в конструктор
     * 
     * @return void
     */
    private function createMapper()
    {
        $this->mapper = new RK_Mapper($this->pdo);
    }
    
}
я написал расширенные комментарии, что б долго не думать что где.
Если вам не трудно не могли бы вы описать, как по вашему мнению должна строиться вся эта структура, может с какими то отдельными примерами?
0
1178 / 1128 / 94
Регистрация: 31.05.2012
Сообщений: 3,060
07.12.2012, 12:14
Цитата Сообщение от alpex Посмотреть сообщение
ну а каким образом без синглтона добиться что бы был создан только один обьект, или ложить его в регистр, а потом брать оттуда, или передавать его из класса в класс?
А с каких пор объект БД должен быть только один? Тогда в нём всё равно должна быть возможность держать внутри себя разные коннекты и переключатся. Бывает так, что сайт юзает несколько бд на нескольких хостах от нескольких юзеров...

Добавлено через 1 минуту
Вот вам пример из популярного фв https://github.com/yiisoft/yii... n.php#L271
0
 Аватар для alpex
603 / 578 / 103
Регистрация: 16.07.2012
Сообщений: 1,762
07.12.2012, 12:27  [ТС]
т.е получается что нужно открыть конструктор, но как же тогда быть с вызовами этого класса из разных мест, ведь при каждом создании обьекта будет открываться новое соединение pdo?
0
1178 / 1128 / 94
Регистрация: 31.05.2012
Сообщений: 3,060
07.12.2012, 12:33
ну вы можете внутри держать разные соединения.
DB::getInstance()->conn1->query(...);
или же соединение будет создаваться вашим приложением и хранится где то в приложении, как это сделано в том же Yii.
0
 Аватар для Василий Макогон
270 / 226 / 11
Регистрация: 20.04.2012
Сообщений: 817
07.12.2012, 12:40
Цитата Сообщение от alpex Посмотреть сообщение
ну а каким образом без синглтона добиться что бы был создан только один обьект, или ложить его в регистр, а потом брать оттуда
ложить в регистр или контекст (смотри у меня как сделан контекст - глобальный объект содержащий все звёздные объекты - http://krugozor.svn.sourceforg... xt%2Fplain)
у меня там ошибка, я как бы не принял во внимание что
Бывает так, что сайт юзает несколько бд на нескольких хостах от нескольких юзеров...
но это поправимо путем сохранения объектов БД в виде массива. тем самым, у меня объекты БД лежат в глобальной обертке, но по факту не являются одиночками

Цитата Сообщение от alpex Посмотреть сообщение
или передавать его из класса в класс?
и вообще то передавать из класса в класс, да. из глобального объекта в специфические объекты, оперирующие БД.
0
 Аватар для alpex
603 / 578 / 103
Регистрация: 16.07.2012
Сообщений: 1,762
07.12.2012, 13:01  [ТС]
Цитата Сообщение от Василий Макогон Посмотреть сообщение
ложить в регистр или контекст
Цитата Сообщение от DrobyshevAlex Посмотреть сообщение
хранится где то в приложении
в общем я понял что , сохранность этого обьекта это уже не относится к обязанностям этого класса, и это нужно перекладывать на регистр класс

Добавлено через 4 минуты
и выглядеть он должен примерно так?
Кликните здесь для просмотра всего текста
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
class RK_DB
{
    
    /**
     * Массив с конфигурационными параметрами
     * @var array
     */
    private $database;
    
    /**
     * Обьект класса RK_Mapper
     * @var object
     */
    private $mapper;
    
    /**
     * Обьект класса PDO
     * @var object
     */
    private $pdo;
 
 
    /**
     * RK_DB::__construct()
     * Конструктор класса
     * 
     * @param array $database массив с конфигурационными параметрами подключения
     */
    public function __construct($database){
        
        $this->database = $database;
        $this->createDriver();
        $this->createMapper();
    }
    
    /**
     * RK_DB::getMapper()
     * Метод возвращает свойство с обьектом класса RK_Mapper
     * 
     * @return object $mapper обьект класса RK_Mapper
     */
    public function getMapper()
    {
        return $this->mapper;
    }
 
    /**
     * RK_DB::createDriver()
     * Метод получает обьект класса PDO для драйвера переданного в массиве параметров
     * 
     * @return void
     */
    private function createDriver()
    {
        // если конфигурационных параметров не передано бросаем исключение
        if ($this->database === NULL)
            throw new \Exception ('Parameters $database invalid!' . print_r($this->database));
        
        // в зависимости от конфигурации формируем имя класса для соответсвующего драйвера    
        $classname = '\\core\\database\\driver\\' . 'RK_' . ucfirst($this->database['driver']);
        
        // если класса нет то исключение бросит автолоад
        if (class_exists($classname, TRUE)){
        
        //если класс соответствующего драйвера существует создаем отражение класса драйвера       
            $rc = new \ReflectionClass($classname);
            
            // если класс не наследует интерфейс бросаем исключение
            if (!$rc->implementsInterface('\\core\\database\\driver\\RK_IDriver'))
                throw new \Exception ('Class' . $classname . ' does not implement \core\database\driver\RK_IDriver');
            
            // создаем обькет класса драйвера   
            $connect = $rc->newInstance($this->database);
            
            // получаем обьект класса PDO для соответствующего драйвера
            $this->pdo = $connect->getDriver();
        }
    }
    
    /**
     * RK_DB::createMapper()
     * Метод создает обьект класса RK_Mapper передавая обьект PDO в конструктор
     * 
     * @return void
     */
    private function createMapper()
    {
        $this->mapper = new RK_Mapper($this->pdo);
    }
    
}
0
1178 / 1128 / 94
Регистрация: 31.05.2012
Сообщений: 3,060
07.12.2012, 13:13
Цитата Сообщение от Василий Макогон Посмотреть сообщение
но это поправимо путем сохранения объектов БД в виде массива
А я разве сказал что это невозможно? Я кажется как раз написал два варианта
Цитата Сообщение от DrobyshevAlex Посмотреть сообщение
держать внутри себя разные коннекты
Цитата Сообщение от DrobyshevAlex Посмотреть сообщение
хранится где то в приложении
0
 Аватар для Василий Макогон
270 / 226 / 11
Регистрация: 20.04.2012
Сообщений: 817
07.12.2012, 16:16
что такое RK_Mapper?

Добавлено через 4 минуты
PHP
1
// если класс не наследует интерфейс бросаем исключение
имхо эта проверка бесполезна, т.к. class_exists дернет автозагрузку, а она дернет класс. если класс объявлен как
PHP
1
implements \core\database\driver\RK_IDriver
то зачем дополнительные проверки?
0
 Аватар для alpex
603 / 578 / 103
Регистрация: 16.07.2012
Сообщений: 1,762
07.12.2012, 17:14  [ТС]
Цитата Сообщение от Василий Макогон Посмотреть сообщение
что такое RK_Mapper?
ну это обертка pdo(query, fetch и т.д), просто я пишу что то типа фреймворка(ну более наверное в познавательных и обучающих целях), но я еще хочу вставитьэти классы в другое приложение , где сейчас сделана обертка на mysqli, с минимальными изменениями.
а в интерфейсе там только один метод getDriver, который возвращает обьект pdo, ну а для чего она, ну наверное что бы никакой левый класс туда не затерся))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.12.2012, 17:14
Помогаю со студенческими работами здесь

Работа формы в фоне, вне фокуса (работа с раскладкой клавиатуры)
Как заставить это работать в фоне? Даный код работает пока форма в фокусе, как только ее отпускаем - она не реагирует. Public...

Работа с Меню. Сохранение, печать, создать новый. Работа с рисованием
В общем сабж. Делается программа, которая должная Сохранять, печатать и очищать поле (создать новый/очистка). Также хочу спросить как...

Работа с файловой системой (системное название некоторых папок и работа со скрытыми документами)
Всем привет, подскажите каким образом можно из VBA сохранить документ txt в папке "Общие документы" и задать для него свойство...

Нужна книга, где рассматриваются работа с прерываниями, указатели, работа с памятью, ассемблерные вставки
Привет всем! Подскажите, пожалуйста, хорошую книгу по C (именно C, не C++). Интересует работа с прерываниями, указатели, работа с памятью,...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит: токи, напряжения и их 1 и 2 производные при t = 0;. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru