Versio

[OOP] Forum, categorieën class

Overzicht Reageren

Milo S

Milo S

26/04/2011 15:11:30
Quote Anchor link
Beste,

Ik begin net in OOP, maar heb wel al aardig wat PHP ervaring. Nu wil ik alleen OOP gaan schrijven. Ik ben begonnen met een class genaamd categorie, nu vroeg ik me af of dit wel oke is.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class forumCategorie {
    
    public $id;    
    public $parent_id;
    
    
    function
__construct( $host, $user, $pass, $datb ) {
        /*
        MySQL verbinding maken
        */

    }
    
    # Categorie ophalen
    function getCategorie() {
        
    }

    
    # Sub-categorie ophalen
    function getSubcategorie() {
    }

    
    # Laatste topic ophalen
    function getLastTopic() {
    }

    
    # Aantal topic ophalen
    function countTopic() {
    }

    
    # Posts ophalen
    function counPost() {
    }
}

?>


Ik hoor graag, tips, opmerkingen en andere vormen van opbouwende kritiek...
Gewijzigd op 26/04/2011 15:17:00 door Milo S
 
PHP hulp

PHP hulp

25/05/2012 12:52:07
Gesponsorde koppelingen:
 
Arjan -

Arjan -

26/04/2011 15:37:49
Quote Anchor link
Het lijkt mij niet handig om je verbinding naar de database op te zetten in de class "forumcategorie". Je kan hier beter een aparte class voor gebruiken (bijvoorbeeld PDO) en deze resource meegeven aan je constructor van de betreffende class.

Dus bijvoorbeeld (simplistisch):

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
protected $_db;

public function __construct(PDO $db) {

$this->_db = $db;

}

Ik weet niet hoe je de categorieën in de database hebt opgezet, maar is het niet handiger om alle categorieën in één keer op te halen? Dus bijvoorbeeld werken met parent_id in de database en hiervoor alleen een functie "getCategorie" gebruiken? Hiermee kan je ook direct het laatste bericht ophalen (bijvoorbeeld via een subquery). Overigens haal je nu Engelse en Nederlandse benamingen door elkaar. Is niet erg, maar misschien op termijn niet handig.

En wat wil je met "public $id" en "public $parent_id" precies bereiken?
Gewijzigd op 26/04/2011 15:42:11 door Arjan -
 
Milo S

Milo S

26/04/2011 16:15:10
Quote Anchor link
Beste Arjan,

Bedankt voor de snelle reactie. Ik heb eens gekeken, en rond gezocht op internet, en bedacht me dat ik niet eens een speciale class zou aanmaken voor me database. Ik heb er tenslotte maar 1, en maak 1 keer connectie en hou het voor gezien.

Ik heb zoals jij daar aangeeft me categorieen. Dus met een parent_id. Nu dacht ik dat het zo meteen de bedoeling was met OOP dat je dat allemaal spreid, het leek mij namelijk een op zich staand iets.

Ik ben tot nu toe hier:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class forumCategorie
{
    protected $db;
    
    # Constructor, word dus automatisch uitgevoerd.
    function __construct( $db )
    {

        $db = new PDO( 'mysql:host='.$db['host'].'; dbname='.$db['dbname'], $db['user'], $db['pass'] );
    }

    
    # Categorie ophalen
    function getCategorie( $id )
    {        
    }

    
    # Laatste topic ophalen
    function getLastTopic( $id )
    {
    }

    
    # Aantal topic ophalen
    function countTopic( $id )
    {
    }

    
    # Posts ophalen
    function countPost( $id, $top_id )
    {
    }
}

?>


Ik dacht dat je in je class de variabelen mee moest geven die je weer in je functies moet gebruiken, dit blijkt dus niet.
 
Arjan -

Arjan -

26/04/2011 16:24:15
Quote Anchor link
Quote:
Bedankt voor de snelle reactie. Ik heb eens gekeken, en rond gezocht op internet, en bedacht me dat ik niet eens een speciale class zou aanmaken voor me database. Ik heb er tenslotte maar 1, en maak 1 keer connectie en hou het voor gezien.


PDO is al een class die je kan gebruiken in je overige classes. PDO heeft super veel voordelen (prepared statements, etc.), dus ik raad je aan om dit te gebruiken.

Quote:
Ik dacht dat je in je class de variabelen mee moest geven die je weer in je functies moet gebruiken...


Dit is ook de juiste manier, maar ik doelde meer op de functie van die twee variabelen (maar die gebruik je dus voor het opvragen van de subcategorieën?).

Maar wanneer jij alle categorieën wilt ophalen, dan kan je net zo goed gelijk de subcategorieën ophalen. Hierdoor hoef je niet voor elke categorie een aparte query te maken voor je subcategorieën. Dit scheelt veel meer tijd en resources dan dat je alles wilt scheiden omdat het overzichtelijker is.

En in jouw revisie maak je nog steeds een database connectie aan in je constructor.

Je kan het beter zo doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

class ForumCategorie {

    protected $_db;

    public function __construct(PDO $db) {

        $this->_db = $db;

    }

}


$db = // pdo connectie / Dit kan je in een apart sql bestand zetten die je op elke pagina include

$ForumCategorie = new ForumCategorie($db);

$AndereClass = new AndereClass($db); // Niet gedefinieerd maar dienend als voorbeeld

?>


Een andere mogelijkheid is het gebruik maken van het Singleton patroon (http://nl.wikipedia.org/wiki/Singleton_(informatica)).
Gewijzigd op 26/04/2011 16:34:09 door Arjan -
 
Milo S

Milo S

26/04/2011 17:04:20
Quote Anchor link
Aaah nu snap ik wat je bedoel met die PDO verbinding. Ik maak dan een config bestandje aan met bijvoorbeeld:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$db
= array (
            'host' => '',
            'datb' => '',
            'user' => '',
            'pass' => ''
            );

try
{
    $db = new PDO('mysql:host='.$db['host'].';dbname='.$db['datb'], $db['user'], $db['pass']);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}

catch(PDOException $e)
{

    echo 'Er is een fout opgetreden bij het maken van connectie met de database.';
}

?>


en mijn forum_cat.class.php heeft dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class ForumCategorie
{
    public $cat_id;
    public $top_id;
    protected $_db;
    
    # Constructor, word dus automatisch uitgevoerd.
    public function __construct(PDO $db)
    {

        $this->_db = $db;
    }

    
    # Categorie ophalen
    function getCategorie( )
    {        
    }

    
    # Laatste topic ophalen
    function getLastTopic( $cat_id )
    {
    }

    
    # Aantal topic ophalen
    function countTopic( $cat_id )
    {
    }

    
    # Posts ophalen
    function countPost( $cat_id, $top_id )
    {
    }
}

?>
Gewijzigd op 26/04/2011 17:10:06 door Milo S
 
Arjan -

Arjan -

26/04/2011 17:08:53
Quote Anchor link
Wat betreft de database connectie is dat inderdaad de manier die ik bedoel (er zijn vele manieren dus een bepaalde manier is niet per definitie de beste manier).

En dan kan je dus in alle functies binnen je class een query opzetten middels bijvoorbeeld: $sql = $this->_db->prepare("");
Gewijzigd op 26/04/2011 17:10:29 door Arjan -
 
Milo S

Milo S

26/04/2011 17:13:15
Quote Anchor link
Dan ga ik vanuit dit opzetje verder werken, en een index pagina van een forum bouwen. Mag je nu eigenlijk wel gewoon queries uitvoeren enzo in je functies, uiteraard PDO...
 
Arjan -

Arjan -

26/04/2011 17:22:43
Quote Anchor link
Van mij wel :) (anders heb je ook niets aan de database resource binnen je class). Alle database data opvragen buiten je class lijkt mij wat lastig. Sommigen beweren dat de schaalbaarheid wordt verkleind door binnen je class queries uit te voeren, maar wanneer je de database benamingen universeel en database schaalbaar houdt dan is er mijn inziens niets aan de hand.

Extra data / velden ophalen vanuit de database (zoals de subcategorieën binnen de hoofdcategorieën) die je later niet nodig hebt is geen wereldramp, aangezien je hierdoor veel minder (onnodige) functies hoeft te gebruiken en wellicht ook (afhankelijk van het systeem) minder afzonderlijke queries nodig hebt.

Trouwens, de countpost functie kan je ook wel integreren in de getCategorie functie. Stel je hebt 20 categorieën, dan zal je dus afzonderlijk 20 keer de functie countpost en bijbehorende query moeten uitvoeren om het aantal posts te verkrijgen.

Voor de categorieën lijkt mij het mooist om een multidimensionale array te retourneren, waarin de categorieën, subcategorieën en de bijbehorende gegevens (aantal posts) zijn opgenomen. Zodoende kan je eenvoudig loopen door de gegevens.
Gewijzigd op 26/04/2011 17:25:59 door Arjan -
 
Niels Kieviet
Beheerder

Niels Kieviet

26/04/2011 17:40:48
Quote Anchor link
Topic's en categorieën.. Moeten dat geen aparte klasses zijn? :)
Gewijzigd op 26/04/2011 17:41:07 door Niels Kieviet
 
Arjan -

Arjan -

26/04/2011 18:03:59
Quote Anchor link
Ja.
Gewijzigd op 26/04/2011 21:20:10 door Arjan -
 
Milo S

Milo S

26/04/2011 18:15:11
Quote Anchor link
@ Niels;
Zoals je ziet haal ik niet een heel topic op, maar alleen de laatste. Topic's zelf worden inderdaad een andere klasse... Niet goed?
 
Arjan -

Arjan -

26/04/2011 20:17:54
Quote Anchor link
Offtopic: Ik dacht dat jij (Milo) vroeg of een topic in een aparte class moet :). Jullie avatars lijken op het eerste oog zo op elkaar.

Ontopic: De laatste topic opvragen behoort tot de categorieën, dus dat kan best in de ForumCategorie class.
Gewijzigd op 26/04/2011 20:18:50 door Arjan -
 
Jaron T

Jaron T

26/04/2011 21:11:49
Quote Anchor link
Arjan - op 26/04/2011 18:03:59:
Ja, eventueel kan je de topic class extenden naar de categorie class (class ForumTopic extends ForumCategorie), aangezien een topic altijd in een categorie valt.


Nee, niet extenden.. welke eigenschappen heeft een topic die een categorie ook heeft?

wanneer wel?

Class User;
Class Supplier Extends User;
class Manager Extends User;
// etc
 
Merijn Venema

Merijn Venema

26/04/2011 21:19:17
Quote Anchor link
De categorie? Maar je hebt wel gelijk hoor, harr.
Gewijzigd op 26/04/2011 21:23:17 door Merijn Venema
 
Milo S

Milo S

26/04/2011 22:05:01
Quote Anchor link
Ik heb dan nu alle queries gemaakt, en zal morgen kijken hoe dat met PDO allemaal werkt. Bedankt voor de hulp, ik zal deze dagen nog wel meer om hulp vragen. Het tis nu nog redelijk hocus spocus.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class ForumCategorie
{
    public $id;
    public $top_id;
    protected $_db;
    
    # Constructor, word dus automatisch uitgevoerd.
    public function __construct( PDO $db )
    {

        $this->_db = $db;
    }

    
    # Categorie ophalen
    function getCategorie( )
    {

        $sql =
        "
        SELECT
            cat.title    AS cat,
                
            subCat.id    AS subCatID,
            subCat.title AS subCat,
            subCat.description
        FROM
            forum AS cat
        INNER JOIN
            forum AS subCat
        ON
            cat.id = subCat.parent_id
        GROUP BY
            subCat.id
        ORDER BY
            cat.id,
            subCat.title
        "
;    
    
    }

    
    # Laatste topic ophalen
    function getLastTopic( $id )
    {

        # Query
        $sql =
        "
        SELECT
            MAX( fu.username )                                   AS lastUser,
            COUNT(fp.id)                                         AS posts,
            DATE_FORMAT( MAX( fp.dateTime ), '%d %M %Y, %H:%i' ) AS lastPostDate
        FROM
            forum_post   AS fp
        LEFT JOIN
            user         AS fu
        ON
            fp.user_id = fu.id
        WHERE
            fp.cat_id = '"
.$id."'
        "
;
    }

    
    # Posts ophalen
    function countPost( $id, $top_id )
    {

        $sql =
        "
        SELECT
            ft.id,
            COUNT(ft.id) AS topics
        FROM
            forum_topic  AS ft
        WHERE
            ft.cat_id = '"
.$id."'
        "
;
    }
}

?>


Uiteraard nog mysql_real_escape_string, maar weet niet hoe dat bij PDO zit, zijn daar andere functies voor enzovoorts...
 
Arjan -

Arjan -

26/04/2011 22:15:04
Quote Anchor link
Met PDO gebruik je doorgaans prepared statements, kortweg komt het er op neer dat je het volgende doet:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

$veldwaarde
= 'een waarde';

$sql = $db->prepare("

SELECT id FROM tabel WHERE veld = :veldwaarde

"
);

$sql->bindParam(':veldwaarde', $veldwaarde);

if($sql->execute()) {

$data = $sql->fetchAll(PDO::FETCH_ASSOC);

}


?>


Dus je bind een variabele aan een constante (beginnend met een dubbele punt) in je query. Hierdoor hoef je mysql_real_escape_string niet meer te gebruiken, aangezien de prepared statements (bindParam en bindValue) dit al voor je doen. Zo stop je altijd veilig de data in je database!

Hiermee kan je ook dit soort constructies gebruiken (simplistisch weergegeven):

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

$sql
= $db->prepare("

INSERT INTO tabel (veldnaam) VALUES (:veldwaarde)

"
);

$sql->bindParam(':veldwaarde', $veldwaarde, PDO::PARAM_INT);

for($i = 0; $i<10; $++) {

$veldwaarde = $i;

$sql->execute();

}


?>


Hierboven zal dus 0 t/m 9 in verschillende records worden toegevoegd in de database.

De bindParam zorgt ervoor dat een referentie wordt aangemaakt, waarbij de waarde veranderbaar is voor, in dit geval, de variabele $veldwaarde. Dus je kan de waarde van $veldwaarde elke keer veranderen, waarna je execute() uitvoert. Dit kan handig zijn als je bepaalde verschillende bewerkingen op alle records moet uitvoeren. Of, zoals in dit geval, meerdere records wil toevoegen met verschillende waarden.

Dit is de beste (Nederlandse) tutorial over PDO: http://www.phptuts.nl/view/27/
Gewijzigd op 26/04/2011 22:27:04 door Arjan -
 
Niels Kieviet
Beheerder

Niels Kieviet

27/04/2011 21:16:44
Quote Anchor link
Daarnaast public variabeles zomin mogelijk gebruiken.. (Alternatief: Protected, private). Daarnaast hebben zijn functies nu altijd public... Benoemd ze dus even apart altijd ;) Dat is voor een andere programmeur ook makkelijker lezen..

Je zou ook eens kunnen kijken naar een ORM. Overigens SQL injection is eventueel mogelijk nu.. Maar ik weet dat je daar (normaliter) rekening mee houdt..

Heb je al nagedacht over user login / registratie ? Waar ga je de gebruiker(s) in opslaan? Ook database of iets anders? (Ldap bijvoorbeeld ;p)

Succes
 



Overzicht Reageren

Get Adobe Flash player