OOP goed of fout

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ki ma

ki ma

29/05/2011 00:41:10
Quote Anchor link
Ik ben begonnen met het uitvogelen van OOP programmeren. Hierbij mijn voorbeeld;

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
<?
require ("./inc/connect.php");
class kamer {
    public function get_all($kamer_id) {
        $sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $kamer_id . "'";
        $q_checkkamer = mysql_query($sql_checkkamer);
        while ($row = mysql_fetch_object($q_checkkamer)) {
            $this->straat  = $row->straat ;
            $this->straat_num = $row->straat_num ;
            $this->onderhoud = $row->onderhoud ;
            $this->postcode = $row->postcode ;
            // enz..
        }
    }
}


$kamerid = 1 ;
$kamer = new kamer() ;
$kamer->get_all ($kamerid);
echo $kamer->straat.'<br>' ;
echo $kamer->straat_num .'<br>' ;
echo $kamer->onderhoud .'<br>' ;
echo $kamer->postcode ;
?>


Het werkt prima maar is dit ook zoals het bedoeld is? Zou je de variabelen ook kunnen zetten door middel van een foreach statement met alle kolommen.
bijv:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
foreach $colom {
 $this->colom_name = $row->colom_name;
}

?>


Ik hoor het graag of ik in de goede richting zit te borduren :)

Topic verplaatst naar het juiste board.[/modedit]
Gewijzigd op 29/05/2011 17:14:20 door Joren de Wit
 
PHP hulp

PHP hulp

23/04/2024 08:21:05
 
Erik van de Locht

Erik van de Locht

29/05/2011 11:40:57
Quote Anchor link
Hoi Ki Ma,

Met $this-> stel je de instantievariabelen in. Die heb je nu nog niet aangemaakt. Deze kun je vlak na het openen van de klasse neer zetten. Hierbij heb je ook 3 mogelijkheden voor de scope van de variabelen: private, protected en public.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
class Kamer {
  private $straat;
  private $straat_num;
  // ...
?>


Let wel op dat als je de variabelen private maakt, dat ze enkel binnen de klasse zelf bereikbaar zijn! Dus dan kun je ze ook niet bereiken met:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo $kamer->straat; ?>


Daarintegen worden er vaak getters en setters gemaakt. Iets wat mijn persoonlijke voorkeur ook is, maar daar kun je over twisten natuurlijk.
Dan krijg je dus:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
public function getStraat() {
  return $this->straat;
}
?>


Nu denk je misschien: wat omslachtig. Lijkt het misschien ook, maar alle velden in je klasse public maken is een echte bad-practice! Je loopt vanzelf een keer tegen problemen aan. De getStraat() methode die ik hier boven geplaatst heb is daarintegen WEL public, want die moet je in andere klassen kunnen aanroepen om de naam van de straat (van die instantie) te verkrijgen.

Zelfde krijg je dan met een setter method:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
public function setStraat($straat = null) {
  $this->straat = $straat;
}
?>



In je code maak je een while-lus voor de resultaten van je query. Hiermee suggereer je dat de query meerdere resultaten zal geven. Als er meerdere resultaten zijn, overschrijft hij de oude waarden gewoon.
Ik neem aan dat de ID de primary key in je tabel is en deze kan dus maar 1 keer voor komen. Je zal dan ook altijd maar maximaal 1 record terug krijgen. Een while lus is dan overbodig.
 
Wouter J

Wouter J

29/05/2011 12:29:14
Quote Anchor link
Je kan in OOP beter werken met PDO dan met mysql_* functies. Verder is het inderdaad belangrijk wat erik hierboven zegt, je moet in OOP gebruiken maken van methodes om te setten en getten.
Want een object (class) heeft eigenschappen (properties) en door middel van methods kun je deze veranderen.
I.p.v. setVariabele en getVariabele kun je ook de magic methods __set en __get gebruiken.

Daarnaast is dit volgens mij niet heel erg goed OOP, maar zo'n OOP deskundige ben ik niet. Want een straat is geen eigenschap van een huis, maar een huis wel van een straat. Je zou dus ook een object (class) straat moeten maken waarvan je het huis op kan halen.
 
Ki ma

ki ma

29/05/2011 14:58:41
Quote Anchor link
Bedankt voor de reacties! Ik snap het nu alweer een stuk beter.

Maar nu heb ik het dus anders aangepakt met de __get variabel in de get.
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
<?
class kamer {
    var
$kamer_id  = '1' ;
// of bijv: var $kamer_id  = $kamer_id  ; maar dit mag niet werken...
    
   function __get($name) {
        $sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $this->kamer_id . "'";
        $q_checkkamer = mysql_query($sql_checkkamer);
        $row = mysql_fetch_object($q_checkkamer);
        if (isset($row->$name)) {
        return $row->$name;
        }
    }
 }


$kamerid = 3;
$kamer = new kamer();
echo $kamer->straat . '<br>';
?>


Alleen hoe krijg is de $kamerid in de class? Ik heb het ook met call__ geprobeerd omdat je er dan 2 variabelen in kunt zetten, maar dit zijn alleen variabelen die in de class gemaakt zijn. Maar ik heb een 'externe' variabel nodig.

Alvast bedankt

Kima

Toevoeging op 29/05/2011 15:38:19:

Ki ma op 29/05/2011 14:58:41:
Bedankt voor de reacties! Ik snap het nu alweer een stuk beter.

Maar nu heb ik het dus anders aangepakt met de __get variabel in de get.
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
<?
class kamer {
    var
$kamer_id  = '1' ;
// of bijv: var $kamer_id  = $kamer_id  ; maar dit mag niet werken...
    
   function __get($name) {
        $sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $this->kamer_id . "'";
        $q_checkkamer = mysql_query($sql_checkkamer);
        $row = mysql_fetch_object($q_checkkamer);
        if (isset($row->$name)) {
        return $row->$name;
        }
    }
 }


$kamerid = 3;
$kamer = new kamer();
echo $kamer->straat . '<br>';
?>


Alleen hoe krijg is de $kamerid in de class? Ik heb het ook met call__ geprobeerd omdat je er dan 2 variabelen in kunt zetten, maar dit zijn alleen variabelen die in de class gemaakt zijn. Maar ik heb een 'externe' variabel nodig.

Groet

Kima
Gewijzigd op 29/05/2011 14:59:45 door ki ma
 
Wouter J

Wouter J

29/05/2011 15:55:20
Quote Anchor link
var is niet goed. Je moet kijken naar de visibility, deze moet je ook aan de functies meegeven. Zie ook http://www.phphulp.nl/php/forum/topic/oop-visibility/76673/
 
Ki ma

ki ma

29/05/2011 20:49:02
Quote Anchor link
Ki ma op 29/05/2011 14:58:41:
Bedankt voor de reacties! Ik snap het nu alweer een stuk beter.

Maar nu heb ik het dus anders aangepakt met de __get variabel in de get.
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
<?
class kamer {
    var
$kamer_id  = '1' ;
// of bijv: var $kamer_id  = $kamer_id  ; maar dit mag niet werken...
    
   function __get($name) {
        $sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $this->kamer_id . "'";
        $q_checkkamer = mysql_query($sql_checkkamer);
        $row = mysql_fetch_object($q_checkkamer);
        if (isset($row->$name)) {
        return $row->$name;
        }
    }
 }


$kamerid = 3;
$kamer = new kamer();
echo $kamer->straat . '<br>';
?>


Alleen hoe krijg is de $kamerid in de class? Ik heb het ook met call__ geprobeerd omdat je er dan 2 variabelen in kunt zetten, maar dit zijn alleen variabelen die in de class gemaakt zijn. Maar ik heb een 'externe' variabel nodig.

Alvast bedankt

Kima




Toevoeging op 29/05/2011 20:49:47:

*del*

Toevoeging op 29/05/2011 20:50:01:

*del*
 
Erik van de Locht

Erik van de Locht

29/05/2011 21:47:12
Quote Anchor link
Ik denk dat je het idee er achter niet helemaal snapt. Ik ben zelf niet bekend met de magic method __get, maar als ik de documentatie bekijk dan kun je zo iets op bouwen:
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
<?php
class Persoon {
    private $naam;
    private $leeftijd;
    
    public function __construct($naam, $leeftijd = null) {
        $this->naam = $naam;
        $this->leeftijd = $leeftijd;
    }

    
    public function __get($name) {
        if (isset($this->$name)) {
            return $this->$name;
        }

        return null;
    }
}
?>


Enkele principes die doorgaans veel genoemd worden zijn DRY (Don't Repeat Yourself) en KISS (Keep It Simple, Stupid).

Je moet er voor zorgen dat elke functie maar 1 doel heeft. Op die manier kun je ze vaker in je code aanroepen (herbruikbaarheid).

Als ik naar je klasse Kamer kijk, doe je 2 dingen in je functie. Je haalt de gegevens uit de database en returnt een waarde. Kortom, elke keer als je een instantievariabele opvraagt wordt er een query uitgevoerd. Lijkt me niet echt de meest ideale oplossing.

Wat me een logischere oplossing lijkt, is om de ID (waarmee je een kamer uit de database haalt) als parameter aan je constructor te geven. Vervolgens haal je in de constructor de gegevens uit de database en stel je de instantievariabelen daar mee in.

Vervolgens heb je de __get methode om de instantievariabelen een voor een op te vragen.
Gewijzigd op 29/05/2011 21:50:40 door Erik van de Locht
 
Ki ma

ki ma

29/05/2011 21:50:06
Quote Anchor link
Finally ik ben eruit.
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
<?
class kamer {

    public $kamerid;

    private function __get($name) {
        $sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $this->kamerid . "'";
        $q_checkkamer = mysql_query($sql_checkkamer);
        $row = mysql_fetch_object($q_checkkamer);
        if (isset($row->$name)) {
            return $row->$name;
        }
    }

}


$kamer = new kamer();
$kamer->kamerid = 1;
echo $kamer->straat . '<br>';
?>


Ik moest dit "$kamer->kamerid = 1;" nog doen om de $var binnen de class te krijgen.
Gewijzigd op 29/05/2011 21:51:07 door ki ma
 
Wouter J

Wouter J

29/05/2011 21:56:10
Quote Anchor link
Nog steeds heb je niet goed door wat __get doet en ik zie nog niks terug van de tips van erik en mij.
 
Erik van de Locht

Erik van de Locht

29/05/2011 21:57:10
Quote Anchor link
Nu heb je nog steeds public instantievariabelen. Zoek eens op internet naar wat een constructor is. Dan kun je de ID mee geven als parameter bij het instantieren; zo dus:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
$kamer
= new Kamer(1);
?>
 
Ki ma

ki ma

29/05/2011 22:55:49
Quote Anchor link
Zo komt het meer in de richting. Het werkt anders prima:
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
<?
class kamer {

    public function __construct($kamer) {
        $this->kamerid = $kamer;
        $this->sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $this->kamerid . "'";
        $this->q_checkkamer = mysql_query($this->sql_checkkamer);
        $this->row = mysql_fetch_object($this->q_checkkamer);
    }


    private function __get($name) {
        if (isset($this->row->$name)) {
            return $this->row->$name;
        }
else {
              return null;
        }
    }
}


$kamer = new kamer(1);
echo $kamer->straat . '<br>';
?>
 
Erik van de Locht

Erik van de Locht

29/05/2011 23:47:52
Quote Anchor link
Zo kun je het inderdaad ook opbouwen. Maar denk aan de volgende dingen:

De magic method __get moet public zijn. Die methode gebruik je immers om de velden op te vragen. Bij mij geeft hij zelfts een warning als ik hem private maak.

Op regel 6 en 7 stel je variabelen in als instantievariabelen. Behoorlijk overbodig.
Zie de instantievariabelen als 'iets wat het object fisiek echt heeft'.
Zo heeft een Persoon een naam, leeftijd, BSN nummer, etc. Je kunt nou niet echt zeggen dat een Kamer een select query heeft. Gewoon een normale variabele van maken dus, net als de select handler van de query die je uit voert.

De instantievariabelen die je nu instelt werken wel, maar ze zijn standaard altijd public! Ofwel de __get methode is nog al overbodig omdat je alles alsnog gewoon met
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo $objectnaam->kamerid; ?>

kunt benaderen.

Bovenaan je code de instantievariabelen instellen als private. Zie de voorbeelden die ik eerder gaf.

En nog een laatste tip, gebruik duidelijke namen voor variabelen. Ik snap dat je met 'row' het resultaat uit de database bedoelt, maar maak er dan eerder iets van 'kamerinformatie' van, dat werkt veel gemakkelijker. Anders zie je door de bomen het bos niet meer als je code wat groter wordt.

Erik
 
Ki ma

ki ma

30/05/2011 16:04:58
Quote Anchor link
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
<?
class get_kamer {
    private $sql_checkkamer;
    private $q_checkkamer;
    private $kamer_info;
    private $kamerid;

    public function __construct($kamer) {
        $this->kamerid = $kamer;
    }


    private function getrow() {
        $this->sql_checkkamer = "SELECT * FROM kamers WHERE id = '" . $this->kamerid . "'";
        $this->q_checkkamer = mysql_query($this->sql_checkkamer);
        $this->kamer_info = mysql_fetch_object($this->q_checkkamer);
    }


    public function __get($name) {
        $this->getrow();
        if (isset($this->kamer_info->$name)) {
            return $this->kamer_info->$name;
        }
else {
            return null;
        }
    }
}

$kamer = new get_kamer(1);
echo $kamer->straat . '<br>';
?>


Nu is het dus zo. Ik heb de select variabelen even gesplitst om het overzichtelijker te maken. Verder heb ik de variabelen nu private gemaakt in de class zelf.

Bedoel je met:
"Gewoon een normale variabele van maken dus, net als de select handler van de query die je uit voert." dat ik hem bijvoorbeeld zo moet aanvragen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?
$sql
= 'de select regel' ;
$kamer = new get_kamer(1,$sql);
?>

Maar dan vervalt een beetje het nut van de class. Het was de bedoeling dat ik hierdoor snel en gemakkelijk kamer informatie kan opvragen ipv iedere keer de hele sql select regels hoef toe te voegen..
Gewijzigd op 30/05/2011 16:08:14 door ki ma
 
Thijs -

Thijs -

31/05/2011 22:21:57
Quote Anchor link
Hallo,

Helemaal OOP is deze class ook nog niet,

Tip: Een functie (of methode) doet maar één.
Een class is een verzameling functies die 1 onderwerp hebben.

Stukje theorie:
Je wilt iets over een kamer maken, kamers ophalen, kamers opslaan. Waarin een database of een tekst bestand ?

oftewel.

Dit is heel globaal hoor ;), dus niet direcht kopieren en plakken en hopen dat het werkt.
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
<?php
class kamer {
 private $kamerid;
 private $kamernaam;

private $db;
 public function __construct() {
    $this->db = new db();
 }


 public function getKamer($kamerid) {
  return $this->db->fetch("SELECT * FROM kamers WHERE kamerid = '" . $kamerid ."');
 }

 public function getKamers() {
return $this->db->fetch("
SELECT * FROM kamers");
}

public function addKamer($kamernaam) {
 $this->db->query("
insert into kamers (kamernaam) values (" . $kamernaam . ")");
}
}

?>


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
<?php

class db {
 private $connection;

public function __construct() {
 $this->connection = mysql_connect(USERNAME, PASSWORD, HOST, DATABASE);

}

public function fetch($qry) {
 return mysql_fetch_array($this->query($qry));
}

public function query($qry) {
return mysql_query($qry, $this->connection);
}
}

?>


En dit is nog maar het begin, geen fout afhandeling. niet optimale. In plaats van enkele variabelen mee sturen in functies kan je ook classes of structs mee sturen. maar het idee is er.

Op deze manier kan je wanneer je "data laag" oftewel de database veranderd 1 ding aanpassen en het werkt. allemaal nog. En dat omdat functies van elkaar on afhankelijk zijn.

edit: kak alles weg ? dan maar overnieuw
Gewijzigd op 31/05/2011 22:36:41 door Thijs -
 
Pim -

Pim -

31/05/2011 23:03:51
Quote Anchor link
Quote:
Een class is een verzameling functies die 1 onderwerp hebben.

Nee, niet echt... Een klasse is een verzameling data en functies die op een object betrekking hebben. Object, niet onderwerp.
kamer#addKamer() is onlogisch: hoe kan je aan een kamer een kamer toevoegen
 
Thijs -

Thijs -

31/05/2011 23:15:25
Quote Anchor link
Ok daar heb je gelijk in,

Kamer::add(); is in mijn opzicht wel een goede manier.

Waarschijnlijk doel jij op een class Huis waar je kamers aan toe kan voegen. Ben ik het eigenlijk wel mee eens.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.