Forum › PHP / SQL › Topic

Een nieuwe topic in het forum PHP / SQL plaatsen Reageren op dit topic Forum:

[PHP/SQL] OOP mysqli connectie meenemen.

Beste WMcityérs

Al lange tijd ben ik aan het knoeien met het doorlussen van de opgezette connectie met mysql naar een andere class.

Stel als voorbeeld.
In klasse system heb ik een db connectie geopend. Maar die wil ik in klasse nieuws hergebruiken. hoe kan ik dit doen?

Kort omschreven maar wel duidelijk neem ik aan?

ZiraX.
Stuur een prive bericht
Hoi ZiraX,

Wat je zou kunnen overwegen is een singleton class waarin je een database connectie opbouwt en returnt. Indien er al een connectie is, geeft hij je gewoon de al bestaande verbinding terug. De class kun je dan in al je andere classes hergebruiken.

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Database {

  private static 
$instance null;

  private function 
__construct() {
    
$this->instance mysqli_connect(); // Vul zelf maar in
    // Wellicht ook nog database selecteren? Ik ben niet echt bekend met mysqli.
  
}

  public static function 
getInstance() {
    if (
is_null($this->instance))
      
$this->instance = new Database();
    
    return 
$this->instance;
  }

  public function 
exec($query) {
    
// Run query..
  
}
}



(Niet getest, dus er zou een foutje in kunnen zitten).

Het idee is het volgende: de instantie van Database wordt bijgehouden in de klasse zelf. Indien er nog geen instantie bestaat, maakt hij deze aan en returnt hij 'm. Indien hij al een instantie heeft wordt hij simpelweg gereturned. Je werkt dus de gehele request met dezelfde connectie. Als je hier meer over wil lezen verwijs ik je graag naar Wikipedia:
http://nl.wikipedia.org/wiki/Singleton_(informatica)

Naast mysqli kun je ook eens een kijkje nemen naar PDO, als je dan toch met OOP bezig bent

Het bovenstaande voorbeeld pas je zo toe trouwens:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
$database Database::getInstance();
$database->exec('SELECT 1 FROM tabel');




Succes!
Erik
Stuur een prive bericht
In principe moet ik dus al mijn bestaande klasses met de database klasse extenden?

Ben sinds kort pas bezig trouwens met OOP programmeren, echter gebruik ik elke keer een nieuwe mysqli connectie per klas, wat toch een hevige verzwaring van het script betekend. Omdat je elke keer een nieuwe connectie oproept.
Stuur een prive bericht
Even een kleine toevoeging. Sorry voor de BUMP, maar vond het wat makkelijker om een overzicht te hebben.

Op het moment heb ik het als volgt:

system.class.php
Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
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
<?php

/** 
 * @author Kevin van 't IJssel
 * @description Webfanaat-SG v2.0
 * @copyright 04-2012 eQaz
 */
 
 
class system {
    
    public 
$siteTitle;
    public 
$siteAuthor 'Webfanaat-SG';
    public 
$siteRevised '13-04-2012 2:09';
    
    public 
$headerPath '/home/user/domains/webfanaat-sg.nl/public_html/dev/template/default/html/header.inc.php';
    public 
$diversPath '/home/user/domains/webfanaat-sg.nl/public_html/dev/template/default/html/divers.inc.php';
    public 
$footerPath '/home/user/domains/webfanaat-sg.nl/public_html/dev/template/default/html/footer.inc.php';
    
    public 
$imagesPath '/dev/template/default/assets/images/';
    public 
$cssPath '/dev/template/default/assets/css/';
    public 
$jsPath '/dev/template/default/assets/js/';
    
    public static 
$db;
    
    public static function 
loaddb(){
        return 
self::$db = new mysqli("localhost""user""""database_sg");
    }
    
    public function 
setTitle($titel){
        
$this->siteTitle '';
        return 
$this->siteTitle $titel;
    }
    
    public function 
html($input){
        return 
stripslashes(htmlentities(trim($input), ENT_QUOTES));
    }
 
 }





news.class.php
Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
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
<?php

/** 
 * @author Kevin van 't IJssel
 * @description Webfanaat-SG v2.0
 * @copyright 04-2012 eQaz
 */
 
 
class news extends system {
    
    public 
$newsFront = array();
    
    public function 
__construct(){ 
    }
    
    public function 
getNewsFront($items){
            
$select_nieuws system::loaddb()->query("SELECT * from cms_nieuws Order by datum DESC LIMIT 0,".$items."");
            
            While(
$n $select_nieuws->fetch_assoc())
            {
                
$this->newsFront[$n['id']] = $n;
            }
    }
    
    
 }




Op deze manier werkt het wel, maar ik heb het gevoel dat het niet de juiste manier is, kan iemand me meer toelichten op bovenstaand?
Stuur een prive bericht
Zijn er hier weinig mensen met kennis van OOP, of die hun tips willen delen etc. ?

Zou wel fijn zijn om hierom wat activiteit te creeëren.. Zo lok je namelijk ook mensen
Stuur een prive bericht
ZiraX,

Als ik jou was, zou ik even goed kijken naar welke classes je gaat maken. Is 'news' namelijk een 'system' ? Want dat suggereer je nu namelijk. Ik weet niet hoe of wat je applicatie wordt, maar zo iets zou mij zelf logischer lijken:
Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
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
<?php
/*
* Een Pagina class, alle andere verschillende typen pagina's kunnen 
* hier van extenden en erven dan de methoden en eigenschappen.
*/
class Page {
    
// Alles wat je bij een pagina wil specificeren.
    
private $titel;

    public function 
__construct($titel) {
        
$this->titel $titel;
    }

    public function 
render($input) {
        
// Render pagina of zo?
    
}
}

class 
News extends Page {
    
// Deze class erft nu alles van Page, hier kun je dan weer code
    // toevoegen die specifiek is aan News.
}

/*
* Database class voor de database connectie.
*/
class Database {
    private static 
$instance null;

    private function 
__construct() {
        
// return nieuwe db connectie
    
}

    public static function 
getInstance() {
        if (
is_null(self::$instance))
            
self::$instance = new Database();

        return 
self::$instance;
    }

    public function 
execute($query) {
        
// Voer query uit met huidige verbinding en return het resultaat.
    
}
}



Again, niet getest ;-) Maar wat ik meer probeer te zeggen is, probeer je classes te abstraheren. Een stukje wat ik ooit eens in een boek gelezen heb van Bob C. Martin (Clean Code) is dat een class maar 1 reden moet hebben om te veranderen. Dus, als een class meerdere doelen heeft dan doet het te veel. Je system class doet nu zoiezo al meerdere dingen, namelijk output geven (of wat ik me er ook bij moet voorstellen) en de database connectie beheren.

Probeer dus even goed na te denken over welke classes je maakt. Vaak wordt er bij dit proces gebruik gemaakt van Noun Phrase Identification. Daarbij leg je het systeem in verhaalvorm uit en ga je alle zelfstandig naamwoorden onderstrepen, markeren of wat je ook fijn vindt. Als je dit gedaan hebt ga je kijken wat goede kandidaten voor classes zijn. Laat ik bijvoorbeeld een voorbeeld als dit nemen:
Quote:
Er zijn drie typen karakters, Goblin, Elf en Knight. Elk karakter heeft levenspunten en mana. Ook hebben ze allemaal een speciale aanval: een Goblin heeft X, een Elf Y en een Knight Z.

Daar haal je als zelfstandig naamwoorden Karakters, Goblin, Elf, Knight en Aanval uit. Zorg wel dat je alle zelfstandig naamwoorden enkelvoud maakt, want een instantie is een representatie van 1 'iets'.
In dit geval lijken ze me allemaal prima kandidaten voor classes. HP en Mana lijken prima kandidaten om variabelen in Karakter te zijn, omdat het iets is wat alle classes hebben. Als Goblin, Elf en Knight een subtype zijn van Karakter is dit precies wat je wil. Daarnaast hadden ze alle 3 nog een 'speciale aanval', dat zouden typische methoden zijn die per subclass vastgelegd worden. Als je dit proces een paar keer gedaan hebt begint het wel te dagen en kom je op nagenoeg hetzelfde uit als je gewoon gaat denken ipv alles in verhaalvorm uitschrijven en dan markeren.

Goed, tot slot nog even over de scope van variabelen, ik zie dat je alles public maakt. Geen probleem hoor, want het zal vast wel werken; maar toch wil ik even uitleggen wat hier het idee achter is.

Public variabelen / methoden zijn overal te benaderen. Dus ook vanuit andere classes. Private variabelen / methoden zijn enkel vanuit de class zelf te benaderen. Protected vanuit de class zelf en alle subclasses.

Goed, ik heb genoeg getypt; hopelijk heb je er iets aan. OOP is niet gemakkelijk en je moet er wel echt je draai in vinden. Ik werk er nu enige tijd mee in onder andere PHP Java en Ruby en leer nog dagelijks bij dus neem de tijd ;-)

Succes!
Erik

p.s. mocht je een of ander online systeem willen maken, heb je overwogen om een bestaand framework te gebruiken? Dan heb je namelijk gelijk een goede basis.
Stuur een prive bericht