 |
Forum PHP Romania - Discutii despre PHP, MySQL, Javascript, AJAX, etc Comunitatea PHP Romania
|
| Subiectul anterior :: Subiectul următor |
| Autor |
Mesaj |
cdanea
Data înscrierii: 05/Iul/2003
Mesaje: 115
Locație: Bucuresti
|
| Trimis: Mar Dec 06, 2005 3:30 pm Titlul subiectului: Extending PEAR/DB |
|
|
Am tot incercat sa adaug metode proprii la PEAR Database abstraction layer, si dupa multe incercari esuate, singura solutie este urmatoarea.
Ideea este sa atasez cateva functii la DB_mysql care mi-ar folosi mie, si mi-ar usura munca, fara sa umblu in sursa PEAR, ceea ce intra in categoria "do not try this at home".
an style="color: #000000"><?php require_once ( 'DB.php' );
class myDB extends DB{
function __construct($dns){
parent::connect($dns);
DB_common::setFetchMode(DB_FETCHMODE_ASSOC);
DB_mysql::autoCommit(true);
}
public function dump_table($tbl){
echo $tbl;
return true;
}
}
$db = new myDB('mysql://user:pass@localhost/database');
$db->dump_table("test");
?>
Problema cu aceasta solutie este ca nu mai am acces la metodele parintilor... ceea ce nu e rezultatul dorit.
In alte incercari nu reuseam sa vad decat metodele parintilor (adica DB_mysql, DB_common , DB si PEAR), ceea ce iar nu e bine.
Cred ca m-am incurcat rau de tot printre plozii si parintii arborelui genealogic al lui PEAR.
Daca cineva vede o aberatie, va rog sa imi dati o alta solutie...
Multumesc |
|
| Sus |
|
aurelian
Data înscrierii: 01/Iun/2003
Mesaje: 833
Locație: Bucuresti
|
| Trimis: Mar Dec 06, 2005 5:29 pm Titlul subiectului: |
|
|
Cred ca nu trebuie extinsa clasa DB, aceasta ofera doar o colectie de metode statice.
Eu cred ca mai indicat, este sa extinzi clasa DB_mysql daca doresti sa adaugi metode valabile doar pentru mysql (de ex. DB_mysqlImproved).
Pentru a folosi aceasta clasa, pasezi un dsn asemanator cu cel pentru mysql, doar ca inlocuiesti mysql cu mysqlImproved.
Asa o sa ai acces si la metodele din DB_common, la cele din DB_mysql dar si la metodele tale.
O tabela de mostenire:
DB_common extends PEAR.
DB_mysql extends DB_common.
DB_mysqlImproved extends DB_mysql. |
|
| Sus |
|
cdanea
Data înscrierii: 05/Iul/2003
Mesaje: 115
Locație: Bucuresti
|
| Trimis: Mar Dec 06, 2005 5:37 pm Titlul subiectului: |
|
|
Asta ar functiona, dar atunci as face din "Database Abstraction Layer" un "Database Particularisation Layer" ...
Ideea e sa pot sa folosesc aceleasi metode indiferent daca folosesc odbc, mysql, informix etc ...
Oricum observatia cu extinderile mi-a aratat ca intr-adevar nu am cum sa il extind pe DB direct.
Am sa incerc sa il mostenesc pe DB_common, ca doar nu s-o chema asa doar de fantezie.
Deci intrebarea ramane deschisa: vreau sa creez o clasa care adauga metode la un DB din PEAR. Metodele pe care vreau sa le implementez trebuie sa fie SQL compliant, sau sa ofere informatii independente de server, astfel incat sa le pot folosi pe orice fel de arhitectura, nu doar pt MySQL. |
|
| Sus |
|
aurelian
Data înscrierii: 01/Iun/2003
Mesaje: 833
Locație: Bucuresti
|
| Trimis: Mar Dec 06, 2005 5:59 pm Titlul subiectului: |
|
|
Pai, nu cred ca merge fara a modifica nimic in pachetul DB.
Poti incerca:
1. clasa ta sa extinda PEAR si sa modifici DB_Common sa extinda noua ta clasa.
2. clasa ta sa extinda DB_Common si sa modifici toate clasele driver (like DB_mysql, DB_sqlite .etc) sa extinda noua ta clasa.
3. sa adaugi metodele tale in DB_Common iar diff-ul (patch) sa il trimiti dezvoltatorilor pachetului PEAR/DB, si cu putin noroc o sa le includa intr-un nou release.
4. sa folosesti un alt abstraction layer care se supune cerintelor tale.
O alta varianta ar fi sa folosesti ceva asemanator:
Cod:
class MyClass {
var $dbh;
function MyClass($dbh) {
if (!is_a('DB', $dbh)) { // (nu stiu exact sintaxa si tipul de obiect pe care il returneaza DB::factory
trigger_error('DBH is not a DB! (illegal argument exception', E_USER_ERROR);
}
$this->dbh= $dbh;
}
/*
metodele tale ce pot folosi handlerul la baza de date
*/
}
$db = &new MyClass(DB::factory($dsn));
// query:
$db->dbh->query();
// metoda:
$db->doSomething();
|
|
| Sus |
|
cdanea
Data înscrierii: 05/Iul/2003
Mesaje: 115
Locație: Bucuresti
|
| Trimis: Mie Dec 07, 2005 12:34 pm Titlul subiectului: |
|
|
e o idee buna, desi aceasta implementare nu ma indeparteaza prea mult de
an style="color: #000000"><?php <php
$db=new DBLayer("host","user","pass","database");
// unde clasa asta e scrisa de mine de la A la Z
?>
si atunci de ce sa mai folosesc PEAR?
oricum multumesc, e clar ca asta va functiona. |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Mie Dec 07, 2005 5:47 pm Titlul subiectului: |
|
|
| Pai ce alte metode ai vreai sa adaugi? dump_table se face cu 2 queryuri, create table cu un query, alter table alt query si tot asa. Deci, daca presupunearea mea e corecta, un pattern decorator (sau delegator, sincer n-am priceput diferenta dintre ele) este o solutie. In php5 o poti implementa chiar usor, in php4 e nitel mai multa munca. |
|
| Sus |
|
aurelian
Data înscrierii: 01/Iun/2003
Mesaje: 833
Locație: Bucuresti
|
| Trimis: Joi Dec 08, 2005 10:29 am Titlul subiectului: |
|
|
Ai mai putea sa folosesti niste magie php, valabila in php 4 cu optiunea --enable-overloading la compilare (by default in windows) si nativ in php 5 (doar daca nu ai compilat cu --disable-overloading)
Cod:
class MyClass {
private $ddh;
public function MyClass($dbh) {
$this->dbh= $dbh;
}
public function __call($method, $arguments) {
/* if (!method_exists($method, $this->dbh)) throw new Exception ('Call to undefined method...'); */
return $this->dbh->$method($arguments[0]);
}
/* alte metode */
function dump_table($table) {
echo $table;
}
}
$myDB= new MyClass(DB::factory($dsn));
// apel metoda:
$myDB->query($select_sql);
// apel metoda definita de tine
$myDB->dump_table($table);
mai multe detalii: http://ro.php.net/manual/en/language.oop5.overloading.php
(vezi method overloading) |
|
| Sus |
|
coditza
Data înscrierii: 23/Ian/2004
Mesaje: 298
Locație: cluj-napoca
|
| Trimis: Joi Dec 08, 2005 11:43 am Titlul subiectului: |
|
|
Exact despre asta vorbeam :)
Ma paote cineva lamuri ce patern e ala? :D |
|
| Sus |
|
aurelian
Data înscrierii: 01/Iun/2003
Mesaje: 833
Locație: Bucuresti
|
| Trimis: Joi Dec 08, 2005 12:16 pm Titlul subiectului: |
|
|
coditza a scris:
Ma paote cineva lamuri ce patern e ala? :D
conteaza un nume acum?
foloseste-l si fii fericit :D
pe alte forumui se discuta pe 25-30 de pagini numele unui patern, cam neproductiv dupa parerea mea.
p.s. delegat :P |
|
| Sus |
|
cdanea
Data înscrierii: 05/Iul/2003
Mesaje: 115
Locație: Bucuresti
|
| Trimis: Joi Dec 08, 2005 12:47 pm Titlul subiectului: |
|
|
M-am hotarat sa imi fac un factory pe baza stivei definite de DB_common si plozii lui . Iata solutia pe care am facut-o pentru a rezolva tema initiala a thread-ului
Mai sus e o solutie eleganta, si in cazul de mai jos chiar am folosit-o; in loc sa definesc disconnect ca metoda a copilului, o apelez direct, si __call returneaza ce vreau, adica $db->db->disconnect()
<?php
require_once ( 'DB.php' );
class myDB extends DB_common{
protected $db=null;
protected $env=array();
function myDB($dns){
$this->db=DB::connect($dns);
if(PEAR::isError($this->db)){
echo "<br />Eroare<br />";
echo $db->getMessage();
}
else{
$this->db->setFetchMode(DB_FETCHMODE_ASSOC);
//alte setari care configureaza obiectul
}
}
public function __call($method, $arguments) {
if (!method_exists($method, $this->db)){
// throw new Exception ('Call to undefined method...');
return false;
}
return $this->db->$method($arguments[0]);
}
public function factory($dns){
$d=DB::parseDSN('mysql://root:@localhost/test');
switch($d['phptype']){
case 'mysql':
return new mysqlDB($dns);
case 'odbc':
return new odbcDB($dns);
}
}
public function my_old_disconnect(){
// nu mai am nevoie, folosesc __call() pentru a apela direct metoda din $this->db
$this->db->disconnect();
}
}
class mysqlDB extends myDB{
function mysqlDB($dns){
parent::__construct($dns); // seteaza obiectul $this->db,se conecteaza etc
$this->env=DB::parseDSN($dns);
}
public function query($sql){
return $this->db->query(mysql_real_escape_string($sql));
}
public function get_tables($mod=''){ // o metoda oarecare
$sql="show tables";
$result=$this->query($sql);
while($row=$result->fetchRow())
$r[]=$row["Tables_in_".$this->env['database']];
return $r;
}
// alte metode pe care le folosesc in mod curent, si sunt comopozitii de metode din DB_common (query-uri,fetch-uri)
}
class odbcDB extends myDB{
function odbcDB($dns){
parent::__construct($dns);
$this->env=DB::parseDSN($dns);
}
// etc
}
echo "<pre>";
$db= myDB::factory('mysql://user:@localhost/test');
//print_r($db);
print_r($db->get_tables());
$db->disconnect();
?>
output
Cod:
Array
(
[0] => board
[1] => books
[2] => careers
[3] => clients
[4] => links
[5] => news
[6] => sessiondata
)
|
|
| Sus |
|
aurelian
Data înscrierii: 01/Iun/2003
Mesaje: 833
Locație: Bucuresti
|
| Trimis: Joi Dec 08, 2005 5:00 pm Titlul subiectului: |
|
|
probabil offtopic, dar daca doresti sa afli informatii despre baza de date, cred ca ar trebui sa folosesti Creole, vezi aici:
http://creole.phpdb.org/wiki/wiki.php?node=5#A24
in primul rand nu iti introduce stupizenia de dependinta PEAR, mai mult iti ofera un api mult mai curat si elegant decat PEAR_DB |
|
| Sus |
|
cdanea
Data înscrierii: 05/Iul/2003
Mesaje: 115
Locație: Bucuresti
|
| Trimis: Joi Dec 08, 2005 5:29 pm Titlul subiectului: |
|
|
nu, nu doresc sa aflu informatii despre baza de date. era doar un exemplu de functie.
Sincer si mie mi se pare o stupizenie PEAR, dar nu chiar atat de mare incat sa folosesc creole, care are exact aceleasi stereotipuri ca si PEAR imho.
Iata un exemplu de creole:
an style="color: #000000"><?php $stmt = $conn->prepareStatement("INSERT INTO users (id, name, created) VALUES (?,?,?)");
$stmt->setInt(1, $id);
$stmt->setString(2, $name);
$stmt->setTimestamp(3, time());
$stmt->executeUpdate();
pentru a face un update de genul asta in PEAR, cu metodele standard oferite e cam aceeasi porcarie.
Eu vreau sa extind un api stabil (si cred ca PEAR este stabil, oricat de alambicat ar fi) si sa fac un update uite asa:
an style="color: #000000"><?php $db = new mysqlDB($dns);
$db->update("tabela" , $recordset , 433 , "tabela_id");
unde prototipul lui update e
an style="color: #000000"><?php public function update(string tabela, array recordset, mixed cond,mixed key);
$tabela - tabela din DB
$recordset - array asociativ de field->valoare
$cond si $key sunt conditiile de update
$cond e o valoare scalara / $key e nume camp (eventual primary key)
$cond e un array de 'field'=>$value / $key dontcare
Nu imi place PEAR, tocmai de aia vreau sa il extind cu functiile mele, care sa automatizeze cateva operatii comune. Nu am innebunit sa folosesc vreodata prepareQuery, sau cum naiba s-o numi in PEAR. De ce sa fac 20 de atribuiri, 50 de evaluari si 30 de apeluri de metode prin mostenitori, frati si unchi ai lui DBmysql, pentru un amarat de update ?
momentan sunt satisfacut de solutia pe care am prezentat-o mai sus, si merge frumos impreuna cu PEAR/HTMLSession (pe care l-am extins deja dupa modelui lui DB_common). Daca cineva are imbunatatiri, le astept cu infrigurare. |
|
| Sus |
|
PHPRomania Bot
Bot Member
Data înscrierii: 27/Dec/2007
Mesaje: 1
Locaţie: Server Google |
| Trimis: Mie Dec 26, 2007 7:01 pm Titlul subiectului: Ad |
|
|
|
|
|
| Sus |
|
| |
|