| 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: 14 let
|
|||
0