Autor | Zpráva | ||
---|---|---|---|
Fisak Profil |
Dobrý den. Potřeboval bych pomoci s řešením situace která mi právě nastala. Mám v mém systému 3 DB -> pro uživatele zvlášť pro systém zvlášť a pro obsah zvlášť db. U vertriga nebo u Endory to funguje tak že všechny db uživatele mají společný server user i pass. Rozdíl je zde jen v názvech DB. Jenže sem narazil na hosting kde je ke každé db zvlášť user heslo i název db. Společný zde mají jen server. Můj skript pro spojení s DB do teďka fungoval takto
<?php abstract class database{ static function connect($db_name) { if(!mysql_connect(_DB_SERVER_,_DB_USER_,_DB_PASSWD_)){ return mysql_error(); } else { if(!mysql_select_db($db_name)){ return "Nepodařilo se vybrat databázi $db_name."; } else { mysql_query("SET character_set_results = utf8"); mysql_query("SET character_set_connection = utf8"); mysql_query("SET NAMES utf8"); } } } } class db extends database { //připojení k databázy system static function query_system($retezec) { static $connected_sys = false; if($connected_sys === false) db::connect(_DB_NAME_SYSTEM_); return mysql_query($retezec); } //pripojení k databázy uživatelu static function query_users($retezec) { static $connected_us = false; if($connected_us === false) db::connect(_DB_NAME_USERS_); return mysql_query($retezec); } //pripojení k databázy obsahu static function query_content($retezec) { static $connected_cont = false; if($connected_cont === false) db::connect(_DB_NAME_CONTENT_); return mysql_query($retezec); } } Jenže jak tento skript upravit tak aby co nejméně zatěžoval server s neustálím spojováním s DB při každém dotazu. Prosím o radu. Ale neprosím o radu abych začal používat dibi nebo již něco vytvořeného. Předem děkuji za odpověď. |
||
Kajman Profil |
#2 · Zasláno: 8. 10. 2012, 08:49:04
Pamatujte si identifikátor těch tří (v tomto případě) různých připojení a předávejte ho jako parametry v mysql_query.
Případně prozkoumejte, zda nemůžete z dvou uživatelských účtů povolit jednomu hlavnímu, aby pracoval s jejich tabulkami (příkazem grant). |
||
Fisak Profil |
#3 · Zasláno: 8. 10. 2012, 12:16:06
Kajman:
„Případně prozkoumejte, zda nemůžete z dvou uživatelských účtů povolit jednomu hlavnímu, aby pracoval s jejich tabulkami (příkazem grant).“ bohužel to nelze u mého webhostingu z toho co jsem pochopil od podpory wedosu. A jak se pamatují identifikátory těchto tří db ?? |
||
Kajman Profil |
#4 · Zasláno: 8. 10. 2012, 12:29:40
Fisak:
„A jak se pamatují identifikátory těchto tří db ?“ V proměnných. http://cz.php.net/manual/en/language.oop5.properties.php |
||
Fisak Profil |
Vyřešil sem to takto. Ale i když to funguje tak nevím jestli je to dobré.
<?php abstract class database{ static function connect($db_name) { if($db_name == "system") { $db_server_db = _DB_SERVER_SYSTEM_; $db_user_db = _DB_USER_SYSTEM_; $db_pass_db = _DB_PASSWD_SYSTEM_; $db_name_db = _DB_NAME_SYSTEM_; } elseif($db_name == "users") { $db_server_db = _DB_SERVER_USERS_; $db_user_db = _DB_USER_USERS_; $db_pass_db = _DB_PASSWD_USERS_; $db_name_db = _DB_NAME_USERS_; } elseif($db_name == "content") { $db_server_db = _DB_SERVER_CONTENT_; $db_user_db = _DB_USER_CONTENT_; $db_pass_db = _DB_PASSWD_CONTENT_; $db_name_db = _DB_NAME_CONTENT_; } else die('Mysql error!'); if(!mysql_connect($db_server_db,$db_user_db,$db_pass_db)){ return mysql_error(); } else { if(!mysql_select_db($db_name_db)){ return "Nepodařilo se vybrat databázi $db_name."; } else { mysql_query("SET character_set_results = utf8"); mysql_query("SET character_set_connection = utf8"); mysql_query("SET NAMES utf8"); } } } } class db extends database { //připojení k databázy system static function query_system($retezec) { static $connected_sys = false; if($connected_sys === false) db::connect("system"); return mysql_query($retezec); } //pripojení k databázy uživatelu static function query_users($retezec) { static $connected_us = false; if($connected_us === false) db::connect("users"); return mysql_query($retezec); } //pripojení k databázy obsahu static function query_content($retezec) { static $connected_cont = false; if($connected_cont === false) db::connect("content"); return mysql_query($retezec); } } |
||
Tori Profil |
Připadá mi to příliš jednorázové, nemůžete to bez úprav použít v jiném projektu. Porušené zapouzdření - spoléháte na existenci nějakých konstant. Třída si nárokuje řízení celé aplikace - použití die. U každého dotazu se snažíte navázat nové připojení s DB (pokud použijete dvakrát za sebou stejné přihl.údaje, tak se sice použije předchozí připojení, ale je zbytečné xkrát volat mysql_connect, když můžete uložit její výsledek a ten přidávat jako 2.param mysql_query). Pokud přidáte další databázi, musíte dopsat další sadu metod.
Zkuste na to jít z opačné strany, jak byste chtěl třídu použít, jaké rozhraní má třída mít. Když si představím, že bych měla používat paralelně 3 databáze (a případně za 2 roky ten kód znova upravovat), tak bych chtěla mít rozhraní snadno čitelné/pochopitelné a taky aby se "za oponou" neděly žádné nečekané věci (např. že překlep v konfiguráku shodí celou aplikaci). Třeba by mi připadalo použitelné něco takovéhoto ↓, takže bych rozhraní třídy udělala podle toho. try { $db = new Database; $db->connect($config['db']['system'] /* přihlašovací údaje + kódování */, 'system' /* nepovinný identifikátor tohoto připojení */ ); $db->connect($config['db']['users'], 'users'); $db->connect($config['db']['content'], 'content'); } catch (DbConnectionError $e) { /* Některé připojení selhalo */ Log::write($e->getMessage()); } try { // přihlášení: // metoda escape escapuje jako řetězec (s doplněním uvozovek okolo) nebo jako číslo, podle toho, jaké znaky vstup obsahuje. // 2.parametr je (výše zadaný) identifikátor databáze. Podle něj se interně jako druhý param. mysql_query // použije identifikátor připojení k DB. Pokud ještě nebylo připojení navázáno, provede se to před dotazem. // Pokud není 2.param. zadaný a existuje pouze jedno připojení (nebo přihl.údaje pro něj), použije se to. $userData = $db->query('SELECT * FROM `users` WHERE `username` = '.$db->escape($_POST['login']), 'users'); // načtení obsahu: $content = $db->query('SELECT `nadpis`, `obsah` FROM `stranky` WHERE `id` = '.$db->escape($router->urlParam['id_stranky']), 'content'); } catch (DbQueryError $e) { Log::write($e->getMessage()); // nějaké další zpracování chyby, přesměrování apod. } |
||
Fisak Profil |
#7 · Zasláno: 9. 10. 2012, 12:05:36
a mohu se zeptat ještě jak by tedy vypadal konečný dotaz na db ??? zvlášť pro db users zvlášť pro db system a zvlášť pro db content ??
|
||
Tori Profil |
#8 · Zasláno: 9. 10. 2012, 12:20:56
Myslíte rozhraní nebo implementaci?
|
||
Fisak Profil |
no myslím např. "query("insert into table ... prostě dotaz", content);" třeba takto ale nevím právě jak by měl fungovat tent Váš skript..
|
||
Amunak Profil |
#10 · Zasláno: 9. 10. 2012, 12:50:06
Tori:
Nebylo by lepší mít každé připojení jako jeden objekt: $dbsys = new Database; $dbsys->connect(...); $dbusr = new Database; $dbusr->connect(...); $dbsys->query(...)->disconnect(); Přijde mi divné takhle spolu spojovat tři věci. To spíš když už by mohl být "nástavbový" objekt connection který by akorát pomáhal vybrat jednu z těch tří databází (a uměl by s připojeními/databázemi pracovat - nastavovat výchozí, pamatovat si poslední použitou, připojení ukončovat a vytvářet nebo tak) ale prijde mi to spíš zbytečné. |
||
Tori Profil |
#11 · Zasláno: 9. 10. 2012, 13:43:37
Amunak:
Chtěla jsem napsat, že to už bych radši objekt connection schovala někde do soukromé proměnné Database::$connection, a že by mohly být odlišné drivery pro různé DB (aspoň mysql a mysqli, aby se nemusela řešit odlišná syntax SQL), ale vlastně pak už by z toho vyšlo zárodečné stadium dibi. :-) Ale je pravda, že ten druhý parametr query(), teda přepínač použité databáze, tam nemá být, protože mění chování metody. Takže pokud by Fisak nechtěl rovnou použít Dibi ( $result = dibi::getConnection('system')->query('...'); ), tak váš návrh je lepší.
|
||
Časová prodleva: 12 let
|
0