Javascript-форум (https://javascript.ru/forum/)
-   Серверные языки и технологии (https://javascript.ru/forum/server/)
-   -   Прозрачная работа с несколькими базами данных на PHP (https://javascript.ru/forum/server/7857-prozrachnaya-rabota-s-neskolkimi-bazami-dannykh-na-php.html)

PeaceCoder 22.02.2010 16:16

Прозрачная работа с несколькими базами данных на PHP
 
Тема следующая. Приходилось ли работать с несколькими базами данных на одном сервере ? Если кому и приходилось расскажите какие были проблемы ?
Зачем: Надоели стандартные методы работы с базой. Думаю создать модуль, который будет прозрачен для разработчика, за счет которого можно работать с любой базой данных любого типа в любой момент, указав всего лишь тип (mysql,mssql и т.п.) и название базы данных (его указываешь в настройках баз), а на выходе получить обьект с (договоренными/обще принятыми) методами типа ->query, ->next и т.п. Вся инфа по тому как сделать запрос, генерация ошибок, колво строк и т.п. выполняет сам полученный обьект...

Kolyaj 22.02.2010 18:55

http://ru.wikipedia.org/wiki/PHP_Data_Objects
http://ru.wikipedia.org/wiki/ORM

Tim 22.02.2010 19:04

http://framework.zend.com/manual/ru/zend.db.html
Советую почитать перед началом - можно подчерпнуть много полезных идей. Сам ни чего такого ещё не делал, но планирую. Вообще идея хорошая ибо для добавления поддержки очередного СУБД нужно править только один класс, да и объекты как-то симпатичнее кучи переменных в глобальном пространстве.

PeaceCoder 22.02.2010 20:12

Цитата:

Сообщение от Tim
СУБД нужно править только один класс

в моем случае ничего даже править не надо. в setup файле надо будет указать тип базы необходимые интсал запросы и идентификатор в модуле.
А в самом модуле будет так:
$db = F_SQL::dbo('Название модуля','идентификатор базы')
$db->q("SELECT * FROM {$db->__}название таблицы");
echo $db->count; //количество полученных строк запроса
while ($r = $db->next()){
  ...
  }

...

где $db->__ - префикс для работы с таблицами модуля.
тем самым модуль прозрачен к сайту полность. все настраивается админом, какой главнй префикс. к какой базе привязан модуль и т.п.

e1f 22.02.2010 20:56

Цитата:

$db->q("SELECT * FROM {$db->__}название таблицы");
Вот и первый плохой подход.
При подобном проектировании, конечная цель -- вообще избавиться от sql везде, кроме как непосредственно в классах, реализующих каждый database engine. Правильно как-то так:
Код:

$db->get_object_list($type, $tbl_name, $fields, $filter, $offset, $count);

PeaceCoder 23.02.2010 01:14

Цитата:

Сообщение от e1f
Правильно как-то так:

и как этим методом ты предлагаешь гибкость выборки ? Твой метод как раз плох. Ты пытаешься исключить вообще запросы, прибегая к жесточайшим методам. Это не то, на что я нацелен.
В моем случае не играет роли на каком языке написан запрос. При создании обьекта $db в нем уже будут готовые функции для работы с тем или инным типом базы данных. В твоем же случае я не представляю как это сделать. Ведь синтаксис разных баз разный... и преобразовывать один в другой просто как минимум лишняя трата времени, а во вторых не файл что преобразование будет правильным.

e1f 23.02.2010 10:09

Цитата:

Сообщение от PeaceCoder (Сообщение 45795)
В моем случае не играет роли на каком языке написан запрос.

Мда? То есть в коде проекта будет sql-строка. А если некоторый формат базы не поддерживает синтаксис, используемый в ней? А если мы решили вообще отказаться от sql? ;) Если делать грамотный Storage-wrapper, то от запросов везде, кроме как в классах, реализующих функционал для каждого типа БД, надо бежать как от огня.
В этом случае да, мы просто в конфиге меняем класс, который будет использоватся, и кушам печенье. Иначе мы бегаем, высунув язык, по коду, и меняем ручками запросы, которые ВНЕЗАПНО перестали работать на другой БД.

Tim 23.02.2010 10:38

e1f,
:yes:

PeaceCoder,
Zend и ещё раз Zend. Семое главное это архитектура (идея как всё должно работать). Реализовать сможет любой, у кого есть более или менее прямые руки. Если сейчас архитектуру не додумать то потом уже не исправить, только переделывать.

sergdev 23.02.2010 11:09

Сдается мне что уже есть такое - тот же самый PEAR DB packages (с Zendом не работал).
Или не прав ?

Tim 23.02.2010 14:04

sergdev,
всё верно, такого много, но это всё ЧУЖОЙ КОД.

PeaceCoder 23.02.2010 16:12

e1f,
Да я уже думал об этом, хотелось бы вообще сделать такой класс, которому пишешь стандартизированный запрос, а класс его переделывает под ту или инную базу и его синтаксис.
Планирую ща следующее. изучить стандарт SQL, внести немного своих фич под свою CMS, а класс, как раз таки, стандартный синтаксис будет конверитровать под тот или иной тип базы данных учитывая фичи CMS.

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

Octane 23.02.2010 16:26

Цитата:

Сообщение от PeaceCoder
свою CMS

Как говорил у нас в Волгограде на семинаре генеральный директор UMI.CMS Сергей Котырев: «Каждый PHP-программист должен написать свою CMS и забросить её». :)

PeaceCoder 23.02.2010 16:40

Цитата:

Сообщение от Octane
Как говорил у нас в Волгограде на семинаре генеральный директор UMI.CMS Сергей Котырев: «Каждый PHP-программист должен написать свою CMS и забросить её

нее. она покруче joomla будет. она гибкая до жути. пиши сайт хоть через левое ухо правой рукой.

Tim 23.02.2010 17:00

PeaceCoder,
Зачем нужно две БД одной CMS? В чём смысл? Так безопаснее? Быстрее? Почему не 5? Сервер железный, пусть работает?

PeaceCoder 23.02.2010 17:16

Цитата:

Сообщение от Tim
Зачем нужно две БД одной CMS? В чём смысл?

ты сталкивался с таким когда модулю надо делать запросы к другой бд от которой зависит текущий результат из нашей бд? вот для этого.

Простой пример. сделано несколько сайтов на разных доменах и базах но с одним сервером..., более банальный пример - сайт альянса в игре. Все сайты кланов хранятся на разных доменах и серверах, но например по "соглашению" можно взять например темы новостей каждого клана и вывести на сайте альянса....
или например, сайт онлайн игры. все ссервера лучше размещать на отдельных серверах и базы соответсвенно... но инфа на главном сайте то должна быть?

Tim 23.02.2010 17:36

Не, мне до такого не додуматься даже. Признаю свою вину, меру, степень, глубину....

x-yuri 24.02.2010 23:45

Цитата:

Сообщение от PeaceCoder
ты сталкивался с таким когда модулю надо делать запросы к другой бд от которой зависит текущий результат из нашей бд? вот для этого.

так есть просто две БД или рассматривается вариант перехода с одной БД на другую?

PeaceCoder 25.02.2010 01:32

Цитата:

Сообщение от x-yuri
так есть просто две БД или рассматривается вариант перехода с одной БД на другую?

то что я описал две. а вообще уже реализовываю кросс-бд запросы. независимо от синтаксиса можно будет делать запросы разных модулей
Пример: есть модуль пользователей с таблицей users, групп с таблицей groups и форум с таблицами topics, forums

Можно будет делать такой запрос
$db->q("SELECT T.*,G.Color,U.Nick
  FROM M_FORUM.topics AS T, M_GROUPS.groups AS G, M_USERS.users AS U 
  WHERE G.UserID=U.id AND T.UserID=U.id");

где M_FORUM, M_GROUPS и M_USERS - названия модулей.
Такой запрос будет действовать не зависимо от того какие базы юзают каждый из модулей и на каком они синтаксисе. При этом об префиксах можно будет вообще забыть. Они будут генерится автоматом =)

x-yuri 25.02.2010 14:36

PeaceCoder в своем стиле... т.е. твоя библиотека автоматически определяет использованный диалект и преобразует в нужный? Или она определяет свой, православный?

p.s. пару сообщений, правда про orm

p.p.s. что меня больше всего смущает, так это то, что ты придумываешь проблему и начинаешь отстаивать ее актуальность. Нет чтобы просто сказать: "Интересно мне, любопытно или что там еще..." ;)

Tim 25.02.2010 15:35

Цитата:

ты придумываешь проблему и начинаешь отстаивать ее актуальность
это из-за универа, без этого навыка диплом не сделать =)

micscr 25.02.2010 17:35

Цитата:

Сообщение от PeaceCoder (Сообщение 45843)
нее. она покруче joomla будет. она гибкая до жути. пиши сайт хоть через левое ухо правой рукой.

дай автограф. :)

А по сути: кому писать сайт будет гибко - пользователям джумлы что-ли? Они писать умеют?

Tim 25.02.2010 18:39

Joomla не самая гибкая CMS. Если говорить о гибкости, то ей нужно меряться с Drupal.

PeaceCoder 25.02.2010 21:43

Цитата:

Сообщение от x-yuri
использованный диалект и преобразует в нужный?

именно. преобразует в соответствие с необходимым типом базы.

e1f 26.02.2010 02:53

PeaceCoder, говноидея. Полностью согласен с x-yuri в том, что Вы выдумываете идею ради идеи.

PeaceCoder 26.02.2010 10:26

Цитата:

Сообщение от e1f
PeaceCoder, говноидея.

Вы всем так говорите? Все что делаете не вы все говно? Вы даже не задумались какие возможно появляются...

e1f 26.02.2010 10:42

Цитата:

Сообщение от PeaceCoder (Сообщение 46151)
Вы всем так говорите? Все что делаете не вы все говно? Вы даже не задумались какие возможно появляются...

Чорт, вот все Вы не так понимаете.
Ну, и какие же возможности появляются? Крошево запросов в веб-части како было, тако и осталось, зато они теперь какие-то мутные, и я плохо представляю себе, как написать их.
Далее, мне понадобился запрос, к примеру, с WITH. Mysql его не поддерживает, емнип. Я пишу -- все работает, потому что модули используются не mysql, а oracle, к примеру. Я радостно дописываю запрос и ухожу домой. Потом кто-то меняет в моем запросе только имя модуля, и вуаля -- ничего не пашет. Вот что тут делать пользователю Вашей "системы"? Надо садится, и руками переписывать sql-запросы. Как был каменный век, так и остался.

PeaceCoder 26.02.2010 11:16

e1f,
Как выражается иногда subzey, я Вам соболезную.
Цитата:

Сообщение от e1f
Потом кто-то меняет в моем запросе только имя модуля

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

e1f 26.02.2010 11:25

А причем тут требования на использование модулей? Или Вы имеете в виду, что я не смогу использовать модули Oracle и MySQL в одном запросе? Так толку тогда с такой системы, когда я вроде бы и могу
Код:

SELECT * FROM _oracle_db, _mysql_db
а на самом деле нет.

PeaceCoder 26.02.2010 11:44

Цитата:

Сообщение от e1f
А причем тут требования на использование модулей?

Явно видно, что Вы не поняли вообще что я подразумеваю под словом "модуль" в моей цмс, а не в апаче. А то что вы имеете ввиду так это как раз и делает модуль работы с SQL.

e1f 26.02.2010 13:07

Цитата:

Сообщение от PeaceCoder (Сообщение 46161)
модуль работы с SQL.

С каким именно sql? sql, он, знаете ли, разный :)
Ну и вдогонку -- все же, запросы будут формироватся пользователем вашей CMS? Как будет реализован квотинг данных? Забота об этом возлагается на пользователя?

PeaceCoder 26.02.2010 14:22

Цитата:

Сообщение от e1f
запросы будут формироватся пользователем вашей CMS

Да. Будет стандартный синтаксис (шаблоны написания запросов), все остальное - функции не реазлизованные на той или инной БД берет на себя модуль. Например SELECT INTO не везде одиноков, но по стандарту он таков: "SELECT ... INTO ... FROM ......"
Цитата:

Сообщение от e1f
Как будет реализован квотинг данных?

А вот над этим я думаю, пытаюсь вообще все на автомат поставить. Потому как задолбало постоянно писать типа
$db->q("SELECT * FROM ... WHERE ...='".sql_escape($data)."'"


Может есть идеи как избавиться от функции ?

Kolyaj 26.02.2010 14:26

Цитата:

Сообщение от PeaceCoder
Может есть идеи как избавиться от функции ?

От sql_escape?
Код:

PDO::prepare

e1f 26.02.2010 15:05

bind_param

Tim 26.02.2010 16:00

Цитата:

Да. Будет стандартный синтаксис
Т.е. запрос будет в виде строки а потом будет парсится регулярками и приводиться к нужному виду?

Цитата:

Сообщение от e1f (Сообщение 45811)
Если делать грамотный Storage-wrapper, то от запросов везде, кроме как в классах, реализующих функционал для каждого типа БД, надо бежать как от огня.

Человек дело говорит! PeaceCoder зря вы мой призыв обратить внимание на Zend не услышали. Посмотрите как там сделано:

$params = array(
	'host'     => 'localhost',
	'username' => 'root',
	'password' => '',
	'dbname'   => 'drupal'
);

// Инициализация адаптера с указанием нужного диалекта
$db = Zend_Db::factory('Pdo_Mysql', $params);

// Выполнение запроса
$result = $db->fetchAll(
	$db	->	select()
		->	from('users')
		->	order('uid')
		->	limit(15)
);

PeaceCoder 26.02.2010 16:14

Цитата:

Сообщение от Kolyaj
От sql_escape?

Идейка понравилась, думал что-то в этом роде но не думал что это будет удобно...

PeaceCoder 26.02.2010 17:52

Цитата:

Сообщение от Tim
зря вы мой призыв обратить внимание на Zend не услышали

услышал. пока размышляю что будет лучше. то как построены зенд запросы и хорошо и плохо. хорошо - мы в нутри класса имеем четкую структуру запроса, плохо такое формирование уменьшает кпд программиста, т.к. постоянно повторятся array(name=>adwd,...) утомляет

PeaceCoder 26.02.2010 18:34

Цитата:

Сообщение от Tim
Посмотрите как там сделано

А вот кста, я так и не понял как сформировать запрос с сабзапросом?

Tim 27.02.2010 00:41

Цитата:

А вот кста, я так и не понял как сформировать запрос с сабзапросом?
// Запрос номер 1 (вложенный)
$query1 = $db	->	select()
				->	from('blocks', 'delta')
				->	where('bid = 2');

// Запрос номер 2
$query2 = $db	->	select()
				->	from('users')
				->	where('uid = ?' , $query1)
				->	limit(2);

// Посмотрим как выглядит строка запроса
print $query2->assemble();

/* Вот она:
SELECT users.* FROM users WHERE (uid = (SELECT blocks.delta FROM blocks WHERE (bid = 2))) LIMIT 2
*/

// Теперь выполним этот запрос
$result = $db->fetchAll($query2);

// Распечатаем массив результатов
print_r($result);


Теперь обратим внимание на строку:
->	where('uid = ?' , $query1)

Запрос 1 будет подставлен вместо знака вопроса. В принципе, можно использовать и конкатенацию, но тогда добавлять скобки придётся руками.
->	where('uid = (' . $query1 . ')' )


Ещё можно так:
->	where('uid = (SELECT delta FROM blocks WHERE bid = 2)')

но это уже совсем быдлокодерство.

P.S.: Сдавайтесь PeaceCoder ;) Zend рулит. Хотя, конечно есть и минусы: они перестраховщики большие - много линних проверок и перепроверок.

PeaceCoder 27.02.2010 01:41

Цитата:

Сообщение от Tim
Запрос 1 будет подставлен вместо знака вопроса. В принципе, можно использовать и конкатенацию,

только вот интересно как это происходит конкатенация если на выходе постоянно обьект, а не строка ? Или в пхп принцип -> иной return не влияет на эту команду ?
Цитата:

Сообщение от Tim
Сдавайтесь PeaceCoder Zend рулит

Рулит но не в том направлении в котором буду делать я. На счет сабов так и подумал...

Tim 27.02.2010 02:46

Цитата:

только вот интересно как это происходит конкатенация если на выходе постоянно обьект, а не строка ?
Нужно определить в классе метод __toString() и он будет автоматически вызываться. Беглый осмотр кода кода Zend показал, что так оно и сделано.

class my_class {

	function __toString()
	{
		return 'Вдруг как в сказке скрипнула дверь ;)';
	}
}

$my_obj = new my_class();

print $my_obj;


Часовой пояс GMT +3, время: 06:54.