OO lijsten
hoe maak ik een lijst met OOP?
ik ben bezig met een intern mailsysteem, daar worden berichten opgeslagen in de database. dan heb ik een Mail_Processor class, die de benodigde data ophaalt uit de database, wat bewerkt etc (bv een method om het aantal nieuwe mailtjes te tonen, 1 specifieke mail op te halen, etc)
nu wil ik dus ook, net als in elke mailbox, een lijst met alle mails (en dan alleen afzender + onderwerp ofzo). maar hoe pak ik dat aan? ik had zelf gedacht om alle resultaten op te halen, html van maken in een var, en dat dan returnen. maar dat lijkt me niet echt netjes etc. en het volgende probleem is dan daaraan pagination toevoegen, dat er max 15 berichten op elke pagina staan. hoe doe ik dat op een goede manier?
Met de pagination of wat er met de array gedaan wordt mag de MessageMapper helemaal niet weten. Voor Pagination heb je een eigen klasse en hoe het op het scherm komt beslis je in een View klasse of via procedurele code.
Globaal wordt het iets van dit:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
$messageMapper = new MessageMaper();
$messagesPagination = new Pagination($messageMapper->getAll());
$messagesPagination->setMaxPerPage(15);
?>
<ul id="messages">
<?php foreach ($messagesPagination->getPage(1) as $message) : ?>
<li><a href="show_message.php?id=<?php echo $message->getId(); ?>"><?php echo $message->getName(); ?></a></li>
<?php endforeach ?>
</ul>
$messageMapper = new MessageMaper();
$messagesPagination = new Pagination($messageMapper->getAll());
$messagesPagination->setMaxPerPage(15);
?>
<ul id="messages">
<?php foreach ($messagesPagination->getPage(1) as $message) : ?>
<li><a href="show_message.php?id=<?php echo $message->getId(); ?>"><?php echo $message->getName(); ?></a></li>
<?php endforeach ?>
</ul>
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
115
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
115
<?php
class Mail_Processor
{
private $_db;
private $_userId;
public __construct(PDO $db, $userId)
{
$this->_db = $db;
$this->_userId = $userId;
}
public function sendMail($desUser, $message, $subject)
{
$getDesUserId =
"SELECT
user_id
FROM
users
WHERE
user_id = :desUser";
$stmt = $this->_db->prepare($getDusUserId);
$results = $stmt->exec(array(':desUser' => $desUser))->fetch();
if (count($results) != 1)
{
return 'Recepient does not exist';
}
else
{
$desUserId = $results['user_id'];
$insertMail =
"INSERT INTO
messages
(desUser_id,
senUser_id,
subject,
message,
dateAndTime,
new)
VALUES
(:desUser,
:senUser,
:subject,
:message,
NOW(),
1)";
$stmt = $this->_db->prepare($insertMail);
$inserted = $stmt->exec(':desUser' => $desUserId,
':senUser' => $this->_userId,
':subject' => $subject,
':message' => $message);
if ($inserted != 1)
{
return 'something went wrong. please try again';
}
else
{
return 'your mail was succesfully sent!';
}
}
}
public function NewMails()
{
$newMails =
"SELECT
COUNT(message_id) AS mails
FROM
messages
WHERE
new = 1
AND
desUser_id = :userId";
$stmt = $this->_db->prepare($newMails);
$mails = $stmt->exec(array(':userId' => $this->_userId))->fetch();
return $mails['mails'];
}
public function listMails($results, $start)
{
}
public function showMail($messageId)
{
$getMail =
"SELECT
users.username AS sender,
messages.subject AS subject,
messages.message AS message,
DATE_FORMAT(messages.dateAndTIme, '%d-%m-%Y at %H:%i') AS time_sent
FROM
messages,
users
WHERE
messages.message_id = :messageId
AND
users.user_id = messages.senUser_id";
$stmt = $this->_db->prepare($getMail);
$mails = $stmt->exec(array(':messageId' => $messageId))->fetch();
if (count($mails) != 1)
{
return 'something went wrong. please try again';
}
else
{
$updateNew =
return array('sender' => $mails['sender'],
'subject' => $mails['subject'],
'message' => $mails['message'],
'time_sent' => $mails['time_sent']);
}
}
}
?>
class Mail_Processor
{
private $_db;
private $_userId;
public __construct(PDO $db, $userId)
{
$this->_db = $db;
$this->_userId = $userId;
}
public function sendMail($desUser, $message, $subject)
{
$getDesUserId =
"SELECT
user_id
FROM
users
WHERE
user_id = :desUser";
$stmt = $this->_db->prepare($getDusUserId);
$results = $stmt->exec(array(':desUser' => $desUser))->fetch();
if (count($results) != 1)
{
return 'Recepient does not exist';
}
else
{
$desUserId = $results['user_id'];
$insertMail =
"INSERT INTO
messages
(desUser_id,
senUser_id,
subject,
message,
dateAndTime,
new)
VALUES
(:desUser,
:senUser,
:subject,
:message,
NOW(),
1)";
$stmt = $this->_db->prepare($insertMail);
$inserted = $stmt->exec(':desUser' => $desUserId,
':senUser' => $this->_userId,
':subject' => $subject,
':message' => $message);
if ($inserted != 1)
{
return 'something went wrong. please try again';
}
else
{
return 'your mail was succesfully sent!';
}
}
}
public function NewMails()
{
$newMails =
"SELECT
COUNT(message_id) AS mails
FROM
messages
WHERE
new = 1
AND
desUser_id = :userId";
$stmt = $this->_db->prepare($newMails);
$mails = $stmt->exec(array(':userId' => $this->_userId))->fetch();
return $mails['mails'];
}
public function listMails($results, $start)
{
}
public function showMail($messageId)
{
$getMail =
"SELECT
users.username AS sender,
messages.subject AS subject,
messages.message AS message,
DATE_FORMAT(messages.dateAndTIme, '%d-%m-%Y at %H:%i') AS time_sent
FROM
messages,
users
WHERE
messages.message_id = :messageId
AND
users.user_id = messages.senUser_id";
$stmt = $this->_db->prepare($getMail);
$mails = $stmt->exec(array(':messageId' => $messageId))->fetch();
if (count($mails) != 1)
{
return 'something went wrong. please try again';
}
else
{
$updateNew =
return array('sender' => $mails['sender'],
'subject' => $mails['subject'],
'message' => $mails['message'],
'time_sent' => $mails['time_sent']);
}
}
}
?>
Ik zou eerst beginnen met het maken van UML diagrammen van wat je nou precies wilt en hoe je het nou in objecten moet onderverdelen.
maar krijg je volgens jou niet iets als dit:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
public function sendMail($desUser, $message, $subject)
{
MailMapper::sendMail($desUser, $message, $subject);
}
?>
public function sendMail($desUser, $message, $subject)
{
MailMapper::sendMail($desUser, $message, $subject);
}
?>
of in de procedurele code een aantal verschillende objecten aanmaken, allemaal met verschillende functies? maar krijg je dan niet precies hetzelfde?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
// User gedoe
$userMapper = new UserMapper();
$user = $userMapper->getById(12);
if (!$user->isLoggedIn()) {
throw new RunTimeException('U moet wel ingelogd zijn.');
}
// Send Mail
$mailMapper = new MailMapper();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (!isset($_POST['message'])) {
throw new RunTimeException('Er moet wel een bericht ingevuld worden');
}
// enz.
$mail = new Mail($user, $_POST['to'], $_POST['message']);
if ($mailMapper->sendMail($mail)) {
echo 'Mail succesvol verzonden';
}
}
?>
// User gedoe
$userMapper = new UserMapper();
$user = $userMapper->getById(12);
if (!$user->isLoggedIn()) {
throw new RunTimeException('U moet wel ingelogd zijn.');
}
// Send Mail
$mailMapper = new MailMapper();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (!isset($_POST['message'])) {
throw new RunTimeException('Er moet wel een bericht ingevuld worden');
}
// enz.
$mail = new Mail($user, $_POST['to'], $_POST['message']);
if ($mailMapper->sendMail($mail)) {
echo 'Mail succesvol verzonden';
}
}
?>
ik vat m niet helemaal. maak je nu een object mail aan met alleen maar gegegevens, en je geeft die gegevens door aan de mailmapper?
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 MailMapper
{
/* ... */
public function sendMail(Mail $mail)
{
$sQuery = "INSERT INTO messages(user_to, user_from, content, subject) VALUES(:to, :from, :content, :subject)";
$stmt = $this->db->prepare($sQuery);
$stmt->execute(array(
':to' => $mail->getUserTo(),
':from' => $mail->getUserFrom(),
':subject' => $mail->getSubject(),
':content' => $mail->getContent(),
));
if ($stmt->rowCount() > 0) {
return true;
}
else {
return new LogicException('<de foutmeldig>');
}
}
}
?>
class MailMapper
{
/* ... */
public function sendMail(Mail $mail)
{
$sQuery = "INSERT INTO messages(user_to, user_from, content, subject) VALUES(:to, :from, :content, :subject)";
$stmt = $this->db->prepare($sQuery);
$stmt->execute(array(
':to' => $mail->getUserTo(),
':from' => $mail->getUserFrom(),
':subject' => $mail->getSubject(),
':content' => $mail->getContent(),
));
if ($stmt->rowCount() > 0) {
return true;
}
else {
return new LogicException('<de foutmeldig>');
}
}
}
?>
ok volgens mij snap ik het! zal het eens omschrijven naar bovenstaand, om zo dus iets moois te krijgen. bedankt voor de mooie uitleg!
message.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
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
<?php
class Message
{
//int, sender (sender user id)
private $_senUserId;
//int, recepient (destination user id)
private $_desUserId;
//string, message content
private $_content;
//string, message subject
private $_subject;
//string, date & time message was sent
private $_dateTime;
public function __construct($SenUserId, $desUserId, $content, $subject, $dateTime)
{
//variable declaration
$this->_senUserId = $senUserId;
$this->_desUserId = $desUserId;
$this->_content = $content;
$this->_subject = $subject;
$this->_dateTime = $dateTime;
}
public function getSenUserId()
{
return $this->_senUserId;
}
public function getDesUser()
{
return $this->_desUser;
}
public function getContent()
{
return $this->_content;
}
public function getSubject()
{
return $this->_subject;
}
public function getDateTime()
{
return $this->_dateTime;
}
}
?>
class Message
{
//int, sender (sender user id)
private $_senUserId;
//int, recepient (destination user id)
private $_desUserId;
//string, message content
private $_content;
//string, message subject
private $_subject;
//string, date & time message was sent
private $_dateTime;
public function __construct($SenUserId, $desUserId, $content, $subject, $dateTime)
{
//variable declaration
$this->_senUserId = $senUserId;
$this->_desUserId = $desUserId;
$this->_content = $content;
$this->_subject = $subject;
$this->_dateTime = $dateTime;
}
public function getSenUserId()
{
return $this->_senUserId;
}
public function getDesUser()
{
return $this->_desUser;
}
public function getContent()
{
return $this->_content;
}
public function getSubject()
{
return $this->_subject;
}
public function getDateTime()
{
return $this->_dateTime;
}
}
?>
MessageMapper.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
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
<?php
class MessageMapper
{
//object, database connection
private $_db;
public function __construct(PDO $db)
{
//variable declaration
$this->_db = $db;
}
public function sendMessage(Messsage $message)
{
$sendMessage =
"INSERT INTO
messages
(desUser_id,
senUser_id,
subject,
message,
dateAndTime,
new)
VALUES
(:desUser,
:senUser,
:subject,
:message,
NOW(),
1)";
$stmt = $this->_db->prepare($sendMessage);
$inserted = $stmt->exec(
':desUser' => $message->getDesUser(),
':senUser' => $message->getSenUser(),
':subject' => $message->getSubject(),
':message' => $message->getContent());
if ($inserted != 1)
{
return 'something went wrong. please try again';
}
else
{
return 'your mail was succesfully sent!';
}
}
public function recieveMessage($messageId, $desUserId)
{
$receiveMessage =
"SELECT
subject,
message,
senUser_id
DATE_FORMAT(messages.dateAndTIme, '%d-%m-%Y at %H:%i') AS time_sent
FROM
messages
WHERE
desUser_id = :desUserId
AND
message_id = :messageId";
$stmt = $this->_db->prepare($receiveMessage);
$stmt->exec(
':desUserId' => $messageId,
':senUser' => $desUserId);
//en dan?!!
}
}
?>
class MessageMapper
{
//object, database connection
private $_db;
public function __construct(PDO $db)
{
//variable declaration
$this->_db = $db;
}
public function sendMessage(Messsage $message)
{
$sendMessage =
"INSERT INTO
messages
(desUser_id,
senUser_id,
subject,
message,
dateAndTime,
new)
VALUES
(:desUser,
:senUser,
:subject,
:message,
NOW(),
1)";
$stmt = $this->_db->prepare($sendMessage);
$inserted = $stmt->exec(
':desUser' => $message->getDesUser(),
':senUser' => $message->getSenUser(),
':subject' => $message->getSubject(),
':message' => $message->getContent());
if ($inserted != 1)
{
return 'something went wrong. please try again';
}
else
{
return 'your mail was succesfully sent!';
}
}
public function recieveMessage($messageId, $desUserId)
{
$receiveMessage =
"SELECT
subject,
message,
senUser_id
DATE_FORMAT(messages.dateAndTIme, '%d-%m-%Y at %H:%i') AS time_sent
FROM
messages
WHERE
desUser_id = :desUserId
AND
message_id = :messageId";
$stmt = $this->_db->prepare($receiveMessage);
$stmt->exec(
':desUserId' => $messageId,
':senUser' => $desUserId);
//en dan?!!
}
}
?>
dan heb ik twee vragen die volgens mij hetzelfde antwoord hebben:
- hoe return ik die waarden op regel 65?
- hoe return ik heel veel van die waarden (dus in een lijst)?
ikzelf dacht aan (in de MessageMapper) een Message te instantieren. in beide gevallen, bij de tweede in een loop een array vullen. maar dat is niet de OOP gedachte, toch? maar hoe doe ik dat dan?
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
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
<?php
class MessageMapper
{
/* ... */
public function getMessages(...)
{
/* ... */
$result = $stmt->fetchAll();
return array_map(array($this, 'populate'), $result);
}
public function populate($data)
{
return new Message($data['subject'], $data['message'], $data['senUser_id'], $data['send_time']);
}
}
$messageMapper = new MessageMapper();
?>
<!-- HTML -->
<dl>
<?php foreach ($messageMapper->getMessages() as $message) : ?>
<dt><?php echo $message->getSubtitle() ?></dt>
<dd><?php echo $message->getContent() ?></dd>
<?php endforeach ?>
</dl>
class MessageMapper
{
/* ... */
public function getMessages(...)
{
/* ... */
$result = $stmt->fetchAll();
return array_map(array($this, 'populate'), $result);
}
public function populate($data)
{
return new Message($data['subject'], $data['message'], $data['senUser_id'], $data['send_time']);
}
}
$messageMapper = new MessageMapper();
?>
<!-- HTML -->
<dl>
<?php foreach ($messageMapper->getMessages() as $message) : ?>
<dt><?php echo $message->getSubtitle() ?></dt>
<dd><?php echo $message->getContent() ?></dd>
<?php endforeach ?>
</dl>
Verder ziet het er heel mooi en goed OOP uit!!
Nog een mooi, en leerzaam, voorbeeldje van Pim: http://www.phphulp.nl/php/forum/topic/oop-in-combinatie-met-database/81754/#580025
Gewijzigd op 12/04/2012 17:08:38 door Wouter J
btw, wat vind je van mn classes?
Code (php)
Als je array($this, 'populate') gebruikt wordt de callback functie de populate method van de klass waar je in zit. De populate method maakt dus van bepaalde gegevens een object.
En een datamapper is afhankelijk van het object dat je gebruikt dus er gaat geen flexibiliteit verloren, anders kan het ook niet. Daarnaast hoef je een klasse maar 1 keer per aanroep te includen (of eigenlijk liever te requireren).
ik begrijp het niet helemaal, maar begrijp wel wat ik ermee kan, en ik kan dit gebruiken. is het trouwens niet beter om de visibility van de populate method op protected te zetten?
Code (php)
Wat begrijp je dan niet? Code die je niet begrijpt moet je niet gebruiken vind ik altijd.
Gewijzigd op 12/04/2012 18:19:39 door Wouter J
dat ik hem wel gebruik is omdat ik wel begrijp wát het doet, alleen het hoe blijft een klein raadsel
en dat ik het kon gebruiken als 'service container' (-> ook al zo'n leuke OO term, ik wacht op de tutorial van pim ;-)) is natuurlijk handig, en had ik helemaal niet aan gedacht
Toevoeging op 12/04/2012 18:35:10:
die link die je nog geplaatst had (over het hoofd gezien) had je al eerder gegeven. heb ik inderdaad veel van geleerd :)
Quote:
(-> ook al zo'n leuke OO term, ik wacht op de tutorial van pim ;-)
Hoeft niet, is er al: Dependency Injection
Quote:
'de callback op dat array item' -> vrij cryptisch, heb maar een vaag idee wat een callback is, daarom.
De callback is de functie die wordt aangeroepen nadat iets wordt gedaan. In dit geval doet de array_map functie zoiets:
Code (php)
De callback is een functie (in dit geval MessageMapper:populate()) en die wordt per array items aangeroepen met als parameter de value of het item.
De functie die wordt aangeroepen is de callback.
Offtopic:
Dit heb je bijv. ook in JS, vooral in jQuery kan het flink oplopen: http://jsfiddle.net/fnUaq/
Aah nou snap ik hem ;) bedankt voor je lange uitleg!