Toon posts:

[PHP] Database Class

Pagina: 1
Acties:

Verwijderd

Topicstarter
Afbeeldingslocatie: http://julien.interned.com/dbontwerp.gif

Ik heb een hoofd class: Database. Daarin doe ik bijvoorbeeld errors weergeven of de errors wegschrijven in een bestand. Als ik de errors weg wil schrijven in een bestand wil ik dit het liefst aan het einde van het script doen dus niet per error. Alleen wanneer weet ik wanneer dat is? Moet ik hiervoor een extra functie maken die aan het einde aangeroepen moet worden? (jammer dat destructors niet ondersteund worden)

De PostgreSQL klas is de extentie op Database. Er moeten dus meerdere extenties gemaakt kunnen worden met dezelfde functies zodat het switchen van database makkelijker wordt.

De $connectionString in de constructor van Database wil ik gaan gebruiken bij connect () pas wanneer er een query uitgevoerd moet worden, dus niet onnodig connecten.

Het probleem is hoe moet ik query's gaan uitvoeren? Op de database moeten er meerdere query's uitgevoerd kunnen worden en op die query's moeten weer meerdere functies uitgevoerd worden zoals getQueryNumRows, getQueryResult etc. Ik kan nu in de functie doQuery om een naam van de query vragen zodat die bij getQueryNumRows als invoer gebruikt wrodt en dat ik in de postgresql class een array maak waar ik de connection id's in opsla met de namen van de query's.

Is dit een goede manier? Of zouden voor alle query's nieuwe objecten gemaakt moeten worden en dat daar ook de functies inzitten om numrows enzo te doen? Dat lijkt mij eigenlijk wel een mooie manier maar hoe maak ik zoiets? Ik wil dan nog wel dat die kan samenwerken met de class PostgreSQL.

Is het te doen door een class te maken die niet geextend is uit de class postgresql: Query. Als ik dan in de query constructor de postgresql object variabele als reference door geef dan zou de query class de postgresql klas kunnen gebruiken en zouden er meerdere objecten van de query class kunnen zijn.

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Allereerst, zitten de Connect(), DisConnect() en doQuery() functies in de class 'Database'?
Zo niet, waarom niet? Wanneer je deze functies in database zou zetten en virtual zou maken heb je een zeer goed OO design te pakken.

Verder zou ik een (opgeleverde) query als een object beschouwen met een set operaties als NumRows(), Cursor(), etc. Hier kan je eventueel ook weer classes van afleiden met specifiekere acties op die query die niet voor alle databases van toepassing zijn.

Verwijderd

Topicstarter
Op zaterdag 08 juni 2002 20:45 schreef Orphix het volgende:
Allereerst, zitten de Connect(), DisConnect() en doQuery() functies in de class 'Database'?
Zo niet, waarom niet? Wanneer je deze functies in database zou zetten en virtual zou maken heb je een zeer goed OO design te pakken.
Wat bedoel je met virtual? De functie daar neer zetten zonder acties in de body? En hem dan in de PostgreSQL class uitwerken?

Class Database
PHP:
1
<?function connect ();?>

Class PostgreSQL
PHP:
1
<?function connect (){  $connection = pg_connect ($this->connectionString);  //etc.}?>

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Op zaterdag 08 juni 2002 20:59 schreef Xenith het volgende:

[..]

Wat bedoel je met virtual? De functie daar neer zetten zonder acties in de body? En hem dan in de PostgreSQL class uitwerken?

Class Database
PHP:
1
<?function connect ();?>

Class PostgreSQL
PHP:
1
<?function connect (){  $connection = pg_connect ($this->connectionString);  //etc.}?>
Ja dat bedoel ik dus :P
Dat werd mij dus niet helemaal duidelijk uit de afbeelding.

Verwijderd

Topicstarter
Dat was het ook niet en ik wist eigenlijk ook niet dat dat kon :). Php pikt het alleen niet als ik zeg function connect (); Dan gaat ie vragen om de accolades.

Dit is wat ik ongeveer heb (database):
PHP:
1
<?class Database{  var $connectionString;  var $isConnected = FALSE;  var $connection;  var $query;    var $errorReporting = "visible";    function Database ($connectionString)  {    $this->connectionString = $connectionString;    $this->siteName = $siteName;  }    function setErrorReporting ($errorReporting)  {    $this->errorReporting = $errorReporting;  }    function throwError ($errorMessage, $fatal = FALSE)  {    if ($this->errorReportingName == "visible")      echo "<b>DB Error:</b> ". $errorMessage ."<br>\n";    //etc...        if ($fatal)      exit;  }    function connect (){}  function disconnect (){}  function newQuery ($queryName, $querySQL){}}class PostgreSQL extends Database{  function connect ()  {    if (!$this->isConnected)    {      $this->connection = pg_connect($this->connectionString);      $this->isConnected = TRUE;    }  }    function disconnect ()  {    if ($this->isConnected)    {      pg_close ($this->connection);      $this->isConnected = FALSE;    }  }    function newQuery ($queryName, $querySQL)  {    if (!$this->isConnected)      $this->connect ();        $this->query[$queryName] = new PostgreQuery ($this->connection, $querySQL);  }}?>

En de query class:
PHP:
1
<?class Query{  var $connection;  var $queryResourse;    function Query ($connection, $querySQL)  {    $this->connection = $connection;    $this->doQuery ($querySQL);  }    function doQuery ($querySQL){}  function getNumRows (){}  //etc...}class PostgreQuery extends Query{  function doQuery ($querySQL)  {    $this->queryResource = pg_exec ($this->connection, $querySQL);  }    function getNumRows ()  {    return pg_numrows ($this->queryResource);  }  //etc...}?>

Een voorbeeld hoe ik de class gebruik:
PHP:
1
<?$db = new PostgreSQL ("connectie string");$db->newQuery ("links", "SELECT * FROM links");echo $db->query["links"]->getNumRows();?>

Dit werkt allemaal best mooi, maar ik denk toch dat ik problemen ga krijgen omdat de query class niks van de database class kan gebruiken. Dus als er een error komt kan ik die niet via de database class laten lopen. Ook moet ik nu de connection meegeven en dat is ook niet zo fraai denk ik.

Verwijderd

Topicstarter
Ik heb het nu opgelost door de PostgreSQL class zichzelf als reference mee te laten gevan aan de constructor van de class Query. Hierdoor kan de query class wel de functies in de database class gebruiken.

In class PostgreSQL:
PHP:
1
<?  function newQuery ($queryName, $querySQL)  {    if (!$this->isConnected)      $this->connect ();        $this->query[$queryName] = new PostgreQuery ($this, $querySQL);  }?>

Query class:
PHP:
1
<?class Query{  var $db;  var $queryResourse;    function Query (&amp;$db, $querySQL)  {    $this->db = &amp;$db;    $this->doQuery ($querySQL);  }    function doQuery ($querySQL){}  function getNumRows (){}  //etc...}class PostgreQuery extends Query{  function doQuery ($querySQL)  {    $this->queryResource = pg_exec ($this->db->connection, $querySQL);  }    function getNumRows ()  {    return pg_numrows ($this->queryResource);  }  //etc...}?>

Is dit de goede manier om het te doen? Ook het virtual maken van de functies in de hoofd classes vind ik nog niet zo omdat het eigenlijk niet ondersteund wordt in PHP. Nu heb ik gewoon wat lege functies dus niet echt virtual lijkt mij.

Verwijderd

Waarom verschilde classes maken voor verschillende dbases? Het is toch veel gemakkelijker in deze aard:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class dbase
{
    var $db_type; /* 1 == mysql, 2 == ... */
    ...
}

...


        function connect()
        {
        if ($this->db_type == 1)
        {
                ... /* doe de mysql connect functie */
        }
        else if (...)
        {
            
        }
    }
}

De bedoeling is toch dat je heel gemakkelijk kan overschakelen naar een andere dbase, zonder heel je code moeten aan te passen. Maar als je verschillende class-files gaat maken, moet je dat toch wel doen?

Of zit ik zelf mis? :)

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Tja PHP ondersteund geen pure virtuele functies, dat wil zeggen dat descendants van een class altijd die functies MOETEN implementeren. Een lege body werkt echter goed en alle class methods in PHP zijn standaard virtueel dus het geeft wel de werking die je verwacht.
Ik vind de database class wel goed opgezet.

Om een aparte query class te maken voor de manier waarop jij het doet vind ik een beetje overkill. Ik zag de query object meer als het resultaat van een query. De dataset dus. Misschien was query niet helemaal de goede benaming.
Deze dataset hoeft in principe geen binding te hebben met de oorspronkelijke database.

Je doet dus zoiets als
code:
1
2
3
4
$db = new PostgreSQLDB("user", "pass");
$db->connect();
$dataset = $db->doQuery("SELECT * FROM users");
echo "Number of rows returned : " . $dataset->getNumRows();

Verwijderd

Topicstarter
Op zondag 09 juni 2002 17:48 schreef DiEana het volgende:
Waarom verschilde classes maken voor verschillende dbases?

De bedoeling is toch dat je heel gemakkelijk kan overschakelen naar een andere dbase, zonder heel je code moeten aan te passen. Maar als je verschillende class-files gaat maken, moet je dat toch wel doen?
De verschillende classes zijn alleen specifiek voor de verschilende databases. Dus aan de class Database hoef je als het goed is helemaal niks aan aan te passen.

Als je over gaat naar een andere database hoef je alleen de includes en de naam van de database te veranderen:
PHP:
1
<?//PostgreSQLinclude "db.php";include "postgresql.php"$db = New PostgreSQL ("connect instellingen");//MySQLinclude "db.php";include "mysql.php"$db = New MySQL ("connect instellingen");?>

Je moet dan natuurlijk wel de mysql extentie hebben of helemaal maken alleen ik denk dat dat niet veel werk is als je al bijvoorbeeld de postgresql extentie hebt gemaakt.

Verwijderd

Op zondag 09 juni 2002 18:27 schreef Xenith het volgende:

[..]

De verschillende classes zijn alleen specifiek voor de verschilende databases. Dus aan de class Database hoef je als het goed is helemaal niks aan aan te passen.

Als je over gaat naar een andere database hoef je alleen de includes en de naam van de database te veranderen:
PHP:
1
<?//PostgreSQLinclude "db.php";include "postgresql.php"$db = New PostgreSQL ("connect instellingen");//MySQLinclude "db.php";include "mysql.php"$db = New MySQL ("connect instellingen");?>

Je moet dan natuurlijk wel de mysql extentie hebben of helemaal maken alleen ik denk dat dat niet veel werk is als je al bijvoorbeeld de postgresql extentie hebt gemaakt.
Volgens mij is het toch veel simpeler (waarom moeilijk maken als het makkelijker ook kan?) als je alle "dbase functies" (in de brede zin) in 1 file/class hebt? Daarbij moet je sommige dingen niet opnieuw/dubbel gaan coden: ik denk bijvoorbeeld aan een functie die een string maakt voor een goede searchfunctie. Als je elke dbase in een aparte class gaat zetten, gaat dat echt moeilijk werken?

En je theorie van "errors in de class Database" volg ik helemaal niet? Wat doe je dan met de commandos: mysql_perror()/mysql_errno()/...? Deze wil je dan ook in de "hoofdclass", hoewel ze TOCH afhankelijk zijn van je dbase?

Verwijderd

Voor de geïnteresseerden, ik doe het al maanden zo:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?
// anaEiD (peter@clueless.be)

class dbase
{
    var $db_type; /* 1 == mysql */
    var $db_server;
    var $db_name;
    var $db_user;
    var $db_pass;
    var $db_persistent;
    var $dbh;
    var $result;
    var $count;
        
    function dbase($type, $server, $db, $user, $pass)
    {
        $this->db_type = $type;
        $this->db_server = $server;
        $this->db_name = $db;
        $this->db_user = $user;
        $this->db_pass = $pass;
          
        $this->db_persistent = 1;
        $this->count = 0;
          
        $this->connect();
    }

    function connect()
    {
        if ($this->db_type == 1)
        {
            if ($this->db_persistent)
                $this->dbh = @mysql_pconnect($this->db_server, $this->db_user, $this->db_pass);
            else
                $this->dbh = @mysql_connect($this->db_server, $this->db_user, $this->db_pass);

            @mysql_select_db($this->db_name, $this->dbh) or die ("ERROR: Connection to MySQL database failed.");
        }
    }

    function query($query)
    {
        if ($this->db_type == 1)
            $this->result = mysql_query($query, $this->dbh) or die ("ERROR: $query.");

        $this->count++;
    }
     
    function num_rows()
    {
        if ($this->db_type == 1)
            return mysql_num_rows($this->result);
    }
        
    function affected_rows()
    {
        if ($this->db_type == 1)
            return mysql_affected_rows();
    }

    function fetch_array()
    {
        if ($this->db_type == 1)
            return mysql_fetch_array($this->result);
    }
        
    function num_queries()
    {
        return $this->count;
    }
        
    function reset_num_queries()
    {
        $this->count = 0;
    }
}

En ik heb nog nooit problemen ondervonden. En hij is makkelijk (heb ik wel niet gedaan, heb het voorlopig ook niet nodig) uitbreidbaar naar andere soorten dbases.

Ik zie echt niet in waarom je het je zo moeilijk zou maken hoor :)

Verwijderd

Topicstarter
Hoe de errors gemaakt worden in mysql, postgresql, oracle etc. interesseert me niet zo veel. In je postgresql/mysql/etc class moet je deze errors gewoon onderscheppen en dan doorgeven aan de functie throwError ($errorMessage, $fatal). Dan kan er in de database class er voor gekozen worden om deze errors direct weer te geven via echo, of bijvoorbeeld ze in een tekst bestand te loggen (dat lijkt mij wel een goede functie).

Het is de bedoeling dat algemene dingen in de database class gebeuren en de specifieke dingen in de postgre/mysql/etc. classen gebeurt.

Hierdoor heb je niet dat je bij elke functie een hele rij if's krijgt om voor elke database de functie uit te voeren (dus code wordt overzichtelijker).

Je ziet alles als soort bouwstenen die wanneer ze gemaakt zijn ook helemaal af zijn. Jouw class is niet af wanneer je het alleen voor mysql heb. Ik kan misschien de totale database, query en postgresql classen schrijven en deze dan op internet vrijgeven zodat misschien anderen een mysql class er voor schrijven zonder dat ze de database class hoeven aan te passen. Het is misschien daardoor ook makkelijker om specifieke database functies toe te voegen.

Ik vind eigenlijk ook niet dat ik het mijzelf moeilijker maak. Ik heb al een frame van functies die ik moet gaan maken per database en dan is het alleen ff uitwerken. Jij zal per database bij elke database een extra if moeten gebruiken. De code die jij gebruikt in de if's is waarschijnlijk hetzelfde als die ik gebruik in de postgresql/mysql/etc class.

Verwijderd

Topicstarter
Op zondag 09 juni 2002 18:12 schreef Orphix het volgende:
Om een aparte query class te maken voor de manier waarop jij het doet vind ik een beetje overkill. Ik zag de query object meer als het resultaat van een query. De dataset dus. Misschien was query niet helemaal de goede benaming.
Deze dataset hoeft in principe geen binding te hebben met de oorspronkelijke database.
Hmz ja daar heb je wel gelijk in en het is denk ik een mooiere oplossing omdat je van die querynamen af bent. Het is denk ik niet zo moeilijk om het daaraan aan te gaan passen. Ik return gewoon in mijn newQuery een object van postgreQuery. Dan zijn ze nog wel met elkaar verbonden en kan ik de errors daarmee door laten sturen.

In de postgresql class (was eerst newQuery):
PHP:
1
<?  function doQuery ($querySQL)  {    if (!$this->isConnected)      $this->connect ();        return new PostgreQuery ($this, $querySQL);  }?>

Verwijderd

Topicstarter
Ik zag net op php.net dat er een nieuwe alpha release is waarin wel destructors ondersteund worden :). Ook kan je private variabelen gebruiken, jammer alleen dat je geen private functies kan maken.

  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 31-03 16:47

CyberSnooP

^^^^ schrijft --->

Op zondag 09 juni 2002 20:48 schreef Xenith het volgende:
Ik zag net op php.net dat er een nieuwe alpha release is waarin wel destructors ondersteund worden :).
buiten-onderwerp:
Je kunt op de PEAR manier altijd destructors na maken (m.b.v. register_shutdown_function). Hoewel er subtiele beperkingen zijn is de methode erg eenvoudig

|_____vakje______|

Pagina: 1