[OOP] Poll Zonder MySQL
Voordat ik mijn versie van een Poll zonder MySQL in de scriptlib post, hoor ik graag jullie opmerkingen erover.
Opbouwende kritiek is altijd welkom, maar op grove antwoorden zal ik niet reageren.
'class.php' kan je includen / kopieren, en in 'index.php' staat een voorbeeld van het gebruik. 'poll_votes.php' is een leeg bestand (aanmaken voor gebruik!) voor het checken van het IP en de gegeven antwoorden:
Een voorbeeld is te vinden op http://www.agenebbes.nl/under_construction/Poll/
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<?php
class Poll {
var $question = '';
var $answers = array();
var $name = '';
var $poll_votes = array();
function __construct() {
$this->setPollVotes();
}
protected function setPollVotes() {
$poll_votes = array();
include('poll_votes.php');
$this->poll_votes = $poll_votes;
}
protected function getPollVotes() {
return $this->poll_votes;
}
public function setPollName($name) {
$this->name = $name;
}
public function getPollName() {
return $this->name;
}
public function resetPollName() {
$this->name = '';
}
public function setQuestion($question) {
$this->question = $question;
}
public function getQuestion() {
return $this->question;
}
public function resetQuestion() {
$this->question = '';
}
public function addAnswer($answer) {
if(is_array($answer)){
foreach($answer as $key => $value){
$this->answers[] = $value;
}
}else{
$this->answers[] = $answer;
}
}
public function getAnswers() {
return $this->answers;
}
public function resetAnswers() {
$this->answers = array();
}
public function checkIp($ip) {
$poll_votes = $this->getPollVotes();
$pollName = $this->getPollName();
foreach($poll_votes as $key => $value){
if((!empty($pollName) && $poll_votes[$key]['pollName'] == $pollName && $poll_votes[$key]['ip'] == md5($ip)) ||
(empty($pollName) && $poll_votes[$key]['ip'] == md5($ip)) ||
($poll_votes[$key]['pollName'] == 'BAN' && $poll_votes[$key]['ip'] == md5($ip))){
return false;
}
}
return true;
}
protected function addIp($ip) {
if(!is_writable('poll_votes.php')){
return false;
}
$file = fopen('poll_votes.php', 'rb');
$content = str_replace('<?php ', '', fgets($file));
$content = str_replace(' ?>', '', $content);
fclose($file);
$file = fopen('poll_votes.php', 'w+b');
$new_content = '$poll_votes[] = array(\'pollName\' => \'' . $this->getPollName() . '\', \'ip\' => \'' . md5($ip) . '\');';
if(!fwrite($file, '<?php ' . $content . $new_content . ' ?>')){
fclose($file);
return false;
}
fclose($file);
return true;
}
public function banIp($ip) {
if(!is_writable('poll_votes.php')){
return false;
}
$file = fopen('poll_votes.php', 'rb');
$content = str_replace('<?php ', '', fgets($file));
$content = str_replace(' ?>', '', $content);
fclose($file);
$file = fopen('poll_votes.php', 'w+b');
$new_content = '$poll_votes[] = array(\'pollName\' => \'BAN\', \'ip\' => \'' . md5($ip) . '\');';
if(!fwrite($file, '<?php ' . $content . $new_content . ' ?>')){
fclose($file);
return false;
}
fclose($file);
return true;
}
public function addVote($answer) {
if(!$this->checkIp($_SERVER['REMOTE_ADDR'])){
return false;
}
if(!is_numeric($answer)){
return false;
}
if(!is_writable('poll_votes.php')){
return false;
}
$file = fopen('poll_votes.php', 'rb');
$content = str_replace('<?php ', '', fgets($file));
$content = str_replace(' ?>', '', $content);
fclose($file);
$file = fopen('poll_votes.php', 'w+b');
$new_content = ' $poll_votes[] = array(\'pollName\' => \'' . $this->getPollName() . '\', \'ip\' => \'' . md5($_SERVER['REMOTE_ADDR']) . '\', \'answer\' => \'' . $answer . '\');';
if(!fwrite($file, '<?php ' . $content . $new_content . ' ?>')){
fclose($file);
return false;
}
fclose($file);
return true;
}
public function getVotes() {
$answers = $this->getAnswers();
$total = 0;
foreach($answers as $key => $value){
$votes[$key]['count'] = 0;
$votes[$key]['answer'] = $value;
}
$this->setPollVotes();
$poll_votes = $this->getPollVotes();
foreach($poll_votes as $key => $value){
if($poll_votes[$key]['pollName'] == $this->getPollName()){
$votes[$poll_votes[$key]['answer']]['count']++;
$total++;
}
}
foreach($answers as $key => $value){
if($total == 0){
$votes[$key]['percentage'] = '0';
}else{
$votes[$key]['percentage'] = round($votes[$key]['count'] / $total * 100, 1);
}
}
return $votes;
}
}
?>
class Poll {
var $question = '';
var $answers = array();
var $name = '';
var $poll_votes = array();
function __construct() {
$this->setPollVotes();
}
protected function setPollVotes() {
$poll_votes = array();
include('poll_votes.php');
$this->poll_votes = $poll_votes;
}
protected function getPollVotes() {
return $this->poll_votes;
}
public function setPollName($name) {
$this->name = $name;
}
public function getPollName() {
return $this->name;
}
public function resetPollName() {
$this->name = '';
}
public function setQuestion($question) {
$this->question = $question;
}
public function getQuestion() {
return $this->question;
}
public function resetQuestion() {
$this->question = '';
}
public function addAnswer($answer) {
if(is_array($answer)){
foreach($answer as $key => $value){
$this->answers[] = $value;
}
}else{
$this->answers[] = $answer;
}
}
public function getAnswers() {
return $this->answers;
}
public function resetAnswers() {
$this->answers = array();
}
public function checkIp($ip) {
$poll_votes = $this->getPollVotes();
$pollName = $this->getPollName();
foreach($poll_votes as $key => $value){
if((!empty($pollName) && $poll_votes[$key]['pollName'] == $pollName && $poll_votes[$key]['ip'] == md5($ip)) ||
(empty($pollName) && $poll_votes[$key]['ip'] == md5($ip)) ||
($poll_votes[$key]['pollName'] == 'BAN' && $poll_votes[$key]['ip'] == md5($ip))){
return false;
}
}
return true;
}
protected function addIp($ip) {
if(!is_writable('poll_votes.php')){
return false;
}
$file = fopen('poll_votes.php', 'rb');
$content = str_replace('<?php ', '', fgets($file));
$content = str_replace(' ?>', '', $content);
fclose($file);
$file = fopen('poll_votes.php', 'w+b');
$new_content = '$poll_votes[] = array(\'pollName\' => \'' . $this->getPollName() . '\', \'ip\' => \'' . md5($ip) . '\');';
if(!fwrite($file, '<?php ' . $content . $new_content . ' ?>')){
fclose($file);
return false;
}
fclose($file);
return true;
}
public function banIp($ip) {
if(!is_writable('poll_votes.php')){
return false;
}
$file = fopen('poll_votes.php', 'rb');
$content = str_replace('<?php ', '', fgets($file));
$content = str_replace(' ?>', '', $content);
fclose($file);
$file = fopen('poll_votes.php', 'w+b');
$new_content = '$poll_votes[] = array(\'pollName\' => \'BAN\', \'ip\' => \'' . md5($ip) . '\');';
if(!fwrite($file, '<?php ' . $content . $new_content . ' ?>')){
fclose($file);
return false;
}
fclose($file);
return true;
}
public function addVote($answer) {
if(!$this->checkIp($_SERVER['REMOTE_ADDR'])){
return false;
}
if(!is_numeric($answer)){
return false;
}
if(!is_writable('poll_votes.php')){
return false;
}
$file = fopen('poll_votes.php', 'rb');
$content = str_replace('<?php ', '', fgets($file));
$content = str_replace(' ?>', '', $content);
fclose($file);
$file = fopen('poll_votes.php', 'w+b');
$new_content = ' $poll_votes[] = array(\'pollName\' => \'' . $this->getPollName() . '\', \'ip\' => \'' . md5($_SERVER['REMOTE_ADDR']) . '\', \'answer\' => \'' . $answer . '\');';
if(!fwrite($file, '<?php ' . $content . $new_content . ' ?>')){
fclose($file);
return false;
}
fclose($file);
return true;
}
public function getVotes() {
$answers = $this->getAnswers();
$total = 0;
foreach($answers as $key => $value){
$votes[$key]['count'] = 0;
$votes[$key]['answer'] = $value;
}
$this->setPollVotes();
$poll_votes = $this->getPollVotes();
foreach($poll_votes as $key => $value){
if($poll_votes[$key]['pollName'] == $this->getPollName()){
$votes[$poll_votes[$key]['answer']]['count']++;
$total++;
}
}
foreach($answers as $key => $value){
if($total == 0){
$votes[$key]['percentage'] = '0';
}else{
$votes[$key]['percentage'] = round($votes[$key]['count'] / $total * 100, 1);
}
}
return $votes;
}
}
?>
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
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
require_once('class.php');
$fPoll = new Poll;
$fPoll->setPollName('Testpoll');
$fPoll->setQuestion('Wat vind je van deze poll?');
$fPoll->addAnswer('Zeer goed');
$fPoll->addAnswer('Goed');
$fPoll->addAnswer('Matig');
$fPoll->addAnswer('Slecht');
$fPoll->addAnswer('Zeer Slecht');
if($fPoll->checkIp($_SERVER['REMOTE_ADDR'])){
if($_SERVER['REQUEST_METHOD'] == 'POST'){
if(!$fPoll->addVote($_POST[$fPoll->getPollName()])){
echo 'Uw antwoord kon niet worden toegevoegd.';
}else{
echo 'Uw antwoord is succesvol toegevoegd.<br><br>';
$votes = $fPoll->getVotes();
foreach($votes as $key => $key){
echo $votes[$key]['answer'] . ' - ' . $votes[$key]['count'] . ' (' . $votes[$key]['percentage'] . ' %)<br>';
}
}
}else{
echo $fPoll->getQuestion() . '<br><br>';
echo '<FORM ACTION="" METHOD="POST">';
$answers = $fPoll->getAnswers();
foreach($answers as $key => $value){
echo '<INPUT TYPE="radio" NAME="' . $fPoll->getPollName() . '" VALUE="' . $key . '"> ' . $value . '<br>';
}
echo '<br><INPUT TYPE="submit" VALUE="Vote!" NAME="submit">';
echo '</FORM>';
}
}else{
$votes = $fPoll->getVotes();
foreach($votes as $key => $value){
echo $votes[$key]['answer'] . ' - ' . $votes[$key]['count'] . ' (' . $votes[$key]['percentage'] . ' %)<br>';
}
}
?>
require_once('class.php');
$fPoll = new Poll;
$fPoll->setPollName('Testpoll');
$fPoll->setQuestion('Wat vind je van deze poll?');
$fPoll->addAnswer('Zeer goed');
$fPoll->addAnswer('Goed');
$fPoll->addAnswer('Matig');
$fPoll->addAnswer('Slecht');
$fPoll->addAnswer('Zeer Slecht');
if($fPoll->checkIp($_SERVER['REMOTE_ADDR'])){
if($_SERVER['REQUEST_METHOD'] == 'POST'){
if(!$fPoll->addVote($_POST[$fPoll->getPollName()])){
echo 'Uw antwoord kon niet worden toegevoegd.';
}else{
echo 'Uw antwoord is succesvol toegevoegd.<br><br>';
$votes = $fPoll->getVotes();
foreach($votes as $key => $key){
echo $votes[$key]['answer'] . ' - ' . $votes[$key]['count'] . ' (' . $votes[$key]['percentage'] . ' %)<br>';
}
}
}else{
echo $fPoll->getQuestion() . '<br><br>';
echo '<FORM ACTION="" METHOD="POST">';
$answers = $fPoll->getAnswers();
foreach($answers as $key => $value){
echo '<INPUT TYPE="radio" NAME="' . $fPoll->getPollName() . '" VALUE="' . $key . '"> ' . $value . '<br>';
}
echo '<br><INPUT TYPE="submit" VALUE="Vote!" NAME="submit">';
echo '</FORM>';
}
}else{
$votes = $fPoll->getVotes();
foreach($votes as $key => $value){
echo $votes[$key]['answer'] . ' - ' . $votes[$key]['count'] . ' (' . $votes[$key]['percentage'] . ' %)<br>';
}
}
?>
Met vriendelijke groet,
Tim
Gewijzigd op 01/01/1970 01:00:00 door Tim
serialize gebruiken om de inhoud van het bestand te maken, maar dit zal ook wel goed werken op zich. Het voordeel van serialize is dat je ook hele complexe structuren kan opslaan, en ze zo weer terug kan halen naar PHP data zonder het relatief onveilige include() te gebruiken. Er zijn ook PHP installaties waar PHP geen beschrijfbare bestanden kan includen/uitvoeren, jouw script werkt dan niet meer.
Is het trouwens niet een beter idee om toch even die $poll_votes variabelen ergens in een property op te slaan wanneer deze al geladen is? Nu include je het bestand meerdere malen, en met meer votes gaat dat langzamer worden.
Je zou nog kunnen overwegen de awnsers en votes aparte objecten te maken zodat je die (lelijke) multidimensionale arrays kan wegwerken.
Ik zou zelf Is het trouwens niet een beter idee om toch even die $poll_votes variabelen ergens in een property op te slaan wanneer deze al geladen is? Nu include je het bestand meerdere malen, en met meer votes gaat dat langzamer worden.
Je zou nog kunnen overwegen de awnsers en votes aparte objecten te maken zodat je die (lelijke) multidimensionale arrays kan wegwerken.
Ik heb eens even zitten kijken naar serialize, en daar ga ik me zeker nog wat meer in verdiepen.
Het opslaan van die $poll_votes heb ik aangepast, maar aangezien deze ook weer ingeladen moet worden na een stem, levert dit (denk ik) niet zoveel tijdswinst op.
Het gebruik van multidimensionale arrays is een persoonlijke keuze. Jij vindt ze lelijk, ik zie het als een mooie mogelijkheid om ingewikkelde modellen te maken ;-).
Gewijzigd op 01/01/1970 01:00:00 door Tim
Oop daarentegen is juist niet voor de beginners, zij zullen moeite hebben met het doorgronden van de logica in/van een class en zien het voordeel er (nog) niet van in.
Uiteraard gebruik ik vor 99% van mijn applicaties wel SQL. Toch zou het om de een of andere vage reden voor kunnen komen dat er een keer geen SQL-database voorhanden is. Daarom dit scriptje / deze class, waarmee makkelijk een poll te integreren is in iedere willekeurige website.
Oeh, over beschrijfbare bestanden gesproken, misschien is het wel handig om wat escape functies toe te voegen, of checks, om te voorkomen dat quotes in de pollname problemen op gaan leveren.
Je zou ook de pollname variabele achterwege kunnen laten, en het pad naar het bestand waarin de gegevens worden opgeslagen variabel kunnen maken (wat op zichzelf ook al een goed idee is, want nu is de locatie afhankelijk van in welke map je script dat deze klasse aanroept staat, en wat zijn cwd is) Het voordeel van verschillende losse bestandjes is dat het makkelijk te backuppen is, minder foutgevoelig (of liever gezegd, minder destructief in het geval van een fout) en lichter om in te laden.
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Het punt is nu niet of er wel of niet altijd een database aanwezig (kan) zijn, maar of het script zo goed is / werkt.
De escapefunctie zal ik binnenkort toevoegen, daar heb je helemaal gelijk in!
Bij verschillende losse bestanden houd je hetzelfde probleem als met één groot bestand, behalve het 'foutgevoeligheidspunt'. Zit het systeem echter goed in elkaar, dan kan dit niet (echt) fout gaan. Bovendien is één bestand (naar mijn idee) beter te back-uppen dan voor iedere poll één.