Tips eerste OOP scriptje
Ik programmeer nu toch al een tijdje, en heb al veel de tip gekregen om eens te beginnen met OOP. Ik had er wat over gelezen op internet en het leek mij allemaal iets te moeilijk. Ik heb mezelf nu toch eens kunnen overhalen om eens een scriptje in classes te schrijven.
Ik heb dus een mini-telefoonboekje geschreven en natuurlijk had ik graag tips gehad. Ik ken dus zo goed als niks van OOP, dus graag tips en opmerkingen.
Online voorbeeldje: http://freshcreations.be/case/oop/
Hier volgt het scriptje dat ik schreef:
mysql.class.php
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class mysql
{
public function __construct($server = '', $username = '', $password = '')
{
mysql_connect($server, $username, $password);
}
public function Select_Db($db = '')
{
if(!empty($db))
{
mysql_select_db($db);
}
else
{
echo 'Please specify a database.';
}
}
}
?>
class mysql
{
public function __construct($server = '', $username = '', $password = '')
{
mysql_connect($server, $username, $password);
}
public function Select_Db($db = '')
{
if(!empty($db))
{
mysql_select_db($db);
}
else
{
echo 'Please specify a database.';
}
}
}
?>
phonebook.class.php
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
class phonebook
{
public $number;
public $name;
public function __construct()
{
if($_SERVER['REQUEST_METHOD'] == "POST")
{
$this->ProcessForm();
}
if(isset($_GET['id']) && !empty($_GET['id']))
{
$this->ShowDetails();
}
else
{
$this->ShowList();
if($_GET['action'] == "add")
{
$this->ShowForm();
}
else
{
echo '<a href="?action=add">Add person</a>';
}
}
}
public function ProcessForm()
{
if(!empty($_POST['name']) && !empty($_POST['number']))
{
$query = "INSERT INTO persons (name, number) VALUES('".htmlspecialchars(mysql_real_escape_string($_POST['name']))."', '".htmlspecialchars(mysql_real_escape_string($_POST['number']))."')";
$result = mysql_query($query) or die(mysql_error());
if($result)
{
echo 'The person has been added to the phonebook.';
}
else
{
echo 'Something went wrong while trying to add the new person to the phonebook.';
}
}
else
{
echo 'You have to fill in all the fields.';
}
}
public function ShowList()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query) or die(mysql_error());
if(mysql_num_rows($result) > 0)
{
echo '
<table border="1">
<tr>
<td width="60">Name</td><td width="110">Number</td><td width="30">Detail</td>
</tr>';
while($row = mysql_fetch_assoc($result))
{
echo '
<tr>
<td>'.$row['name'].'</td><td>'.$row['number'].'</td><td align="center"><a href="?id='.$row['id'].'">X</a></td>
</td>
</tr>';
}
echo '</table><br />';
}
else
{
echo 'No records present.<br /><br />';
}
}
public function ShowDetails()
{
$query = "SELECT name, number FROM persons WHERE id = '".$_GET['id']."'";
$result = mysql_query($query) or die(mysql_error());
if(mysql_num_rows($result) == 1)
{
$row = mysql_fetch_assoc($result);
echo 'Name: '.$row['name'].'<br />';
echo 'Number: '.$row['number'].'<br /><br />';
}
else
{
echo 'This record doesn\'t exist.';
}
}
public function ShowForm()
{
echo '
<form action="" method="post">
Name: <input name="name" type="text" /><br />
Number: <input name="number" type="text" /><br /><br />
<input name="Submit" type="submit" value="Submit" id="Submit" />
</form>';
}
}
?>
class phonebook
{
public $number;
public $name;
public function __construct()
{
if($_SERVER['REQUEST_METHOD'] == "POST")
{
$this->ProcessForm();
}
if(isset($_GET['id']) && !empty($_GET['id']))
{
$this->ShowDetails();
}
else
{
$this->ShowList();
if($_GET['action'] == "add")
{
$this->ShowForm();
}
else
{
echo '<a href="?action=add">Add person</a>';
}
}
}
public function ProcessForm()
{
if(!empty($_POST['name']) && !empty($_POST['number']))
{
$query = "INSERT INTO persons (name, number) VALUES('".htmlspecialchars(mysql_real_escape_string($_POST['name']))."', '".htmlspecialchars(mysql_real_escape_string($_POST['number']))."')";
$result = mysql_query($query) or die(mysql_error());
if($result)
{
echo 'The person has been added to the phonebook.';
}
else
{
echo 'Something went wrong while trying to add the new person to the phonebook.';
}
}
else
{
echo 'You have to fill in all the fields.';
}
}
public function ShowList()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query) or die(mysql_error());
if(mysql_num_rows($result) > 0)
{
echo '
<table border="1">
<tr>
<td width="60">Name</td><td width="110">Number</td><td width="30">Detail</td>
</tr>';
while($row = mysql_fetch_assoc($result))
{
echo '
<tr>
<td>'.$row['name'].'</td><td>'.$row['number'].'</td><td align="center"><a href="?id='.$row['id'].'">X</a></td>
</td>
</tr>';
}
echo '</table><br />';
}
else
{
echo 'No records present.<br /><br />';
}
}
public function ShowDetails()
{
$query = "SELECT name, number FROM persons WHERE id = '".$_GET['id']."'";
$result = mysql_query($query) or die(mysql_error());
if(mysql_num_rows($result) == 1)
{
$row = mysql_fetch_assoc($result);
echo 'Name: '.$row['name'].'<br />';
echo 'Number: '.$row['number'].'<br /><br />';
}
else
{
echo 'This record doesn\'t exist.';
}
}
public function ShowForm()
{
echo '
<form action="" method="post">
Name: <input name="name" type="text" /><br />
Number: <input name="number" type="text" /><br /><br />
<input name="Submit" type="submit" value="Submit" id="Submit" />
</form>';
}
}
?>
index.php
Code (php)
Gewijzigd op 01/01/1970 01:00:00 door Cedric
bij het voorbeeld zou ik zelf kiezen voor de volgend 2 klasses
- Telefoonboek
( Deze heeft een Array met objecten van Personen )
- Persoon
( Hierin worden alle gegevens opgeslagen van de persoon )
- Nooit echoen in je klasses, maak gebruik van return en return een string die je vervolgens in je pagina pas echoed.
- VOor het weergeven van fouten kan je Exceptions gebruiken.
- Maak gebruik van PDO ( Goed artikel: http://www.phphulp.nl/php/tutorials/8/534/ )
- Classnamen altijd met hoofdletter beginnen
- Namen van methodes met kleine letter beginnen
Wat heb je?
- Telefoonboek
- Vermeldingen in het telefoonboek. (Een vermelding zou ook los van het telefoonboek kunnen voorkomen, bijvoorbeeld in de vorm van een visitekaartje, dus daarom is deze niet een met het telefoonboek.)
Wat heeft je telefoonboek voor eigenschappen?
(de public properties)
- geen :(
Wat kan je telefoonboek?
(de public methods)
- vermeldingen ophalen
- vermeldingen toevoegen
Wat heeft je telefoonboek daarvoor nodig?
(de protected properties & methods)
- een database-verbinding.
Wat heeft je vermelding voor eigenschappen?
- een id, uniek nummer, auto-increment kolom bijvoorbeeld.
- naam
- nummer
Wat kan je vermelding
- niet echt iets. Misschien dat je een functie kan verzinnen waarmee hij wordt weergegeven in de vorm van een hCard, al is het de vraag of je die mix van presentatie & data wilt maken.
Wat heeft je vermelding daarvoor nodig?
- niets
Dus om het even samen te vatten:
Je hebt nodig: Een database-link (ik zou gewoon lekker gemakkelijk voor PDO gaan), een Telefoonboek-klasse en een Vermelding-klasse. De telefoonboek-klasse geef je een PDO-instantie mee in de constructor, en heeft methods om vermeldingen uit de database te halen, op te slaan en te verwijderen. De ophaal-methods geven een array met instanties van Vermelding terug, de save & delete methods accepteren een instantie van Vermelding (je hoeft de instantie van Vermelding niet eens helemaal te vullen, zo lang hij maar het id van de database-regel heeft zodat het telefoonboek weet welke hij moet verwijderen.)
In een class moet je ( vrijwel ) nooit echoen. Met een exception kun je nu een error opvangen op een lager niveau en dan kan je er wat aan doen:
Code (php)
Veder is het misschien slim om ook een optionele parameter aan je constructor mee te geven voor de te selecten database.
Over het algemeen is het ook makkelijk om je open connectie bij te houden:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
protected $connection;
// en dan in je constructor:
$connection = mysql_connect (...);
?>
protected $connection;
// en dan in je constructor:
$connection = mysql_connect (...);
?>
Dan kan je bijvoorbeeld in je destructor weer de connectie sluiten.
Op de site waar ik het een en ander over OOP te weten probeerde te komen vond ik een voorbeeldje van een OO gastenboek. Dit bestond ook maar uit 1 class..
De telefoonboek-class versta ik, het bevat zowat wat ik in mijn class had. Maar de vermelding class snap ik niet echt.. In de telefoonboek class doe je toch al alles wat nodig is? En die functies, ik moet dus denken met wat ik heb? Maar wanneer mag ik dan bijvoorbeeld maar het form echoën? En hoort dat in de class te gebeuren of met een instancevan de class?
Blijkbaar was het voorbeeld die ik bekeek niet zo goed geschreven als ik het zo bekijk.. Heb je misschien een voorbeeld van een gelijkaardig script die dan wel goed geschreven is? Dan kan ik dat eens goed bestuderen en uit leren.
Een gastenboek in 1 klasse is niet werkelijk OO geprogrammeerd. Dat is gewoon het ontwerp opdelen in functies, en die achter elkaar aanroepen.
De klasse Vermelding is nu nog niet erg nuttig, maar met oog op de toekomst heb je nu een plek waar je later functies aan toe kan voegen, bijvoorbeeld voor het opvragen van bijvoorbeeld het netnummer. Dan maak je een method in je Vermelding-klasse erbij die dat deel van het telefoonnummer teruggeeft en de rest van de code hoef je niet te veranderen. Stel dat je nu je database een beetje anders inricht, en ook het landnummer in het telefoonnummer gaat opnemen. Dan kan je de methods van Vermelding die het telefoonnummer en het netnummer aanpassen zodat ze het landnummer niet ook meegeven, en je kan er een nieuwe method bij maken. De rest van je code hoeft dan niet te veranderen, omdat die slechts afhankelijk is van de buitenkant, de API van de klasse Vermelding en niet verbonden is met de werking binnenin. Dat is een van de gevolgen van OOP. Je geeft de objecten hun verantwoordelijkheden, waardoor die logica die daarvoor nodig is maar op 1 plek in de code staat gedefinieerd. Er is maar 1 plek waar die fout kan gaan, en er is maar 1 plek waar je de code hoeft te veranderen wanneer je de werking wat wilt aanpassen. Zoek maar eens op abstractie.
Een formulier echo'en e.d, oftewel presentatie zou ikzelf nooit in klassen doen, maar in aparte php-bestanden die ik al dan niet include. Je kan er ook templates voor gebruiken mocht je dat leuk vinden, al heeft het weinig toegevoegde waarde. Door de presentatie buiten de klassen te houden kan je de klassen voor veel meer doeleinden gebruiken. Daarnaast is het gewoon prettig om PHP logica & HTML zo weinig mogelijk te mixen, niet mixen is overzichtelijker. Het afhandelen van je formulier, en de eigenschappen van het object veranderen op basis van de $_POST-argumenten doe je gewoon op de manier zoals je dat altijd hebt gedaan, buiten een klasse. Eventueel maak je er later een controller-klasse van conform met het MVC design pattern. Dan kan je ook die logica hergebruiken mocht dat nodig zijn.
Ik ben nu weer opnieuw aan het proberen, maar het lijkt nu wel of ik gewoon een verzameling functies maak, niets meer. Ik begrijp het OOP gedoe natuurlijk nog niet echt.. Maar heb je misschien een voorbeeld van een scriptje die volgens jou wél goed geschreven is? Dan kan ik mij daar op baseren en kijken hoe alles in elkaar zit. Ik heb hier nu wel een OO webshop liggen maar deze is gewoon té uitgebreid om als beginner er even tussenin te kruipen en alles proberen te begrijpen.
Nu zit ik namelijk weer zo vast als iets. Een goed voorbeeld zou zeker aangenaam zijn ;)
phonebook.class.php
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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
77
78
79
80
81
82
83
84
85
<?php
class Phonebook
{
public $id;
public $name;
public $number;
public $data;
public function __construct()
{
// Niks?
}
public function get_data()
{
$this->data = array("id" => $this->id, "name" => $this->name, "number" => $this->number);
return $this->data;
}
public function set_name($name)
{
$this->name = $name;
}
public function set_number($number)
{
$this->number = $number;
}
public function add_record()
{
$query = "INSERT INTO persons (name, number) VALUES('".mysql_real_escape_string($this->name)."', '".mysql_real_escape_string($this->number)."')";
$result = mysql_query($query) or die(mysql_error());
if($result)
{
return true;
}
else
{
return false;
}
}
public function get_record($id)
{
$query = "SELECT id, name, number FROM persons WHERE id = '".$id."'";
$result = mysql_query($query) or die(mysql_error());
if(!$result)
{
return false;
}
else
{
$row = mysql_fetch_assoc($result);
$this->id = $row['id'];
$this->name = $row['name'];
$this->number = $row['number'];
return true;
}
}
public function get_all_records()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($result))
{
$record = new Phonebook;
$record->get_record($row['id']);
$records[] = $record;
}
return $records;
}
}
?>
class Phonebook
{
public $id;
public $name;
public $number;
public $data;
public function __construct()
{
// Niks?
}
public function get_data()
{
$this->data = array("id" => $this->id, "name" => $this->name, "number" => $this->number);
return $this->data;
}
public function set_name($name)
{
$this->name = $name;
}
public function set_number($number)
{
$this->number = $number;
}
public function add_record()
{
$query = "INSERT INTO persons (name, number) VALUES('".mysql_real_escape_string($this->name)."', '".mysql_real_escape_string($this->number)."')";
$result = mysql_query($query) or die(mysql_error());
if($result)
{
return true;
}
else
{
return false;
}
}
public function get_record($id)
{
$query = "SELECT id, name, number FROM persons WHERE id = '".$id."'";
$result = mysql_query($query) or die(mysql_error());
if(!$result)
{
return false;
}
else
{
$row = mysql_fetch_assoc($result);
$this->id = $row['id'];
$this->name = $row['name'];
$this->number = $row['number'];
return true;
}
}
public function get_all_records()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($result))
{
$record = new Phonebook;
$record->get_record($row['id']);
$records[] = $record;
}
return $records;
}
}
?>
index.php
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
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
<?php
include "mysql.class.php";
include "phonebook.class.php";
$db = new MySQL('localhost', '***', '***');
$db->select_db('***');
if($_SERVER['REQUEST_METHOD'] == "POST")
{
if(!empty($_POST['name']) && !empty($_POST['number']))
{
$obj = new phonebook;
$obj->set_name(htmlspecialchars($_POST['name']));
$obj->set_number(htmlspecialchars($_POST['number']));
if($obj->add_record())
{
echo 'Your record has been added.<br />';
}
else
{
echo 'Something went wrong while adding the record.<br />';
}
}
else
{
echo 'You need to fill in all the fields.<br />';
}
}
echo '
<table border="1">
<tr>
<td width="60">Name</td><td width="110">Number</td><td width="30">Detail</td>
</tr>';
foreach(Phonebook::get_all_records() as $phonebook)
{
echo '
<tr>
<td>'.$phonebook->name.'</td><td>'.$phonebook->number.'</td><td align="center"><a href="?id='.$phonebook->id.'">X</a></td>
</td>
</tr>';
}
echo '</table><br />';
?>
<form action="" method="post">
Name: <input name="name" type="text" /><br />
Number: <input name="number" type="text" /><br /><br />
<input name="Submit" type="submit" value="Submit" id="Submit" />
</form>
include "mysql.class.php";
include "phonebook.class.php";
$db = new MySQL('localhost', '***', '***');
$db->select_db('***');
if($_SERVER['REQUEST_METHOD'] == "POST")
{
if(!empty($_POST['name']) && !empty($_POST['number']))
{
$obj = new phonebook;
$obj->set_name(htmlspecialchars($_POST['name']));
$obj->set_number(htmlspecialchars($_POST['number']));
if($obj->add_record())
{
echo 'Your record has been added.<br />';
}
else
{
echo 'Something went wrong while adding the record.<br />';
}
}
else
{
echo 'You need to fill in all the fields.<br />';
}
}
echo '
<table border="1">
<tr>
<td width="60">Name</td><td width="110">Number</td><td width="30">Detail</td>
</tr>';
foreach(Phonebook::get_all_records() as $phonebook)
{
echo '
<tr>
<td>'.$phonebook->name.'</td><td>'.$phonebook->number.'</td><td align="center"><a href="?id='.$phonebook->id.'">X</a></td>
</td>
</tr>';
}
echo '</table><br />';
?>
<form action="" method="post">
Name: <input name="name" type="text" /><br />
Number: <input name="number" type="text" /><br /><br />
<input name="Submit" type="submit" value="Submit" id="Submit" />
</form>
Ik vind wel dat het nogal traag laadt. Maar is dit al beter dan de vorige keer?
Beetje vreemd. Voor ieder telefoonnummer maak je een nieuw telefoonboek aan, en fetch je opnieuw alle data. Een telefoonnummer is toch niet een eigenschap van een telefoonboek? Een kaft is, maar een telefoonnummer hoort thuis in een klasse vermelding. Daarom zei ik dat je die los moest trekken.
Ik moet nu in feite nog een onderscheid maken welk functies in de boekklasse moet en welke in vermeldingklasse..
Ik moet dus in die loop vermeldinginstanties maken denk ik. Welke functies heb ik nodig in telefoonboek en welke in vermelding? Naar mijn mening kan add_record(); in beide? :S
Ik ga morgen even je voorbeeld goed bestuderen en dan nog s een poging wagen.
Obj-C is eigenlijk een hele handige taal om het idee achter OOP te leren zo gezien. In Obj-C stuur je namelijk 'berichten' naar objecten. Voorbeeldje:
waarin telefoonboek een instantie is van Telefoonboek, en mijnVermelding een instantie van Vermelding. Je zegt als het ware tegen het telefoonboek dat hij die vermelding moet opnemen. Logischer kan het volgens mij niet.
phonebook.class.php
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
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
<?php
class Phonebook
{
public function __construct()
{
// Niks?
}
public function add_record($obj)
{
$query = "INSERT INTO persons (name, number) VALUES('".mysql_real_escape_string($obj->name)."', '".mysql_real_escape_string($obj->number)."')";
$result = mysql_query($query) or die(mysql_error());
if($result)
{
return true;
}
else
{
return false;
}
}
public function get_all_records()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($result))
{
$record = new Phonerecord;
$record->set_id($row['id']);
$record->set_name($row['name']);
$record->set_number($row['number']);
$record->get_record();
$records[] = $record;
}
return $records;
}
}
?>
class Phonebook
{
public function __construct()
{
// Niks?
}
public function add_record($obj)
{
$query = "INSERT INTO persons (name, number) VALUES('".mysql_real_escape_string($obj->name)."', '".mysql_real_escape_string($obj->number)."')";
$result = mysql_query($query) or die(mysql_error());
if($result)
{
return true;
}
else
{
return false;
}
}
public function get_all_records()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($result))
{
$record = new Phonerecord;
$record->set_id($row['id']);
$record->set_name($row['name']);
$record->set_number($row['number']);
$record->get_record();
$records[] = $record;
}
return $records;
}
}
?>
phonerecord.class.php
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
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
<?php
class Phonerecord
{
public $id;
public $name;
public $number;
public function __construct()
{
//
}
public function set_id($id)
{
$this->id = $id;
}
public function set_name($name)
{
$this->name = $name;
}
public function set_number($number)
{
$this->number = $number;
}
public function get_record()
{
$query = "SELECT id, name, number FROM persons WHERE id = '".$this->id."'";
$result = mysql_query($query) or die(mysql_error());
if(!$result)
{
return false;
}
else
{
$row = mysql_fetch_assoc($result);
$this->id = $row['id'];
$this->name = $row['name'];
$this->number = $row['number'];
return true;
}
}
}
?>
class Phonerecord
{
public $id;
public $name;
public $number;
public function __construct()
{
//
}
public function set_id($id)
{
$this->id = $id;
}
public function set_name($name)
{
$this->name = $name;
}
public function set_number($number)
{
$this->number = $number;
}
public function get_record()
{
$query = "SELECT id, name, number FROM persons WHERE id = '".$this->id."'";
$result = mysql_query($query) or die(mysql_error());
if(!$result)
{
return false;
}
else
{
$row = mysql_fetch_assoc($result);
$this->id = $row['id'];
$this->name = $row['name'];
$this->number = $row['number'];
return true;
}
}
}
?>
index.php
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
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
<?php
include "mysql.class.php";
include "phonebook.class.php";
include "phonerecord.class.php";
$db = new MySQL('localhost', '***', '***');
$db->select_db('***');
if($_SERVER['REQUEST_METHOD'] == "POST")
{
if(!empty($_POST['name']) && !empty($_POST['number']))
{
$phonebook = new Phonebook;
$obj = new Phonerecord;
$obj->set_name(htmlspecialchars($_POST['name']));
$obj->set_number(htmlspecialchars($_POST['number']));
if($phonebook->add_record($obj))
{
echo 'Your record has been added.<br />';
}
else
{
echo 'Something went wrong while adding the record.<br />';
}
}
else
{
echo 'You need to fill in all the fields.<br />';
}
}
echo '
<table border="1">
<tr>
<td width="60">Name</td><td width="110">Number</td><td width="30">Detail</td>
</tr>';
foreach(Phonebook::get_all_records() as $record)
{
echo '
<tr>
<td>'.$record->name.'</td><td>'.$record->number.'</td><td align="center"><a href="?id='.$record->id.'">X</a></td>
</td>
</tr>';
}
echo '</table><br />';
?>
<form action="" method="post">
Name: <input name="name" type="text" /><br />
Number: <input name="number" type="text" /><br /><br />
<input name="Submit" type="submit" value="Submit" id="Submit" />
</form>
include "mysql.class.php";
include "phonebook.class.php";
include "phonerecord.class.php";
$db = new MySQL('localhost', '***', '***');
$db->select_db('***');
if($_SERVER['REQUEST_METHOD'] == "POST")
{
if(!empty($_POST['name']) && !empty($_POST['number']))
{
$phonebook = new Phonebook;
$obj = new Phonerecord;
$obj->set_name(htmlspecialchars($_POST['name']));
$obj->set_number(htmlspecialchars($_POST['number']));
if($phonebook->add_record($obj))
{
echo 'Your record has been added.<br />';
}
else
{
echo 'Something went wrong while adding the record.<br />';
}
}
else
{
echo 'You need to fill in all the fields.<br />';
}
}
echo '
<table border="1">
<tr>
<td width="60">Name</td><td width="110">Number</td><td width="30">Detail</td>
</tr>';
foreach(Phonebook::get_all_records() as $record)
{
echo '
<tr>
<td>'.$record->name.'</td><td>'.$record->number.'</td><td align="center"><a href="?id='.$record->id.'">X</a></td>
</td>
</tr>';
}
echo '</table><br />';
?>
<form action="" method="post">
Name: <input name="name" type="text" /><br />
Number: <input name="number" type="text" /><br /><br />
<input name="Submit" type="submit" value="Submit" id="Submit" />
</form>
Nu moet het gewoon goed :S Ik denk dat het redelijk goed gelukt is, behalve bij get_record. Ik had de keuze om zonder argument of met te werken. Ik heb zonder gewerkt omdat get_record() gewoon de gegevens van het huidige object moet hebben. Anders kon ik ook een id als argument meegeven, maar dan kan hij de gegevens van allemaal ophalen. Ik weet niet welke best is, maar ik nam deze omdat ik denk datie enkel de gegevens van zichzelf nodig heeft.
Als je de mogelijkheid wilt hebben om individuele records op te halen, zou ik de get_record method verplaatsen naar Phonebook, en hem inderdaad zoals je zelf al zegt een id als argument laten slikken. Bovendien is het voordelig als je deze method naar Phonebook verplaatst, aangezien je dan alle opslag-gerelateerde functies alleen binnen Phonebook hebt, en Phonerecord er niet meer gevoelig voor is (en in theorie, mocht je de database ook via klassen willen gaan doen, niet meer afhankelijk is van een instantie van de database)
Verder zie ik dat je in Phonerecord wel accessors (de get_ en set_ method) hebt, maar je eigenschappen ook public. Accessors zijn er eigenlijk voor bedoeld dat de werking binnenin het object niet naar buiten komt. Dus probeer de eigenschappen zoveel mogelijk protected te houden, en het object van buitenaf alleen via de accessors aan te spreken. Ook binnen phonebook.
Je gebruikt bij je queries 'or die()', terwijl je daarna ook nog controleert of het resultaat wel bestaat (en indien niet, false teruggeeft) Het is een good practice om je klassen zo verlegen mogelijk te maken. Laat ze geen uitvoer echo'en, en zeker geen scripts halverwege afkappen wanneer een query mislukt. Hiervoor kun je sinds PHP 5 heel goed Exceptions gebruiken. Op die manier kan je haperende klassen binnen je script opvangen zonder dat de rest daar last van hoeft te hebben.
In index.php zie ik dat je htmlspecialchars over de gegevens in Phonerecord haalt. Dat heeft als gevolg dat je al opgemaakte data in je database zet. Voor HTML alleen zou dat niet snel problemen opleveren. Maar stel dat je de data ook wilt gaan gebruiken in emailtjes, of in plain text-documenten. Dan is de data die je in je database hebt al 'bevuilt' met HTML. Het is een goed idee om de data zo rauw mogelijk in je database op te slaan, en het escapen van speciale karakters pas te doen wanneer de data wordt weergegeven.
Zo kan ik ook netjes de form validatie in mijn classe uitvoeren en krijg ik nette errors op mijn scherm. Alles afvangen is natuurlijk een must. Een debug variabele geeft precies de hoeveelheid aan informatie die de error moet bevatten aan. Ik vind het heel prettig werken, aangezien ik elke classe dus extend met deze standaard classe, en ik mijn output, (bijvoorbeeld jou index.php) enorm kan inkorten. Dit werkt extra snel en makkelijk wat betreft de opmaak.
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
60
61
62
63
64
65
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
<?php
class Phonebook
{
public function __construct()
{
//
}
public function add_record($obj)
{
$query = "INSERT INTO persons (name, number) VALUES('".mysql_real_escape_string($obj->get_name())."', '".mysql_real_escape_string($obj->get_number())."')";
$result = mysql_query($query);
if($result)
{
return true;
}
else
{
return false;
}
}
public function get_record($id, $obj)
{
$query = "SELECT id, name, number FROM persons WHERE id = '".$id."'";
$result = mysql_query($query);
if(!$result)
{
return false;
}
else
{
$row = mysql_fetch_assoc($result);
$obj->set_id($row['id']);
$obj->set_name($row['name']);
$obj->set_number($row['number']);
return true;
}
}
public function get_all_records()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result))
{
$record = new Phonerecord;
$record->set_id($row['id']);
$record->set_name($row['name']);
$record->set_number($row['number']);
$records[] = $record;
}
return $records;
}
}
?>
class Phonebook
{
public function __construct()
{
//
}
public function add_record($obj)
{
$query = "INSERT INTO persons (name, number) VALUES('".mysql_real_escape_string($obj->get_name())."', '".mysql_real_escape_string($obj->get_number())."')";
$result = mysql_query($query);
if($result)
{
return true;
}
else
{
return false;
}
}
public function get_record($id, $obj)
{
$query = "SELECT id, name, number FROM persons WHERE id = '".$id."'";
$result = mysql_query($query);
if(!$result)
{
return false;
}
else
{
$row = mysql_fetch_assoc($result);
$obj->set_id($row['id']);
$obj->set_name($row['name']);
$obj->set_number($row['number']);
return true;
}
}
public function get_all_records()
{
$query = "SELECT id, name, number FROM persons";
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result))
{
$record = new Phonerecord;
$record->set_id($row['id']);
$record->set_name($row['name']);
$record->set_number($row['number']);
$records[] = $record;
}
return $records;
}
}
?>
Wat ik nu wel heb is dat ik bij een get_record een instance van een phonerecord moet meegeven. Is dit wel de juiste manier van werken?
Naam weergeven
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$obj = new Phonebook;
$rec = new Phonerecord;
$obj->get_record(26, $rec);
echo $rec->get_name();
?>
$obj = new Phonebook;
$rec = new Phonerecord;
$obj->get_record(26, $rec);
echo $rec->get_name();
?>
Cedric schreef op 28.03.2008 17:23:
Wat ik nu wel heb is dat ik bij een get_record een instance van een phonerecord moet meegeven. Is dit wel de juiste manier van werken?
Het is niet echt nodig. Ik zou get_record de instantie laten aanmaken. Dat scheelt je weer herhalend werk en het is eigenlijk logischer. In je huidige opzet is het meer een fill_record dan een get_record.
Trouwens, je kan nu bijvoorbeeld add_record de klasse van het argument laten afdwingen:
Dat maakt je code weer wat leesbaarder en foutjes komen een heel klein beetje sneller aan het licht.
Ow, ik bedenk me net, je kan ook mysql_fetch_object gebruiken. Die accepteert als 2e argument een klasse. Dat scheelt je weer 3 setters aanroepen per object:
Sterker nog, nu zou je de set_id-accessor kunnen weglaten. Een id is immers ook niet aan te passen, die is uniek en permanent per record, dus een setter daarvoor hebben is eigenlijk niet logisch.
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Jelmer schreef op 28.03.2008 17:39:
Het is niet echt nodig. Ik zou get_record de instantie laten aanmaken. Dat scheelt je weer herhalend werk en het is eigenlijk logischer. In je huidige opzet is het meer een fill_record dan een get_record.
Ik liet de functie de instantie aanmaken: $record = new Phonerecord; En dan returnde ik op het einde $record. Maar toen was ik verplicht in het script $record te gebruiken als object inplaats van $rec.
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$rec = $phonebook->get_record(24);
$rec->set_name('Klaas de 2e');
$phonebook->save_record($rec);
?>
$rec = $phonebook->get_record(24);
$rec->set_name('Klaas de 2e');
$phonebook->save_record($rec);
?>
Dat lijkt mij de meest logische en gemakkelijke volgorde.
tutorial over.
Om methodes zoals get_data, set_name en set_data te voorkomen zou je ook eens kunnen kijken naar de magic methods in PHP5. Staat op deze site een prima Anyway, magic methods zijn inderdaad ook een oplossing om je getters & setters te verbergen. Of je ze wilt gebruiken is puur persoonlijk. Ze bieden verder geen voordelen in de zin van snelheid of gebruikersgemak. Zelf geef ik tegenwoordig meer de voorkeur aan ouderwetse methods, omdat je daar al klassen kan afdwingen in de definitie van de argumenten van de method, en de methods mooi naar voren komen in de documentatie en de andere hulpmiddelen zoals Eclipse. Maar een jaar geleden zou ik nog __get & __set gebruikt hebben. Tegenwoordig gebruik ik die alleen nog maar om trucjes als 'lazy loading' en 'chainability' in te kunnen bouwen.