Vraag & Antwoord

Webprogrammeren & scripting

database class MySQL+PostgreSQL

15 antwoorden
  • ik heb dus nu mijn zelfgeschreven databseclass in gebruik, maar ik betwijfel of ik het op de goede manier gebruik, ik heb namelijk nog steeds vars die voor de database zijn, maar neit in het object staan. ff een voorbeeldje zoals ik mijn class gebruik: <? $db=new database('database'); //object aanmaken $result=$db->query('SELECT * FROM gegevens'); //querie draaien $resultaat=$db->fetch_array($result,false); //2d array naar php halen echo($resultaat[1]['achternaam'].'<br />'); //resultaat weergeven echo($db->num_rows($result).'<br />'); //aantal rijen weergeven echo($db->result($result,1,'voornaam')); //nog een resultaat echoen $db->free_result($result); //gehuegen vrijmaken ?> is dit uit OOP perspectief een beetje netjes werken? en is dit een goede class, ik werk namelijk voor het eerst met OOP class: [url=http://62.251.18.80/class.php]Bekijk hier de class[/url]
  • Simon_banaan, Overstappen van procedural naar OO programmeren is niet iets simpels: het is een soort 'klik' die je manier van denken verandert over programmacode. Jij hebt die 'klik' nog niet gemaakt, maar dat is logisch aangezien dit je eerste poging is ;). Je maakt een aantal veelgemaakte beginnersfouten. 1. Veel mensen die met OO beginnen is dat ze beginnen met functies die bij elkaar horen in één class te stoppen. Het is een samengerapte collectie van functies, meer niet. Als je de class{} weghaalt, dan zijn al je functies perfect te gebruiken. 2. Veel mensen die met OO beginnen, zien het verschil tussen een class en een object niet. Jouw class heeft geeneens geïnitaliseerd te worden om te werken(heeft ook met punt 1 te maken). Een class is een bouwtekening\blauwdruk voor een object. Een object is een geïnitieerde class. 3. Veel mensen die met OO beginnen, maken de fout door te echo'en in een class. Zie bijv. jouw foutafhandeling. Niet doen! En het gebruikelijk om gewoon FALSE te retourneren als iets fout gaat. De gebruiker kan dan zelf aan het object vragen wat er mis is gegaan als hij dit wil weten. Bijv:[code:1:8a44aa6264]if ($result=$db->query('SELECT * FROM gegevens')) { // fout direct op het scherm echo $db->getError(); // of meld een ander fout en mail de fout naar de beheerder echo 'Het is helaas niet gelukt om de gegevens op te halen'; mail("joecool@example.com", "[error] query doesn't work", "Fout in bla.."); }[/code:1:8a44aa6264] 4. Veel mensen die met OO beginnen, benoemen hun object en methodes\properties verkeerd. Bijv.: $db->num_rows($result)... Je vraagt iets aan een object, dan is $db->getRowCount($result) of $db->getNumberOfRows($result) duidelijker. Wat doet $db->result(..)? Is het niet beter in plaats hiervan $db->getValue(..) te schrijven? [quote:8a44aa6264="simon_banaan"]..ik heb namelijk nog steeds vars die voor de database zijn, maar neit in het object staan.[/quote:8a44aa6264]Je moet een object zien als een 'black box'. Je voert hem gegevens (je vars) en dan doet hij het werk voor je. Deze 'black box' hoef je nooit aan te passen, dus als bijv. je gebruikersnaam verandert moet je dit niet in de class te hoeven aanpassen. [quote:8a44aa6264="simon_banaan"]is dit uit OOP perspectief een beetje netjes werken? en is dit een goede class[/quote:8a44aa6264]Syntax gezien is het OOP, meer niet vanuit OO denken. Een paar tips/vragen om je aan het denken te zetten: Gebruik de constructor alleen om je object te initaliseren en doe geen dingen die fout kunnen gaan. Stel er is geen verbinding en je mag niet echo'en vanuit een object! Hoe weet de gebruiker dat het verbinden mislukt is? Het object geeft mij een resultset. Waarom moet ik dezelfde resultset waar aan het object teruggeven, om te tellen of een array te krijgen? Wat heeft een resultset eigenlijk te maken met een databaseconnection? Als je 200 verschillende typen databasen wil gaan ondersteunen, dan wordt het wel een hele groot object.... Wat heeft een PostgreSQL-verbinding eigenlijk te maken met een MySQL-verbinding, behalve dat ze dezelfde methode-naam hebben? -Rémy p.s. Ik vind je manier van programmacode schrijven verschrikkelijk. Gebruik de normale standaarden zodat je code makkelijk leesbaar is voor andere mensen. Gebruik geen underscores in methodes, dus niet $db->fetch_results(), maar $db->fetchArray(...) (is trouwens ook slechte naam voor een methode). Indent goed, geen code achter accolades, verminder je if-statemants als dit kan, benoem je properties en gebruik deze niet zomaar ($this->rDb). Dus:[code:1:8a44aa6264]//niet zo class database{ var $sDatabaseType='MySQL'; function close_con() {if($this->sDatabaseType=='MySQL') {//begin mysql if(!mysql_close($this->rDb)) {$this->error(6); return false; } //einde mysql } if($this->sDatabaseType=='PgSQL') {//begin pgsql if(!pg_close($this->rDb)); {$this->error(6); return false; } //einde pgsql } } } //maar zo class Database { var $type; var $conn; function closeConnection() { switch ($this->type) { case 'MySQL': return (mysql_close($this->conn)) ? True : False ; break; case 'PgSQL': return (pg_close($this->conn)) ? True : False ; break; } }[/code:1:8a44aa6264]
  • dat echeon in de class doe ik nu alleen maar om de class zelf te testen... dat gaat later weg, want idd echoen in de class is niet handig [quote:e02983805c]4. Veel mensen die met OO beginnen, benoemen hun object en methodes\properties verkeerd. Bijv.: $db->num_rows($result)... Je vraagt iets aan een object, dan is $db->getRowCount($result) of $db->getNumberOfRows($result) duidelijker. Wat doet $db->result(..)? Is het niet beter in plaats hiervan $db->getValue(..) te schrijven? [/quote:e02983805c] is dit niet een questie van persoonlijke smaak? ik gebruik gewoon de namen van de mysql fucnties en haal daar mysql af, dan weet ik precies wat ze doen:) maar ik zla dr ff over nadenken ja [quote:e02983805c]Je moet een object zien als een 'black box'. Je voert hem gegevens (je vars) en dan doet hij het werk voor je. Deze 'black box' hoef je nooit aan te passen, dus als bijv. je gebruikersnaam verandert moet je dit niet in de class te hoeven aanpassen.[/quote:e02983805c] dat weet ik.. maar aangezien MySQL bijvoorbeeld geen subqueries ondersteunt is het soms nodig om een loop ta maken, je werkt dan met 2 of meer resultsets.. om deze allemaal binnen hetzelfde object te houden is het lastig.. ik he het geprobeert maar belemmeringen in MySQL werken me tegen.. [quote:e02983805c]Als je 200 verschillende typen databasen wil gaan ondersteunen, dan wordt het wel een hele groot object.... Wat heeft een PostgreSQL-verbinding eigenlijk te maken met een MySQL-verbinding, behalve dat ze dezelfde methode-naam hebben? [/quote:e02983805c] ik was vergeten te zeggen dat ik er uiteindelijk 2 classes van maak.. een voor MySQL en een voorn PostgreSQL.. alleen voor het maken zet ik ze ff bij elkaar om te zorgen dat ik dezelfde functienamen en dezelfde paramterd heb.. doel van mijn class is namelijk dat je uiteindelijk makkelijk tussen die 2 kan wisselen, omdat iedereen mbegint met MySQL maar later tegen de beperkingen aanloopt. Ps.. na een tijdje gdacht te hebben ga ik idd ff die namen van methoden veranderen. en de code een beetje herstructureren bdankt voor de tips tot zover.. als iemand nog tipes heeft om die result van een querie binnen het object te houden en toch nog meerdere resutls omtebsuurt kan gebruiken hoor ik het graag..
  • is het mishcien een goede oplossing om een naam mee te geven aan een de querie methode? dan kan ik in het obecjt in een array alle resultsets opslaan. dan heb ik alle databse functies binnen het object zitten:)
  • [quote:3ae5de20ae]ik was vergeten te zeggen dat ik er uiteindelijk 2 classes van maak.. een voor MySQL en een voorn PostgreSQL.. alleen voor het maken zet ik ze ff bij elkaar om te zorgen dat ik dezelfde functienamen en dezelfde paramterd heb.. doel van mijn class is namelijk dat je uiteindelijk makkelijk tussen die 2 kan wisselen, omdat iedereen mbegint met MySQL maar later tegen de beperkingen aanloopt.[/quote:3ae5de20ae]Ik ben wel meer theoreticus, maar is het niet handiger om 1 DB class te maken en dan 2 classes te maken die die DB class 'extenden' met DB specifieke functies/queries?
  • [quote:95e8bfbcf9="simon_banaan"]is dit niet een questie van persoonlijke smaak? ik gebruik gewoon de namen van de mysql fucnties en haal daar mysql af, dan weet ik precies wat ze doen[/quote:95e8bfbcf9]Je kan je methodes benoemen zoals je wilt, dus het is een kwestie van smaak, maar het is niet de smaak van vele andere OOP-programmeurs ;). Je methodes dienen duidelijk te zijn zodat je object direct te gebruiken is door mensen die niet weten hoe jouw object werkt. Je neemt als uitgangspunt de functies van MySQL en dit is ook verkeerd. Een object is geen verzameling van functies, zoals ik al eerder vertelde. Want misschien heb ik die functies helemaal niet nodig, om het object te laten doen wat ik wil. Met OO denk je op een abstract-nivo over dingen (de implentatie komt pas later en is verborgen). Als ik nu de databasefuncties in PHP direct zou willen gebruiken, dan zou ik denk de handleiding erbij moeten pakken, omdat ik ze te weinig gebruik: ik gebruik hier altijd objecten voor. [quote:95e8bfbcf9="simon_banaan"]ik was vergeten te zeggen dat ik er uiteindelijk 2 classes van maak.. een voor MySQL en een voorn PostgreSQL.. alleen voor het maken zet ik ze ff bij elkaar om te zorgen dat ik dezelfde functienamen en dezelfde paramterd heb.. doel van mijn class is namelijk dat je uiteindelijk makkelijk tussen die 2 kan wisselen, omdat iedereen mbegint met MySQL maar later tegen de beperkingen aanloopt.[/quote:95e8bfbcf9]Maak dan meteen een abstracte(interface) class, waar je de twee classes vanaf leidt. Zo kun je je de methodes (en geen functienamen, want dit zijn geen functies ;)) hetzelfde houden. Dit zorgt er namelijk ook voor dat je goed over je abstracte class nadenkt, zonder over speciefieke MySQL-functies na te denken. [quote:95e8bfbcf9="simon_banaan"]dat weet ik.. maar aangezien MySQL bijvoorbeeld geen subqueries ondersteunt is het soms nodig om een loop ta maken, je werkt dan met 2 of meer resultsets.. om deze allemaal binnen hetzelfde object te houden is het lastig.. ik he het geprobeert maar belemmeringen in MySQL werken me tegen.. als iemand nog tipes heeft om die result van een querie binnen het object te houden en toch nog meerdere resutls omtebsuurt kan gebruiken hoor ik het graag..[/quote:95e8bfbcf9]Ik wist dat dit een probleem zou vormen en daarom stelde ik je ook de vraag:"Wat heeft een resultset eigenlijk te maken met een databaseconnection?" Waarom moet dat ene object ALLES doen? Denk daar eens over na en dan zou je misschien tot een oplossing kunnen komen. -Rémy
  • ik heb hem naar eigen idee flink verbeterd.. de resultsets worden nu aan de hand van een standaardnaam opgeslagen.. ik houd het graag bij 1 class en niet met extends in dit geval, dit omdat ik precies dezelfde methode's wil gebruiken voor zowel mysql als pg sql.. ik deel ze later op in 2 classes denk ik, [url=http://62.251.18.80/class.php]Nieuwe class[/url]
  • sorry foutje met kopieren,nu doet ie het wel? http://62.251.18.80/class.php wie kan mij tips geven over de foutafhandeling? aparthe methode voor maken, of wat is gebruike;ijk?
  • Los van alles wat Rémy je al heeft verteld vind ik dat er nog (minstens) één vitaal onderdeel mist, namelijk het commentaar! Maak alsjeblieft gebruik van commentaar om de code te verklaren, zowel voor jezelf als voor anderen. Maak eventueel gebruik van pre- en postconditions. Preconditions zijn de voorwaarden die gelden om de methode aan te kunnen/mogen roepen. Postconditions is wat er veranderd zou moeten zijn na het aanroepen van de methode. Een simpel voorbeeld zou zijn:[code:1:09c8590514]function close_con(){ /* post: Alle verbindingen met de database zijn gesloten. */ ...[/code:1:09c8590514]Daarnaast is het volgens mij in PHP4 nog niet mogelijk om interfaces te maken, maar zal dit wel kunnen in PHP5. Even geduld nog, ik zit ook al enige tijd met smart te wachten. - Bas
  • [quote:edaac863a9="simon_banaan"]ik heb hem naar eigen idee flink verbeterd.. de resultsets worden nu aan de hand van een standaardnaam opgeslagen..[/quote:edaac863a9]Met alle respect je hebt het niet verbeterd maar je hebt het nog erger gemaakt. Ik heb een aantal fouten aangeduid en adviezen gegeven, maar je hebt geen enkele fout weggehaald en geen enkel advies van mij toegepast in je nieuwe ontwerp. Serieus, vind je zelf dat jouw object een duidelijke/handige manier om informatie uit een db te halen, dan de normale functies? Ik vind het nogal onduidelijke manier. Als ik naar [i:edaac863a9]echo($db->result('ResulSetNaam',1,2));[/i:edaac863a9] kijk, dan ziet dit er ingewikkeld uit en ik heb geen flauw idee wat hier gebeurt. Als ik in een script gewoon mysql_query() vervang voor pg_query(), dan is dat toch veel simpeler, dan jouw object. Stel dat ik dit doe, zoals onderstaand. Is dit niet veel leesbaarder en begrijpelijker? [code:1:edaac863a9]$db =& new MySqlDatabase(DB_NAME, DB_HOST); $db->connect(DB_USERNAME, DB_PASSWORD); $rs =& $db->query('SELECT CID, naam FROM customers WHERE CID=12345'); $customer =& $rs->getRow(0); echo $rs->getRowCount(); echo $customer['serial_number']; echo $customer['naam'];[/code:1:edaac863a9] [quote:edaac863a9="simon_banaan"]is het mishcien een goede oplossing om een naam mee te geven aan een de querie methode? dan kan ik in het obecjt in een array alle resultsets opslaan. dan heb ik alle databse functies binnen het object zitten:)[/quote:edaac863a9]Nee, dit is geen goede oplossing. Nogmaals wat heeft een resultset met een databaseverbinding te maken? Misschien dat een vergelijking helpt: wat heeft een opgehaalde bestand met een ftp-verbinding te maken? (Dus waarom zijn een resultset en een dbverbinding één object?) [quote:edaac863a9="simon_banaan"]ik houd het graag bij 1 class en niet met extends in dit geval, dit omdat ik precies dezelfde methode's wil gebruiken voor zowel mysql als pg sql.. ik deel ze later op in 2 classes denk ik,[/quote:edaac863a9]Waarom deel je ze nu niet op in twee aparte classes? Omdat je dezelfde methoden wil gebruiken? Daarvoor heb je abstracte\interface classes (kan wel zeggen dat dit één van de peilers is van OOP). Ik begrijp dat OOP niet 1-2-3 even geleerd is, maar ik stel je die vragen om je te leren nadenken over ontwerpen in OOP, zodat je sneller OOP begrijpt. OOP begrijpen kost maanden cq jaren (op de genieën na ;)). Ik ken mensen die OOP al jaren gebruiken en toepassen, maar het nog steeds niet begrijpen ;). [quote:edaac863a9="BasHamar"]Daarnaast is het volgens mij in PHP4 nog niet mogelijk om interfaces te maken, maar zal dit wel kunnen in PHP5. Even geduld nog, ik zit ook al enige tijd met smart te wachten.[/quote:edaac863a9]Tuurlijk is het mogelijk om interfaces te maken in PHP4. Een interface is niets meer dan een abstracte class. Dat je deze in PHP5 écht kan benoemen en dat PHP voor je controleert of een class aan een interface voldoet is alleen maar een handigheidje voor programmeurs. (Wil niet zeggen dat ik dit niet verdraaid handig vindt en ik ook niet met smart zit te wachten totdat PHP5 uit beta is hostingbedrijven dit zullen gaan installeren.;)) -Rémy
  • [quote:1159f46fbd]Nee, dit is geen goede oplossing. Nogmaals wat heeft een resultset met een databaseverbinding te maken? Misschien dat een vergelijking helpt: wat heeft een opgehaalde bestand met een ftp-verbinding te maken? (Dus waarom zijn een resultset en een dbverbinding één object?) [/quote:1159f46fbd] hoe kan je dit doen met meerdere objecten? enn wat doet de & operator, ik snap die php uitelg niet echt over '&' [quote:1159f46fbd]$db =& new MySqlDatabase(DB_NAME, DB_HOST); $db->connect(DB_USERNAME, DB_PASSWORD); $rs =& $db->query('SELECT CID, naam FROM customers WHERE CID=12345'); $customer =& $rs->getRow(0); echo $rs->getRowCount(); echo $customer['serial_number']; echo $customer['naam']; [/quote:1159f46fbd] is mischien wel makkelijker, maar hoe kan je met meerdere resultsets werken?
  • [quote:2df07f2723="simon_banaan"]enn wat doet de & operator, ik snap die php uitelg niet echt over '&'[/quote:2df07f2723]Los van de normale functie als "AND" heeft het ook nog een functie in zgn references. Een zeer uitgebreid en duidelijk artikel is van Rémy zelf: [url=http://blog.ourselves.nl/archives/000005.php]References Explained part I[/url] en [url=http://blog.ourselves.nl/archives/000006.php]part II[/url]. En het moet toch even van mijn hart: @Rémy, ik weet dat interfaces niet meer zijn dan abstracte classes, maar het is juist die controle die 't 'm doet. :D - Bas
  • [quote:d971d21438="simon_banaan"]hoe kan je dit doen met meerdere objecten? is mischien wel makkelijker, maar hoe kan je met meerdere resultsets werken?[/quote:d971d21438]Als ik je ga antwoorden wordt het denk een vrij lang antwoord en ik hoor mijn (water)bed roepen :D... Ik zal kijken of ik je morgen een goed antwoord kan geven (mits het niet te druk is ;)) [quote:d971d21438="BasHamar"] ik weet dat interfaces niet meer zijn dan abstracte classes, maar het is juist die controle die 't 'm doet. :D[/quote:d971d21438]Ja en nee. [b:d971d21438]Strict[/b:d971d21438] gezien is die controle door een programeertaal niet nodig om een interface te maken, net zoals private\protected\public niet nodig zijn. Een ontwikkelaar moet dan wel gedisiplineerd zijn en geen dingen doen die niet mogen (want ze kunnen wel: de programeertaal geeft geen error). Hiervan is een heel goed voorbeeld in een recent [url=http://forum.computertotaal.nl/phpBB2/viewtopic.php?t=113281]topic[/url] te zien. Je kan echo'en vanuit de maand-functie, maar het hoort niet: je hoort een waarde te returneren. Het feit dat je een interface kan benoemen (en private\protected\public) en dat de programmeertaal dit voor jouw controleert (en bij fouten een error geeft) is puur een handigheidje om makkelijker te programmeren (en misschien slechte programmeurs te dwingen goed te programmeren :lol:). -Rémy p.s. Je zou het gedeeltelijk zou kunnen oplossen in PHP4 ;) [code:1:d971d21438]function doSomething() { die('doSomething is not implemented by a child of blabla.'); }[/code:1:d971d21438]
  • [quote:173610beb1="Remytje"]Het feit dat je een interface kan benoemen (en private\protected\public) en dat de programmeertaal dit voor jouw controleert (en bij fouten een error geeft) is puur een handigheidje om makkelijker te programmeren (en misschien slechte programmeurs te dwingen goed te programmeren :lol:).[/quote:173610beb1]Misschien. :D[quote:173610beb1="Remytje"]Je zou het gedeeltelijk zou kunnen oplossen in PHP4 [...][/quote:173610beb1]Hmmm... Interessant... - Bas
  • [quote:00d62d3b23="simon_banaan"]is mischien wel makkelijker, maar hoe kan je met meerdere resultsets werken?[/quote:00d62d3b23]Je kan het toepassen als volgt: [code:1:00d62d3b23]$db =& new MySqlDatabase(DB_NAME, DB_HOST); $db->connect(DB_USERNAME, DB_PASSWORD); $rs1 =& $db->query('SELECT CID, naam FROM customers WHERE CID=12345'); $rs2 =& $db->query('SELECT CID, naam FROM customers ORDER BY CID'); $customer =& $rs1->getRow(0) echo $customer['CID']; echo $customer['naam']; for ($i = 0 ; $i <= $rs2->getRowCount() ; $i++) { $customer =& $rs2->getRow($i); echo $customer['CID']; echo $customer['naam']; }[/code:1:00d62d3b23]Zelf zou ik dan ook nog een iterator gebruiken:[code:1:00d62d3b23]$db =& new MySqlDatabase(DB_NAME, DB_HOST); $db->connect(DB_USERNAME, DB_PASSWORD); $rs1 =& $db->query('SELECT CID, naam FROM customers WHERE CID=12345'); $rs2 =& $db->query('SELECT CID, naam FROM customers ORDER BY CID'); $customer =& $rs1->getRow(0) echo $customer['serial_number']; echo $customer['naam']; for ($it =& new QueryIterator($rs2) ; $it->isValid() ; $it->next()) { $customer =& $it->getCurrent(); echo $customer['CID']; echo $customer['naam']; }[/code:1:00d62d3b23] [quote:00d62d3b23="simon_banaan"]hoe kan je dit doen met meerdere objecten?[/quote:00d62d3b23]In bovenstaande oplossing gebruik ik drie objecten: een database(connection)Object, een resultsetObject en een iteratorObject. Op het moment dat ik [i:00d62d3b23]$db->query('SELECT CID, naam FROM customers WHERE CID=12345')[/i:00d62d3b23] doe, krijg ik een resultsetObject terug! Hoe ik dit doe? Ik heb twee classes [i:00d62d3b23]MyDatabase[/i:00d62d3b23] en [i:00d62d3b23]MyQueryResult[/i:00d62d3b23]. [i:00d62d3b23]MyDatabase[/i:00d62d3b23] heeft een methode [i:00d62d3b23]query()[/i:00d62d3b23]. Deze methode is als volgt (vereenvoudigt) gedefineerd:[code:1:00d62d3b23]function &query($sql) { return new MyQueryResult(mysql_query($sql)); }[/code:1:00d62d3b23]Dus als ik [i:00d62d3b23]$db->query('SELECT CID, naam FROM customers WHERE CID=12345')[/i:00d62d3b23] doe, dan krijg ik een object terug (van de class MyQueryResult). -Rémy

Beantwoord deze vraag

Weet jij het antwoord op deze vraag? Registreer of meld je aan met je account

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.