« 1 2 »
Autor Zpráva
Jack06
Profil
Dobré dopoledne.
Měl bych technickou otázku budu mít třeba 3 třídy:

class Prvni{
public function __construct(){
$this->db = new MyDB; $this->db->set_charset('utf8');
}
....
}

class Druha extends Prvni{
public function __construct(){
$this->db = new MyDB; $this->db->set_charset('utf8');
}
....
}

class Treti extends Druha{
public function __construct(){
$this->db = new MyDB; $this->db->set_charset('utf8');
}
....
}


Jde mi o to, jestliže budu ve třetí třídě volat nějakou funkci z první, jestli se mi to několikanásobně nepřipojí do databáze... Vlasně jakože ve třetí se to připojí ve druhé a v té první také. Abych nebyl najednou připojen třikrát k databázi v jedné instanci. Děkuji
DoubleThink
Profil *
jestliže budu ve třetí třídě volat nějakou funkci z první, jestli se mi to několikanásobně nepřipojí do databáze
Pokud nebudeš volat přímo konstruktor, tak ne.
Alphard
Profil
Několikanásobně se nepřipojí, ale proč mít připojení v každé třídě? Stačí ho mít ve třídě Prvni a ostatni ho zdědí.
Ještě lepší je dát si připojení samostatně a vytvořit ho jako Singleton.
DoubleThink
Profil *
Záleží na charakteru aplikace. Já většinou do tříd, které komunikují s databází, vkládám referenci na instanci už připojené databázové třídy.

Singleton
To se moc nehodí na databázový interface. Můžeš mít přece víc připojení najednou a tedy víc instancí.

Osobně mám docela negativní názor na "emulaci" pokročilých objektových konstrukcí u jazyka, který objekty taky v podstatě jenom emuluje.
Jack06
Profil
Alphard

A jak to udělat?? Nyní to mám udělané tak že mám soubor s třídou pro mysqli:
class MyDB extends MySQLi {

  const SERVER = 'localhost';
  const USERNAME = 'root';
  const PASSWORD = 'vertrigo';
  const DBNAME = 'superpokec_beta';
  
  public function __construct() {
    parent::__construct(self::SERVER, self::USERNAME, self::PASSWORD, self::DBNAME);
  }
}

pak dám require na soubor s mysqli a volám novou třídu..

require_once "MyDB.php";
$db = new MyDB; $db->set_charset('utf8');

DoubleThink

Co myslíš tou referencí? můžeš mi dát nějaký příklad? Děkuji
DoubleThink
Profil *
$db = new db();
$auth = new auth($db);


class auth {

	private $db;

	public function __construct(&$db) {
		$this->db = $db;
	}
}
Majkl578
Profil
DoubleThink
objekty se jako reference (kopie ukazatele) predavaji automaticky, ne?
Jack06
Profil
Tak teď v tom mám zmatek jak to využít v těch extendovaných třídách :-(
Alphard
Profil
Já osobně v poslední době použím dibi a jeho statický registr.
(Varuji, je to návykové).
V bootstrap.php se připojím k databázi (samozřejmě lazy) a pak používám statické metody (nepotřebuji přenášet jakékoliv proměnné, ať jsem kdekoliv, dibi je po ruce).
Kdekoliv chci dotaz, stačí zavolat
dibi::query ("...");

Navíc lze používat i např. dibi::fetchAll (""); nebo dibi::fetchSingle("");
Více připojení najednou to trochu komplikuje
dibi::activate('alfa databaze');
dibi::query(...);

ale to používám málokdy.
Majkl578
Profil
[#9]
u dibi se mi nejvic libi fluent rozhrani:
dibi::select('foo, bar')->from('users')->where('foo <= %i', $max ?: 10)->orderBy('bar')->desc()->fetchAssoc('foo');
Mastodont
Profil
Inu, když je někdo líný napsat SELECT rovnou ... tak to napíše v pětkrát pomalejším tvaru, ale objektově :)
->desc()->

Něco podobného jsem viděl na Sitepointu, autor přiznal, že tím byl asi půl roku nadšen a pak to zahodil.
Jan Tvrdík
Profil
Mastodont:
Flent interfaces se hodí pro pustupné skládání SQL dotazů. Normální SQL dotazy ale píšu taky normálně.
Mastodont
Profil
Jan Tvrdík
SQL buildery se samozřejmě někdy hodí, třeba při vytváření INSERT či UPDATE, aby se člověk nemusel starat o escapování textových polí.
$sql = DBQ::InsertSQLFromArray($table, $fields_array);

Ale normální SELECTy je opravdu lepší psát normálně - jsou rychlejší a většinou i čitelnější.
Jack06
Profil
Moc se mi nechce využívat nějaký velký framework, ještě k tomu, když s ním neumím naučit se v něm chodit, aby mi to neškodilo by mi dalo asi dost práce.

Trošku jste odbočili od mého smělého dotazu :-D . Rád bych se zeptal, jak to je s tou referencí popříkladě o radu jak to použít, jestliže mám stránku, na které se připojím k databází (něco jakože config.php) a potom všude kde volám třídy mám tento soubor jako require_once.
A hlavně to ošetření, aby se mi to při procházení více třídami, kde potřebuji tu db použít nepřipojovalo znovu a znovu, protože mám neblahý dojem že to je jako jedna instance a je to jakobych napsal mysql_connect xkrát za sebou.
Děkuji
Jan Tvrdík
Profil
Jack06:
Moc se mi nechce využívat nějaký velký framework
dibi = db + mini :)

Otázkou je, co mají ty třídy dělat. Pokud mají plnit funkci modelu (M v MVC), tak je vhodné vytvořit abstraktní třídu BaseModel, která připojení k DB řeší, a ostatní modely od ní podědit.
Jack06
Profil
Jan Tvrdík
Třídy kontrolují uživatelovy práva v administraci, jeho aktivitu a vytvářejí soupis akcí, které provádí čím vytváří jakýsi report.
Alphard
Profil
Jack06:
Já jsem uváděl další možnost jak řešit daný problém, ale bohužel jsem se zmínil o dibi a strhla se diskuse nesouvisející s tématem.
K vašemu kódu. Jak jsme již psali, pokud zavoláte $neco = new Treti(); připojíte se k databázi jenom jednou. Ale pokud potřebujete např.
$jedna = new Treti();
$dve = new Druha();
$tri = new Treti();

tak si každá instance vytvoří vlastní připojení k databázi. Tomu nezabráníte ani tím, že budete dědit od jednoho předka.
DoubleThink jako řešení navrhuje referenci (viz [#6]), nevím, co víc k tomu dodat. Mně se zase líbí statické metody. A zmíněn byl i Singleton (i když tady asi není nejvhodnější), nic jiného mě nenapadá.
Vybrat si musíte sám.
Jan Tvrdík
Profil
Alphard:
Tomu nezabráníte ani tím, že budete dědit od jednoho předka.
Myslel jsem samozřejmě, že připojení se uloží do statické proměnné.
Mastodont
Profil
Jack06
Nejjednodušší je zmíněný singleton, který si napoprvé vytvoří připojení, uloží si ho do proměnné a pak ho vrací dle potřeby. Ukázka třeba na
http://www.talkphp.com/advanced-php-programming/1304-how-use-singleton-design-pattern.html
(Internet je sice plný různých článků na téma "singleton je zlo", ale ty neberte vážně.)
O něco komplikovanější je nasazení vzoru Registry, kde jsou ale opět většinou volány statické metody.
BetaCam
Profil
Mastodont
Internet je sice plný různých článků na téma "singleton je zlo", ale ty neberte vážně.

"Singleton je zlo" pokud jeho použití nedomyslíš a použiješ ho tam kde je v budoucnu možné že bude potřeba více instancí dané třídy. Připojení k DB je krásný příklad. Záleží samozdřejmě na tom jestli třída pro připojení k DB je šitá na míru projektu a nebo jestli se dělá univerzální.
Mastodont
Profil
"Singleton je zlo" pokud jeho použití nedomyslíš ...
Jistě, ale to platí pro libovolný vzor a nelze to považovat za jeho obecnou vlastnost.
bude potřeba více instancí dané třídy. Připojení k DB je krásný příklad.
V tom případě se to dá jednoduše upravit na Registry vracející instanci pojmenovaného připojení.
DB::Connect('admin')->query(...);
BetaCam
Profil
Mastodont
V tom případě se to dá jednoduše upravit na Registry vracející instanci pojmenovaného připojení.

O tom právě mluvím. Proč to dělat jako singleton, když to jde udělat rovnou pořádně.
Mastodont
Profil
No protože většina lidí nepotřebuje víc připojení nebo různé druhy DB ... aneb KISS
AM_
Profil
a proč to prostě neudělat podobně jako procedurální model mysql_* ? Tuším i Dibi to má podobně - prostě když nechci používat více instancí, nezadám nepovinný parametr instance a použije se tedy "výchozí" instance... Není tak složité ani ke všem metodám udělat statickou metodu, která se bude jednoduše odkazovat na nějakou tu výchozí insanci, něco jako:
class myDBi{
  public myQuery($q){
    ...
  }
}
class myDB{
  private $default_instance = null;
  public static myQuery($q){
    if (!default_instance) $default_instance = new myDBi();
    self::$default_instance->myQuery($q);
  }
}
Mastodont
Profil
AM_
prostě když nechci používat více instancí, nezadám nepovinný parametr instance a použije se tedy "výchozí" instance
Jistě, například:
class DB {
	static $connection = Array();
	static $credentials = false;
	
	static function Connect() {
		// přihlašovací údaje
		if ( (self::$credentials === false) ) {
			if ( file_exists( ... ) ) 
				self::$credentials = unserialize(file_get_contents( ... ));
			else
				throw new DatabaseException('Database connection configuration file is missing.');
		}

		switch (func_num_args()) {
		case 0:
			$connection_name = 'default';
			break;
		case 1:
			$name = func_get_arg(0);
			if ( isset(self::$credentials[$name]) ) {
				$connection_name = $name;
			} else {
				throw new DatabaseException('Invalid name of database connection');
			}
			break;
		default:
			throw new DatabaseException('Invalid number of arguments for connection.');
		} 
		
		if ( isset(self::$connection[$connection_name]) && is_object(self::$connection[$connection_name]) ) {
			return self::$connection[$connection_name];
		} else {
			self::$connection[$connection_name] = new mysqli( ... );
			if (mysqli_connect_error()) {
				self::$connection[$connection_name] = false;
				throw new DatabaseException('Database connection failed.');

			}
			return self::$connection[$connection_name];
		}

	}

}
Jack06
Profil
Vau zas tak dobře třídy neovládám..
Viz Mastodont
Ten kód vypadá dosti složitě.. Čeho bych docílil použitím takové rozsáhlé třídy (oproti předešlím případům)
Viz tam kde jsi dal ... nebo nevyplnil věci.. mohl by jsi tam naznačit co by v tom mělo zhruba být?

Předpokládám že ej to třída s možností připojení nejen k jedné databázi, pakliže ano, u funkce connect máš napsáno přihlašovací údaje když tam napíšu k jedné db tak jak se to přepojí k jiné při výběru?
Mastodont
Profil
Jack06
Kód je složitější, protože konfigurace je v externím souboru (nesnáším konfiguraci v kódu) - první dvě vynechávky jsou jen název souboru, kromě toho jsem vypustil parametry konstruktoru mysqli, aby to bylo přehlednější.

Ano, třída se umí připojit víckrát k MySQL, název připojení můžeš zadat jako parametr:
DB::Connect()->query(...); // default
DB::Connect('admin')->query(...); // jiné než default
BetaCam
Profil
Jack06
Čeho bych docílil použitím takové rozsáhlé třídy

Ono je potřeba si uvědomit, že knihovna pro práci s DB by měla být univerzální a její "složitost" se od toho odvíjí.

Mastodont
No protože většina lidí nepotřebuje víc připojení nebo různé druhy DB ... aneb KISS

To je sice pravda, ale zrovna DB Layer by se měl navrhovat jako univerzální a ne jako jednoúčelová třída.
Mastodont
Profil
BetaCam
No jo, ale co vše se rozumí pojmem universální? Jsou lidi, kteří vyžadují, abys mohl mít část dat na Oraclu a část na Postgre, a když to DB vrstva neumí, tak je to špatně. Všechno má své meze.
DB knihoven je asi 123 456 a nějaký drobný k tomu, píše si je každý, nemusí mít všechny stejnou funkčnost.
Jack06
Profil
Mastodont
Můžeš mi napsat jak b budou ty soubory vypadat? Jakým způsobem v nich budou sepsaná přihlašovací údaje, aby se to připojilo? a kam strčíš to new mysqli nebo mysqli_connect.. ?
« 1 2 »

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: