Thread: php-oop met database (mysqli)
-
10-09-2010, 01:20 #1Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
php-oop met database (mysqli)
Ik maak nu al een tijdje gebruik van de objectgeoriënteerde manier van werken met mysqli om mijn data af te handelen.
Nu zou ik echter een stap verder willen gaan en met classes gaan werken gezien ik totnutoe altijd vooral proceduraal gewerkt heb.
Ik heb al heel wat opzoekwerk gedaan op google, maar ik vind verbazend weinig echt nuttige zaken terug behalve misschien deze:WebmasterCity - Scripts - OOP Gastenboek
echter heb ik een paar opmerkingen over dit script, er wordt bijvoorbeeld een database adapter in de class Reactie gestoken terwijl dit volgens mij beter gescheiden gehouden wordt?
Daarnaast wordt dan daarom een reactie opgeslagen op volgende manier: $reactie->opslaan() terwijl het mij logischer lijkt dat je een object aan je dataklasse doorgeeft en deze gebruikt om je gegevens op te slaan, dus in de aard van $dataReacties = new DataReacties();
$dataReacties.insertRectie($reactie);
Ik heb daarom eens een scriptje uitgewerkt waarbij ik gebruik maak van aparte objecten, dataclasses en een mysqli connectie klasse waarop ik graag wil verderbouwen, maar ik had er graag eens jullie mening over gehad of mijn werkwijze correct is (het werkt in ieder geval
)
Code:<?php class Database{ private $connection; public function maak_verbinding($host, $gebruikersnaam, $wachtwoord, $naam){ //connectie maken $this->connection = new mysqli($host,$gebruikersnaam,$wachtwoord,$naam); if (mysqli_connect_errno()) { printf("Kan niet connecteren met MySQL Server. Errorcode: %s <br />", mysqli_connect_error()); exit; } //encoding op UTF-8 zetten $this->connection->query("SET NAMES 'utf8'"); } public function get_connection(){ return $this->connection; } public function sluit_verbinding(){ $connection->close(); } } ?>
Code:<?php class DataNieuws{ private $database; public function __construct(Database $database) { $this->database = $database; } public function nieuws_toevoegen(Nieuwsbericht $nieuwsbericht) { $query_insert_nieuws = "insert into nieuws(titel,bericht,datum,gebruiker) values(?,?,?,?)"; if ($stmt = $this->database->get_connection()->prepare($query_insert_nieuws)) { $stmt->bind_param('ssss',$nieuwsbericht->titel,$nieuwsbericht->bericht,$nieuwsbericht->datum,$nieuwsbericht->gebruikersnaam); $stmt->execute(); $stmt->store_result(); if(!($stmt->affected_rows == 1)){ echo "Er heeft zich een fout voorgedaan bij het toevoegen van het nieuwsbericht : " . $stmt->error . "<br /><br />"; }else{ echo "opgeslagen.<br /><br />"; } $stmt->close(); }else{ echo "Er heeft zich een fout voorgedaan bij het toevoegen van het product : " . $stmt->error . "<br /><br />"; } } public function get_nieuwsbericht($id){ $query = "select titel,bericht,datum,gebruiker from nieuws where nieuwsID = ?"; if ($stmt = $this->database->get_connection()->prepare($query)) { $stmt->bind_param('i',$id); $stmt->execute(); $stmt->bind_result($titel,$bericht,$datum,$gebruikersnaam); $stmt->store_result(); $stmt->fetch(); if(($stmt->num_rows) == 1){ return new Nieuwsbericht($titel,$bericht,$datum,$gebruikersnaam); }else{ echo 'Het nieuwsbericht werd niet teruggevonden.'; } $stmt->close(); }else{ echo "Er heeft zich een fout voorgedaan bij het toevoegen van het product : " . $stmt->error . "<br /><br />"; } } public function get_nieuwsberichten($aantal){ $query = "select titel,bericht,datum,gebruiker from nieuws order by datum desc LIMIT ?"; if ($stmt = $this->database->get_connection()->prepare($query)) { $stmt->bind_param('i',$aantal); $stmt->execute(); $stmt->bind_result($titel,$bericht,$datum,$gebruikersnaam); $stmt->store_result(); if(($stmt->num_rows) > 0){ while ($stmt->fetch()) { $nieuwsberichten = new Nieuwsbericht($titel,$bericht,$datum,$gebruikersnaam); } return $nieuwsberichten; } $stmt->close(); }else{ echo "Er heeft zich een fout voorgedaan bij het ophalen van de nieuwsberichten : " . $stmt->error . "<br /><br />"; } } } ?>
uitvoeren:Code:<?php class Nieuwsbericht{ public $titel; public $bericht; public $datum; public $gebruikersnaam; //constructor public function __construct($titel,$bericht,$datum,$gebruikersnaam,$datanieuws=""){ $this->titel = $titel; $this->bericht = $bericht; $this->datum = $datum; $this->gebruikersnaam = $gebruikersnaam; $this->datanieuws = $datanieuws; return; } //titel public function setTitel($titel){ $this->$titel = $titel; return; } public function getTitel(){ return $this->titel; } //bericht public function setBericht($bericht){ $this->$bericht = $bericht; return; } public function getBericht(){ return $this->bericht; } //datum public function setDatum($datum){ $this->$datum = $datum; return; } public function getDatum(){ return $this->datum; } //gebruikersnaam public function setGebruikersnaam($gebruikersnaam){ $this->$gebruikersnaam = $gebruikersnaam; return; } public function getGebruikersnaam(){ return $this->gebruikersnaam; } } ?>
Code:<?php //classes importeren require_once("Database.php"); require_once("DataNieuws.php"); require_once("Nieuwsbericht.php"); //opslaan $db = new Database(); $db->maak_verbinding('localhost', 'user', 'pass', 'dbname'); $dataNieuws = new DataNieuws($db); $nieuwsbericht = new Nieuwsbericht("test","testbericht","2010-10-01","testgebruiker"); $dataNieuws->nieuws_toevoegen($nieuwsbericht); //tonen $db = new Database(); $db->maak_verbinding('localhost', 'root', 'bartbart', 'testclasses'); $dataNieuws = new DataNieuws($db); $nieuwsbericht = $dataNieuws->get_nieuwsbericht(1); echo $nieuwsbericht->titel; ?>webdeveloper / gamerno votes
-
-
10-09-2010, 02:40 #2Member
- Registered
- 09/08/05
- Location
- Kieskring BHV
- Posts
- 1,683
- iTrader
- 5 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 1/22
Waarom zie ik in PHP altijd public datamembers terwijl het in andere talen de gewoonte is ze private te maken en met getters en setters te werken?
Verder lijkt de scheiding van de lagen mij wel inorde. Ik ben zelf wel meer geneigd om de methoden van DataNieuws bij Nieuwsbericht te plakken.
Eventueel van u database een singleton maken?
/edit: ik zie net dat jij public datamembers én getters en setters gebruikt, is toch nergens voor nodig?Last edited by sanzo; 10-09-2010 at 03:04.
no votes
-
10-09-2010, 09:53 #3Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
@eerste opmerking, idd goede vraag, in java en .NET gebruik ik idd private en getters en setters, in php kan je in ieder geval gewoon de var aanroepen ipv via de getter, maar het is mss beter om via de getter te werken, zou daar niet echt op kunnen antwoorden wat het beste is.
@ je edit, je hebt volledig gelijk, maar in mijn script gebruik ik nog beiden door elkaar, gewoonweg om de verschillende mogelijkheden uit te proberen, in productie zal ik sowieso nog gaan opsplitsen, dus ofwel met public members werken ofwel met getters en setters.
singleton kan ik eventueel doen ja.
Bedankt voor je opmerkingen alvast
webdeveloper / gamerno votes
-
10-09-2010, 10:59 #4Crew Member
- Registered
- 01/09/02
- Location
- Peutie
- Posts
- 7,664
- iTrader
- 0
- Mentioned
- 4 Post(s)
- Reputation
- 13/105
Van die database kan je inderdaad misschien best een singleton maken, of je moet ze overal aan gaan meegeven. Dan is de keuze snel gemaakt.
Getters en setters zijn in de meeste gevallen overroepen naar mijn mening. Als ze effectief iets moeten doen (validatie, andere dingen setten en dergelijke meer), dan moet je ze gebruiken, maar meestal staan ze garant voor onnodig veel overbodige code. Neem nu onderstaand (veel voorkomend) voorbeeld:
Hier ga ik bijna altijd gewoon een public variabele van maken. Zolang je maar consistent en duidelijk bent is er niets mis mee.Code:class Foo { private $_foo; public GetFoo() { return $_foo; } public SetFoo($foo) { $_foo = $foo; } }
Vandaar dat ze in .NET 3.0 ook de automatic properties geïntroduceerd hebben. Kan je nog iets van scheiding doen zonder effectief zelf een hoop extra code te gaan schrijven.
Just my 2 cents.Vanaf nu gaan we verder op BeyondGaming!
In deze thread wordt uitgelegd hoe je jouw account kan migreren.no votes
-
10-09-2010, 11:52 #5Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
no votes
-
10-09-2010, 23:08 #6Member
- Registered
- 17/07/02
- Location
- Sol System
- Posts
- 10,064
- iTrader
- 1 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 27/78
Euh... Gewoon je private datamembers definiëren, en dan via code completion de getters en setters laten creëren, dat is nu eens geen werk. Gebruik dus eerst maar een deftige IDE (NetBeans met PHP support doet het wel goed, en vind ik ook iets sneller werken dan Eclipse PDT).
Wat mij persoonlijk overigens wel stoort is dat je foutmeldingen zit te echo-en vanuit je model, en ook dat je geen coding convention gebruikt in je code (de ene keer is 't camel case, de andere keer lowercase met underscores - PHP is op zich al inconsistent genoeg
). Eigenlijk zou je misschien ineens de stap naar ORM moeten zetten. Uit de aanpak van vb. Propel kan je enorm veel leren, dat lijkt mij als tijdsbesteding ook nuttiger dan zelf het wiel opnieuw te proberen uitvinden. En wat de coding conventions betreft, persoonlijk vind ik die van het Zend Framework wel aangenaam werken (http://framework.zend.com/manual/en/...-standard.html).
Last edited by dJeez; 10-09-2010 at 23:21.
PSN: dJeezBE - Delicious bookmarks
Disclaimer: I am currently suffering from severe CSD (Compulsive Sarcasm Disorder). - L'onion fait la farce - Facile largire de alienoPastafarian by choiceno votes
-
12-09-2010, 14:10 #7Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
idd, voor java en dergelijke gebruik ik eclipse, voor php gewoon JEdit, mss handiger om idd een IDE te gebruiken

camelcase en throwen van exceptions doe ik echter wel bij java en .NET dus waarom ik het hier niet heb gedaan is puur uit snel een voorbeeld ineen te willen stampen, maar ik ga er inderdaad aandacht aan moeten besteden om het overzichtelijk te houden en niet altijd te snel willen zijn
Propel en zend heb ik al van gehoord en ga deze zeker eens bestuderen.
Bedankt voor de tips!Last edited by sarnath; 12-09-2010 at 14:17.
webdeveloper / gamerno votes
-
13-09-2010, 10:48 #8Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
Mijn huidig script is zo goed als af en heb van de database een singleton gemaakt. Ik snap wel niet goed wat je bedoelt met dat ik het nu overal moet gaan meegeven.
Is dat niet nog steeds zo met een singleton en is een singleton niet gewoon bedoeld zodat ik slechts één instantie van het database object hoef te maken en zo meer performantie heb?webdeveloper / gamerno votes
-
13-09-2010, 11:19 #9Crew Member
- Registered
- 01/09/02
- Location
- Peutie
- Posts
- 7,664
- iTrader
- 0
- Mentioned
- 4 Post(s)
- Reputation
- 13/105
Vanaf nu gaan we verder op BeyondGaming!
In deze thread wordt uitgelegd hoe je jouw account kan migreren.no votes
-
13-09-2010, 13:06 #10Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
Sorry, maar ik snap nog steeds niet wat je wil zeggen, stel dat ik mijn singletonclass gebruik:
Dan roep ik deze zo op:Code:<?php class Database { private $connection; private static $m_pInstance; private function __construct() { echo "Constructor called<br />\n"; } public function makeConnection($host, $gebruikersnaam, $wachtwoord, $naam){ //connectie maken $this->connection = new mysqli($host,$gebruikersnaam,$wachtwoord,$naam); if (mysqli_connect_errno()) { printf("Kan niet connecteren met MySQL Server. Errorcode: %s <br />", mysqli_connect_error()); exit; } //encoding op UTF-8 zetten $this->connection->query("SET NAMES 'utf8'"); } public function getConnection(){ return $this->connection; } public function closeConnection(){ $this->connection->close(); } public static function getInstance() { if (!self::$m_pInstance) { self::$m_pInstance = new Database(); } return self::$m_pInstance; } } ?>
in plaats van:Code:$db = Database::getInstance(); $db->makeConnection('localhost', 'user', 'pass', 'dbname'); $dataNieuws = new DataNieuws($db); ...
Dus structureel blijft het hetzelfde, ik maak het object enkel anders aan, maar geef het evengoed door aan mijn data adapters.Code:$db = new Database(); $db->maakVerbinding('localhost', 'user', 'pass', 'dbname'); $dataNieuws = new DataNieuws($db);
Het verschil is nu dat er slechts één instance van bestaat.
of bedoel je dat ik dan echt zo moet oproepen:
Database::getInstance()->getConnection()->prepare($query) in bijvoorbeeld mijn DataNieuws klasse en dus aan de constructor niks meer meegeef?Last edited by sarnath; 13-09-2010 at 13:38.
webdeveloper / gamerno votes
-
13-09-2010, 14:20 #11Crew Member
- Registered
- 01/09/02
- Location
- Peutie
- Posts
- 7,664
- iTrader
- 0
- Mentioned
- 4 Post(s)
- Reputation
- 13/105
Inderdaad. Als je een singleton gebruikt hoef je die database parameter niet mee te geven aan je DataNieuws klasse. Je kan die rechtstreeks aanspreken.
Vanaf nu gaan we verder op BeyondGaming!
In deze thread wordt uitgelegd hoe je jouw account kan migreren.no votes
-
13-09-2010, 14:24 #12Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
Ok bedankt, wist niet dat je een singleton direct kon aanspreken, want ik lees nu op een aantal fora dat men daarom het gebruik van je database als singleton wil afraden omdat het niet veilig is, maar als ik telkens de connectie wel op en sluit lijkt me dat toch niet direct onveilig?
Der zijn gewoon een aantal voorstanders en een aantal tegenstanders wat het natuurlijk wat verwarrender maakt of ik het nu al dan niet zou gebruiken
webdeveloper / gamerno votes
-
14-09-2010, 23:33 #13Member
- Registered
- 17/07/02
- Location
- Sol System
- Posts
- 10,064
- iTrader
- 1 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 27/78
Tjah, er zijn er enkelen die het gebruik van singletons zien als het teken des duivels en dat dan ook wensen te verbannen. Dat zijn dan doorgaans aanhangers van dependency injection. Maar om er wat dieper op in te gaan : unit testing bijvoorbeeld is bij het gebruiken van singletons nogal lastig (op z'n zachtst uitgedrukt), dat gaat inderdaad wel een pak makkelijker met dependency injection, aangezien dat je dan ook makkelijk een mock object kan gaan doorgeven.
Voor meer info ivm unit testing en singletons/dependency injection, zie Testing Code That Uses Singletons.Last edited by dJeez; 14-09-2010 at 23:45.
PSN: dJeezBE - Delicious bookmarks
Disclaimer: I am currently suffering from severe CSD (Compulsive Sarcasm Disorder). - L'onion fait la farce - Facile largire de alienoPastafarian by choiceno votes
-
15-09-2010, 15:52 #14Member
- Registered
- 07/11/03
- Location
- Bree
- Posts
- 6,239
- iTrader
- 158 (99%)
- Mentioned
- 0 Post(s)
- Reputation
- 0/0
Interessante artikels, ga ze volledig doornemen, bedankt
webdeveloper / gamerno votes
-
16-09-2010, 20:37 #15Member
- Registered
- 17/07/02
- Location
- Sol System
- Posts
- 10,064
- iTrader
- 1 (100%)
- Mentioned
- 0 Post(s)
- Reputation
- 27/78
Bekijk ook The Clean Code Talks - "Global State and Singletons" eens als je er de tijd voor kan vrijmaken.
PSN: dJeezBE - Delicious bookmarks
Disclaimer: I am currently suffering from severe CSD (Compulsive Sarcasm Disorder). - L'onion fait la farce - Facile largire de alienoPastafarian by choiceno votes

