PHP OOP - Property setten middels constructor of methode?
Ik zit met een vraagje en ik kan hier niet echt een duidelijk antwoord op vinden. De antwoorden die ik vind, hebben weer te maken met andere zaken dan waar ik de vraag om stel.
Wanneer ik bijvoorbeeld een klasse 'Gebruiker' heb aangemaakt, kan ik dan beter property 'gebruiker_id' setten middels de klasse-constructor of middels een methode (bijv. 'set_gebruiker_id')?
Voor zover ik weet:
Voordelen methode 1 (middels de constructor):
- Je hoeft geen methode meer aan te roepen (in de constructor kun je deze property zonder methode vullen);
Note: ik zou sowieso een methode maken, mocht je van 'id' willen wisselen.
Voordelen methode 2 (middels een setter):
- Voor elke property kun je een setter en getter maken (lijkt me uiteindelijk overzichtelijker);
Note: in sommige gevallen (bijv. database-klasse) is een constructor misschien geschikter.
- Uiteindelijk wordt het dan voor grotere projecten gebruikt, dus wat is overzichtelijker?
- Zitten hier nog performance-verschillen in?
Dus: optie 1 of optie 2 van het onderstaande voorbeeld?
Code (php)
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
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
<?php
// Methode 1 - middels de constructor
class Klassenaam1 {
private $_id;
public function __construct($id = 0)
{
$this->_id = intval($id);
}
public function get_id()
{
return $this->_id;
}
}
$klassenaam1 = new Klassenaam1(1337);
echo $klassenaam1->get_id();
/* -------------------------- */
// Methode 2 - middels een methode
class Klassenaam2 {
private $_id;
public function set_id($id = 0)
{
$this->_id = intval($id);
}
public function get_id()
{
return $this->_id;
}
}
$klassenaam2 = new Klassenaam2;
$klassenaam2->set_id(1337);
echo $klassenaam2->get_id();
?>
// Methode 1 - middels de constructor
class Klassenaam1 {
private $_id;
public function __construct($id = 0)
{
$this->_id = intval($id);
}
public function get_id()
{
return $this->_id;
}
}
$klassenaam1 = new Klassenaam1(1337);
echo $klassenaam1->get_id();
/* -------------------------- */
// Methode 2 - middels een methode
class Klassenaam2 {
private $_id;
public function set_id($id = 0)
{
$this->_id = intval($id);
}
public function get_id()
{
return $this->_id;
}
}
$klassenaam2 = new Klassenaam2;
$klassenaam2->set_id(1337);
echo $klassenaam2->get_id();
?>
Alvast bedankt voor de tips/reacties! :-)
Gr. Kevin
Je kan best via de constructor een waarde geven, niets mis mee. Alleen ook als je het in de constructor doet, zou ik het nog via een setter doen. Reden is heel simpel. Als je later nog eens een extra check wil invoeren (bijvoorbeeld id moet groter dan 0 zijn), dan hoef je alleen die setter aan te passen. Omdat de constructor ook die setter aanroept, ben je gelijk klaar.
Ja, een combinatie van die twee leek me ook wel een geschikte optie. Als ik voor methode 1 zou gaan, dan zou ik sowieso ook een set-methode aanmaken (om de duidelijke reden die jij ook noemde).
Maar tijdens de eerste init (of hoe je dat ook noemt) van de klasse, kan dit beter/netter middels de constructor (enkel en alleen het id), of niet? Mocht ik later het id willen veranderen, dan kan dat middels de setter.
Ik heb nog even rondgekeken en wat ik zo kon vinden over de performance: het zou niets uit moeten maken. Zelfs bij aardig grote projecten is dit verschil nihil.
Ik ben dan van plan om het zo te gaan oppakken:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$gebruiker = new Gebruiker(1337); // 1337 komt uit een GET-waarde
$gebruiker->load(); // Deze methode haalt de gegevens uit de database o.b.v. het id en set de properties direct (niet met de methodes).
echo $gebruiker->get_gebruiker_id(); // Output: 1337
// Mocht je van id willen wisselen, dan kan dat met deze setter:
$gebruiker->set_gebruiker_id(666);
echo $gebruiker->get_gebruiker_id() // Output: 666
?>
$gebruiker = new Gebruiker(1337); // 1337 komt uit een GET-waarde
$gebruiker->load(); // Deze methode haalt de gegevens uit de database o.b.v. het id en set de properties direct (niet met de methodes).
echo $gebruiker->get_gebruiker_id(); // Output: 1337
// Mocht je van id willen wisselen, dan kan dat met deze setter:
$gebruiker->set_gebruiker_id(666);
echo $gebruiker->get_gebruiker_id() // Output: 666
?>
Enige nadeel van deze methode (i.c.m. de load-methode) is dat bij het aanroepen van load(), dat er dan een hoop "overbodige/extra" gegevens worden geladen.
Code (php)
Wat betreft die load functie, daar kan je dus ook een property in je class bouwen die bijhoudt welke gegevens moeten worden opgehaald. Daar zet je standaard waardes in via de constructor, maar kan je laten veranderen middels een setter. Heeft een bepaalde pagina dus veel minder gegevens nodig dan kan dat worden aangepast.
Gewijzigd op 28/01/2013 10:44:06 door Erwin H
Kevin de Groot op 28/01/2013 10:36:07:
... Maar tijdens de eerste init ... kan dit beter/netter middels de constructor (enkel en alleen het id), of niet?..
Die vraag kan teruggekaatst worden.
Heb jij tijdens de constructor die waarde al nodig?
Indien niet, kan het later gebeuren.
Een voorbeeld: pdo.
$db = new PDO($dsn, $user, $password);
Hier vind ik het vrij relevant dat de connectie-gegevens al bij de constructor worden meegegeven.
Na het aanroepen van de constructor is het object klaar voor gebruik.
Andere "optionele" settings kunnen beter later.
bv.
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
En wat betreft de load-functie: een extra parameter (een array bijvoorbeeld) meesturen naar de constructor. En dan in de load-methode die gegevens uit de array halen? Bijvoorbeeld (en let niet op gegevens-validatie, het gaat om het idee):
Code (php)
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
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
<?php
class Klassenaam {
private $_gebruiker_id;
private $_gegevens;
public function __construct($gebruiker_id = 0, $gegevens = array())
{
if (!is_array($gegevens))
{
$gegevens = array('gebruikersnaam', 'email');
}
$this->set_gegevens($gegevens);
$this->set_gebruiker_id($gebruiker_id);
}
public function set_gegevens($gegevens = array())
{
unset($this->_gegevens);
$this->_gegevens = $gegevens
}
public function set_gebruiker_id($gebruiker_id = 0)
{
$this->_gebruiker_id = intval($gebruiker_id);
}
public function get($veld = 'id')
{
if (in_array($veld, $this->_gegevens))
{
return $this->_gegevens[$veld];
}
else
{
return 'niet bekend';
}
}
public function load()
{
$query = "SELECT ". implode(',', $this->_gegevens) ." FROM gebruiker WHERE gebruiker.id = ". $this->_gegevens ." LIMIT 1";
// De rest van de code (fetchen enz)...
foreach($this->_gegevens as $i => $veld)
{
$this->_gegevens[$veld] = $fetch[$veld];
}
}
}
$gebruiker = new Gebruiker(1337, array('gebruikersnaam', 'email', 'wachtwoord'));
$gebruiker->load();
?>
class Klassenaam {
private $_gebruiker_id;
private $_gegevens;
public function __construct($gebruiker_id = 0, $gegevens = array())
{
if (!is_array($gegevens))
{
$gegevens = array('gebruikersnaam', 'email');
}
$this->set_gegevens($gegevens);
$this->set_gebruiker_id($gebruiker_id);
}
public function set_gegevens($gegevens = array())
{
unset($this->_gegevens);
$this->_gegevens = $gegevens
}
public function set_gebruiker_id($gebruiker_id = 0)
{
$this->_gebruiker_id = intval($gebruiker_id);
}
public function get($veld = 'id')
{
if (in_array($veld, $this->_gegevens))
{
return $this->_gegevens[$veld];
}
else
{
return 'niet bekend';
}
}
public function load()
{
$query = "SELECT ". implode(',', $this->_gegevens) ." FROM gebruiker WHERE gebruiker.id = ". $this->_gegevens ." LIMIT 1";
// De rest van de code (fetchen enz)...
foreach($this->_gegevens as $i => $veld)
{
$this->_gegevens[$veld] = $fetch[$veld];
}
}
}
$gebruiker = new Gebruiker(1337, array('gebruikersnaam', 'email', 'wachtwoord'));
$gebruiker->load();
?>
Zo kun je die array met gegevens ook aanroepen in de load-methode, maar goed, het gaat om het idee :-)
Ik heb enkele simpele systeempjes gemaakt in OOP, maar het is allemaal te omslachtig. Voor elke property twee methodes (set en get) aanmaken met allemaal statische/hard-coded benamingen. Wat ik wil zeggen is: ik ben niet geheel nieuw in OOP, wel in praktische/dynamische zaken. Als hier tutorials over te vinden zijn, dan lees ik die met alle plezier doen :-) Een cursus kan ik niet van jou/jullie vragen, haha!
Toevoeging op 28/01/2013 11:10:24:
Oeps, ik had jouw bericht over het hoofd gezien, Kris.
Gegevens m.b.t. de verbinding met de database vind ik wel logisch om die mee te geven in de constructor. In dit geval (gebruiker-klasse) vind ik een gebruiker_id meesturen ook wel relevant. Op basis van een gebruiker_id kan er van alles gedaan worden, gebruiker_id is in dit geval vereist. Zo kun je andere methodes gebruiken voor handelingen met deze gebruiker(_id).
Het idee klopt inderdaad. Afgezien van de validatie denk ik alleen dat je 1 fout maakt. Eerst plaats je de op te halen kolommen in $this->_gegevens, later plaats je de opgehaalde gegevens in $this->_gegevens. Als je dus na de load method nog een keer de set_gegevens method aanroept dan ben je al je gebruikers gegevens weer kwijt. Lijkt mij handiger om dat in twee verschillende properties op te slaan.
Dus drie properties aanmaken (in dit voorbeeld):
1. gebruiker_id (bijvoorbeeld: 1337)
2. velden (bijvoorbeeld: array('voornaam', 'achternaam'))
3. waarden (bijvoorbeeld: array('Kevin', 'de Groot'))
Misschien niet overal de juiste namen gebruikt, maar het is een voorbeeldje.
Precies.
Thanks! :-)