Session werkt niet goed met mysql records door loop probleem
De example.php file:
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
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
<?php
//session starts
session_start();
// Database selection and pH selection (this comes from a form+post file where the pH level is asked for and selected)
switch ($_POST["pH"]) {
//Option 1 (I put xxxx for privacy purposes, guess you understand) (c1, c2, c3 are the selections you could make in the Form)
case "c1":
$con = mysqli_connect("localhost", "xxxx", "") or die (mysql_error ());
if (!$con) {die('Could not connect: ' . mysqli_error($con));}
mysqli_select_db($con,"xxx")or die(mysql_error());
//change query here
$sql="SELECT * FROM people WHERE rain <=200 AND Soil IN ('Sand','Sand Clay', 'Sand Clay Silt') AND pH<=4.5";
$result = mysqli_query($con,$sql);
break;
//Option 2
case "c2":
$con = mysqli_connect("localhost", "xxxx", "") or die (mysql_error ());
if (!$con) {die('Could not connect: ' . mysqli_error($con));}
mysqli_select_db($con,"xxx")or die(mysql_error());
//change query here
$sql="SELECT * FROM people WHERE rain <=200 AND Soil IN ('Sand','Sand Clay', 'Sand Clay Silt') AND pH BETWEEN 4.5 AND 7.0";
$result = mysqli_query($con,$sql);
break;
//Option 3
case "c3":
$con = mysqli_connect("localhost", "xxxx", "") or die (mysql_error ());
if (!$con) {die('Could not connect: ' . mysqli_error($con));}
mysqli_select_db($con,"xxx")or die(mysql_error());
//change query here
$sql="SELECT * FROM people WHERE rain <=200 AND Soil IN ('Sand','Sand Clay', 'Sand Clay Silt') AND pH >=7.0";
$result = mysqli_query($con,$sql);
break;
//default when nothing is selected
default:
$strpH = "Please go back and make your selection";
break;
}
//here starts the echo part for this page.
// printing main table
echo "<table>
<tr bgcolor=#339966>
<th>id</th>
<th>Common Name</th>
<th>Latin Name</th>
<th>pH level</th>
<th>Soil</th>
<th>Rain annual</th>
</tr>";
// Loop the recordset $result and Write the value van $result
while($row = mysqli_fetch_array($result))
{
$queryArray[] = $row;
// Declaration of session items...here something has to be changed.
$_SESSION ['select1']= $row [id];
$_SESSION ['select2']= $row ['CommonName'];
$_SESSION ['select3']= $row ['LatinName'];
$_SESSION ['select4']= $row [pH];
$_SESSION ['select5']= $row ['Soil'];
$_SESSION ['select6']= $row [rain];
echo "<tr>";
echo "<td>" .$row[id]. "</td>";
echo "<td>" .$row['CommonName']. "</td>";
echo "<td>" .$row['LatinName']. "</td>";
echo "<td>" .$row[pH]. "</td>";
echo "<td>" .$row['Soil']. "</td>";
echo "<td>" .$row[rain]. "</td>";
echo "</tr>";
}
echo "</table>";
// Close the database connection
mysqli_close($con);
?>
//session starts
session_start();
// Database selection and pH selection (this comes from a form+post file where the pH level is asked for and selected)
switch ($_POST["pH"]) {
//Option 1 (I put xxxx for privacy purposes, guess you understand) (c1, c2, c3 are the selections you could make in the Form)
case "c1":
$con = mysqli_connect("localhost", "xxxx", "") or die (mysql_error ());
if (!$con) {die('Could not connect: ' . mysqli_error($con));}
mysqli_select_db($con,"xxx")or die(mysql_error());
//change query here
$sql="SELECT * FROM people WHERE rain <=200 AND Soil IN ('Sand','Sand Clay', 'Sand Clay Silt') AND pH<=4.5";
$result = mysqli_query($con,$sql);
break;
//Option 2
case "c2":
$con = mysqli_connect("localhost", "xxxx", "") or die (mysql_error ());
if (!$con) {die('Could not connect: ' . mysqli_error($con));}
mysqli_select_db($con,"xxx")or die(mysql_error());
//change query here
$sql="SELECT * FROM people WHERE rain <=200 AND Soil IN ('Sand','Sand Clay', 'Sand Clay Silt') AND pH BETWEEN 4.5 AND 7.0";
$result = mysqli_query($con,$sql);
break;
//Option 3
case "c3":
$con = mysqli_connect("localhost", "xxxx", "") or die (mysql_error ());
if (!$con) {die('Could not connect: ' . mysqli_error($con));}
mysqli_select_db($con,"xxx")or die(mysql_error());
//change query here
$sql="SELECT * FROM people WHERE rain <=200 AND Soil IN ('Sand','Sand Clay', 'Sand Clay Silt') AND pH >=7.0";
$result = mysqli_query($con,$sql);
break;
//default when nothing is selected
default:
$strpH = "Please go back and make your selection";
break;
}
//here starts the echo part for this page.
// printing main table
echo "<table>
<tr bgcolor=#339966>
<th>id</th>
<th>Common Name</th>
<th>Latin Name</th>
<th>pH level</th>
<th>Soil</th>
<th>Rain annual</th>
</tr>";
// Loop the recordset $result and Write the value van $result
while($row = mysqli_fetch_array($result))
{
$queryArray[] = $row;
// Declaration of session items...here something has to be changed.
$_SESSION ['select1']= $row [id];
$_SESSION ['select2']= $row ['CommonName'];
$_SESSION ['select3']= $row ['LatinName'];
$_SESSION ['select4']= $row [pH];
$_SESSION ['select5']= $row ['Soil'];
$_SESSION ['select6']= $row [rain];
echo "<tr>";
echo "<td>" .$row[id]. "</td>";
echo "<td>" .$row['CommonName']. "</td>";
echo "<td>" .$row['LatinName']. "</td>";
echo "<td>" .$row[pH]. "</td>";
echo "<td>" .$row['Soil']. "</td>";
echo "<td>" .$row[rain]. "</td>";
echo "</tr>";
}
echo "</table>";
// Close the database connection
mysqli_close($con);
?>
En hieronder de output.php file
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
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
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
session_start();
// setting the table
echo "<table>
<tr bgcolor=#339966>
<th>id</th>
<th>Common Name</th>
<th>Latin Name</th>
<th>pH level</th>
<th>Soil</th>
<th>Rain annual</th>
</tr>";
//readig session variables
echo "<tr>";
echo "<td>" .$_SESSION ['select1']. "</td>";
echo "<td>" .$_SESSION ['select2']. "</td>";
echo "<td>" .$_SESSION ['select3']. "</td>";
echo "<td>" .$_SESSION ['select4']. "</td>";
echo "<td>" .$_SESSION ['select5']. "</td>";
echo "<td>" .$_SESSION ['select6']. "</td>";
echo "</tr>";
echo "</table>";
?>
ini_set('display_errors', 'On');
error_reporting(E_ALL);
session_start();
// setting the table
echo "<table>
<tr bgcolor=#339966>
<th>id</th>
<th>Common Name</th>
<th>Latin Name</th>
<th>pH level</th>
<th>Soil</th>
<th>Rain annual</th>
</tr>";
//readig session variables
echo "<tr>";
echo "<td>" .$_SESSION ['select1']. "</td>";
echo "<td>" .$_SESSION ['select2']. "</td>";
echo "<td>" .$_SESSION ['select3']. "</td>";
echo "<td>" .$_SESSION ['select4']. "</td>";
echo "<td>" .$_SESSION ['select5']. "</td>";
echo "<td>" .$_SESSION ['select6']. "</td>";
echo "</tr>";
echo "</table>";
?>
Gewijzigd op 30/10/2015 10:33:42 door Marco Bijl
Het enige wat variabel is in je switch-statement is je query, de rest (maken connectie, selecteren database, uitvoeren query) is elke keer hetzelfde; dit kun je dus buiten je switch-statement trekken. Je kunt dus deze code dus flink in het aantal regels terugbrengen.
Daarnaast is het enige gegeven wat bepaalt hoe de query luidt, en dus welke resultaten getoond worden $_POST['pH']. Als je dit gegeven nu eens in $_GET (je querystring) doorgeeft? Dan hoef je niet alle (zoek?)resultaten over te hevelen in je sessie. Je zou er zelfs voor kunnen kiezen om enkel dat (de pH-waarde) op te slaan in je sessie, maar je hoeft hiervoor helemaal geen sessie te gebruiken.
Te meer als dit een soort van zoekfunctionaliteit is: gebruik alsjeblieft $_GET, dit levert ook knip- en plakbare links op (in tegenstelling tot wanneer je $_POST gebruikt).
Ik zou dus deze ingeslagen weg niet verder bewandelen, maar de hele aanpak omgooien.
Ik weet ook niet wat je in het bovenstaande probeert te bereiken; als je op grond van een pH-waarde data wilt afdrukken kun je, als je hiervoor $_GET gebruikt, zelfs dezelfde broncode gebruiken...
In een formulier zijn er 3 keuzes. De example.php koppelt elke keuze aan een selectie uit een database. Je merkt terecht op dat connectie maken e.d. buiten de Switch kan, dat ga ik doen. Dank daarvoor.
Op dezelfde example.php pagina wordt alles goed ge-echoed. Er worden meerdere records getoond als dat er meerdere moeten zijn. So far so good.
Mijn doel is om deze selectie van meer records nogmaals te echoen op een andere pagina. Dat is de output.php file (dat wil ik zodat bezoekers daar een schone lijst kunnen printen). Maar dat lukt dus niet. Ik weet niet precies hoe ik daar dan $_GET voor kan gebruiken, of hoe e.a. daar in een loop te zetten. Wellicht kun je me helpen met een stukje code? Ben hier al dagen mee bezig en wil maar niet lukken.
Ik begrijp dat er de wens is om de selectie die je in example.php maakt (via een formulier) onthoudt in output.php.
Je zult mij moeten helpen met twee dingen:
* Hoe verschilt example.php wezenlijk van output.php, is het de bedoeling dat je in laatstgenoemde pagina andere dingen kunt doen dan example.php? Anders lijkt mij een van de twee overbodig.
* Als blijkt dat output.php een bestaansrecht heeft naast example.php, is het dan de bedoeling dat je van example.php kunt navigeren naar output.php?
Zoals ik het op dit moment zie doen beide pagina's hetzelfde.
Als dit alles zoekfunctionaliteit betreft, dan zou ik je formulier aanpassen naar zoiets:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<form action="example.php" method="get">
<select name="ph">
<option value="c1">c1</option>
<option value="c2">c2</option>
<option value="c3">c3</option>
</select>
<button type="submit">go</button>
</form>
<select name="ph">
<option value="c1">c1</option>
<option value="c2">c2</option>
<option value="c3">c3</option>
</select>
<button type="submit">go</button>
</form>
Vervolgens doe je zoiets in example.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
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
<?php
// stop in includes/connect.php je database-connectie-gegevens
require './includes/connect.php';
if (isset($_GET['ph'])) {
$query = false;
switch ($_GET['ph']) {
case 'c1':
$query = '... je c1 query hier ...';
break;
case 'c2':
$query = '... je c2 query hier ...';
break;
case 'c3':
$query = '... je c3 query hier ...';
break;
}
if ($query === false) {
?><p>Geen geldige pH waarde geselecteerd.</p><?php
} else {
// voer hier je query $query uit en druk de resultaten af
// ...
}
} else {
?><p>Geen pH waarde geselecteerd.</p><?php
}
?>
// stop in includes/connect.php je database-connectie-gegevens
require './includes/connect.php';
if (isset($_GET['ph'])) {
$query = false;
switch ($_GET['ph']) {
case 'c1':
$query = '... je c1 query hier ...';
break;
case 'c2':
$query = '... je c2 query hier ...';
break;
case 'c3':
$query = '... je c3 query hier ...';
break;
}
if ($query === false) {
?><p>Geen geldige pH waarde geselecteerd.</p><?php
} else {
// voer hier je query $query uit en druk de resultaten af
// ...
}
} else {
?><p>Geen pH waarde geselecteerd.</p><?php
}
?>
En als je de geselecteerde pH waarde over meerdere pagina's wilt onthouden sla je deze op in $_SESSION, maar niet alle bijbehorende resultaten.
* Hoe verschilt example.php wezenlijk van output.php, is het de bedoeling dat je in laatstgenoemde pagina andere dingen kunt doen dan example.php? Anders lijkt mij een van de twee overbodig.
Inderdaad ga je straks ook andere dingen doen in Example.php; namelijk een volgende formulier invullen (wat dan doorverwijst naar Example2.php, Example3.php etc etc (volg je het nog?). Uiteindelijk wordt het een systeem waar je via verschillende pagina's met vragen (Forms) steeds een meer nauwkeurige zoekopdracht uitvoert in dezelfde database. Het gaat hier over het selecteren van Boomsoorten waarbij je eerst gevraagd wordt naar de grondsoort, dan pH, available water, etc etc. (eigenlijk wilde ik een volledig dynamische pagina waarbij je eerst een zoekresultaat laat zien, dan de volgende vraag invult, en onmiddellijk een meer nauwkeurige zoekresultaat laat zien (een selectie uit de eerste zoekopdracht), dan weer een vraag invult, ect etc. Maar aangezien ik echt geen idee heb, en in welke code, hoe ik zo'n dynamisch script moet maken ben ik de weg hierboven maar ingeslagen; er zullen wel een hoop files moeten worden aangemaakt op deze manier.
* Als blijkt dat output.php een bestaansrecht heeft naast example.php, is het dan de bedoeling dat je van example.php kunt navigeren naar output.php?
Inderdaad. Op example.php komt een button (naast een nieuwe Form waar je naar Example 2,3,4 etc gaat) waar je navigeert naar een nieuwe pagina met enkel de resultaten van je zoekopdracht, en verder niets. Die kun je daar dan printen/of PDF van maken.
Bedankt alvast voor de suggesties hierboven. Als je er nog meer hebt aan de hand van mijn antwoord dan graag!
Anders kun je volstaan met één filter-formulier waarbij je een of meer filterwaarden invult en vervolgens een query opbouwt op grond van ingevulde filter-eigenschappen (de niet-ingevulde filter-eigenschappen worden buiten beschouwing gelaten).
Ik denk dat de opzet van je zoekfunctionaliteit afhangt van:
- hoe je data georganiseerd is, en
- hoe je hier (vervolgens) in wilt zoeken
Het antwoord op je vraag is een mix van beide suggesties.
In principe is het idee van 1 Form met 5-6 vragen ok. Maar de antwoorden moeten dan wel uiteindelijk 1 eindselectie opleveren. Dus alle antwoorden moeten bij elkaar gevoegd, en daar moet dan één zoekopdracht voor gegeven worden. Hoe dat precies dan zou moeten weet ik niet, je moet dan inderdaad een query opbouwen....of example.php moet een keuze kunnen maken uit alle (pakweg 100 verschillende mogelijke eindselecties (5-6 vragen met elk 3-4 antwoorden).
Maar ik schreef een mix van je suggesties. Want ik zou wel graag elke vraag van het Formulier op een aparte pagina willen stellen. De uiteindelijke website gaat gebruikt worden door boeren in Spanje, en op elke pagina komt een uitgebreide beschrijving van de vraag en hoe ze de beste keuze kunnen maken.
Maar we zouden dan kunnen denken aan 5-6 forms die uiteindelijk allemaal bij example.php uitkomen? Maar we moeten dan wel steeds de antwoorden tussentijds opslaan. Er worden dan geen tussen resultaten getoond (hoewel dat natuurlijk wel mooi zou zijn, maar is niet direct noodzakelijk, dan kom je trouwens alsnog terecht bij jou suggestie 1, hierboven).
Wat betreft de database, die is niet ingewikkeld. Er komen pakweg 50 soorten planten en bomen in, met 10 kolommen met eigenschappen. Die structuur staat al.
groet, Marco
Wellicht is via Javascript steeds maar 1 stap (van 1 formulier op 1 pagina) tonen.
Alsof je doorgaat, maar je doet niet meer dan een ander stukje van dat ene formulier op 1 pagina tonen.
Voordelen:
Maximaal 2 pagina's
1 Pagina met 1 formulier
Geen gezeur met onthouden, of erger: halverwege binnenkomen (dus op pagina 3 oid).
Nadelen: het vertrouwt op Javascript... Maar je kan het ook zo maken dat, wanneer Javascript uit staat (0,1% oid), het heel formulier gewoon in 1x wordt getoond.
Er zijn verschillende oplossingen denkbaar:
- iets met JavaScript, waarbij je divs (pagina-elementen) toont en verbergt, op grond van welke vraag je beantwoordt, je hoeft dan niets door te geven, je blijft continu op dezelfde pagina tot het moment dat je alle informatie verstuurt
- een oplossing met PHP, waarbij je alles opdeelt over verschillende scripts, ik denk dat je hiermee wel wat overhead introduceert, omdat de structuur over het algemeen hetzelfde zal zijn
- een oplossing met PHP, waarbij je één script gebruikt
Ik neem aan dat het in het belang van de invuller is dat alles waarheidsgetrouw wordt ingevuld en dat er niet (expres) geprobeerd zal worden om stappen over te slaan of foutieve of lege antwoorden in te vullen (dus dat er sprake is van "vals spel")? Natuurlijk moet het script wel veilig zijn, maar dit laatste bepaalt wel een beetje hoe robuust je navigatie moet zijn en hoe grondig de opgeslagen gegevens gevalideerd moeten worden.
Als je wilt kan ik wel een voorbeeldje geven van een enkel script waarin "aparte" pagina's worden aangeroepen waartussen je informatie verstuurt via formulieren en opslaat in een sessie.
Het zou inderdaad een goed idee zijn, om via een scrip en divs steeds nieuwe vragen te laten zien. Als je inderdaad een voorbeeldje kunt geven wat ik zelf makkelijk kan uitbreiden met meer vragen en antwoorden zou ik daar zeer mee geholpen zijn.
marco
Hoi Thomas, kun je me nog een voorbeeldje geven zoals je hierboven aangaf? Dan kan ik verder! Alvast bedankt.
questionnaire.php, of hoe je het ook wilt noemen.
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
<?php
define('DEBUG', true); // of we aan het ontwikkelen zijn
// DEBUG - melden en weergeven van fouten
if (DEBUG) {
error_reporting(E_ALL);
ini_set('display_errors', 'stdout');
}
// We definieren deze functionaliteit als een klasse.
// Deze klasse doet van zichzelf niets, maar aan het einde van deze code
// wordt een instantie van deze klasse aangeroepen en uitgevoerd.
// Aanname: ALLE data volgt een UTF-8 encodering.
class MyQuestionnaire
{
protected $action; // bevat de huidige uit te voeren actie
public function __construct() {
// Bepaal bij de creatie welke actie uitgevoerd dient te worden, deze actie wordt
// ingesteld middels de querystring parameter "action". Een bijbehorende (proctected)
// "action method" wordt uitgevoerd. Indien geen actie is opgegeven, wordt de default
// action method "actionDefault" aangeroepen.
$action = isset($_GET['action']) ? $_GET['action'] : 'default';
if (method_exists($this, 'action'.ucfirst($action))) {
$this->action = $action;
} else {
$this->action = 'default';
}
// De __construct methode kan ook gebruikt worden om andere zaken te initialiseren
// zoals sessie- en databasemanagement.
session_start();
// Het is wellicht handig om alle tussengelegen resultaten op te slaan in een sub-array
// van je sessie om deze gescheiden te houden van de rest van eventuele sessie-data, dit
// doen we bijvoorbeeld in $_SESSION['questionnaire'].
if (empty($_SESSION['questionnaire'])) {
$_SESSION['questionnaire'] = array(
'data' => array(), // de data uit de verschillende stappen
);
}
} // function __construct
// Voer de berekende action method uit.
public function execute() {
$action = 'action'.ucfirst($this->action);
$this->$action();
}
// Hulpfunctie voor het escapen van (HTML) output.
protected function escape($in) {
return htmlspecialchars($in, ENT_QUOTES, 'UTF-8');
} // function escape
// Hulpfunctie voor redirect.
protected function redirect($link) {
header('HTTP/1.1 303 See Other');
header('Location: '.$link);
exit;
} // function redirect
// Omdat we vaak een complete HTML-pagina construeren en hier herhalende delen in zitten
// introduceren we twee (interne) hulpfuncties: __header() en __footer(). Hierin zitten
// (you guessed it) respectievelijk de standaard HTML header en de standaard HTML footer.
// De __header() methode bevat een optionele parameter $title die je kunt gebruiken om
// een documenttitel in te stellen.
protected function __header($title='') {
header('Content-Type: text/html; charset=UTF-8');
// Noot: we springen hier expres niet in zodat er geen spaties/linebreaks voor het begin van het document staan.
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?php echo $this->escape($title) ?></title>
<!-- minimale stylesheet -->
<link rel="stylesheet" type="text/css" href="questionnaire.css">
<!-- hier kun je eventueel nog meer stylesheets of JavaScript invoegen die je in de individuele "pagina's" gebruikt -->
</head>
<body><?php
// DEBUG - let op; inhoud is mogelijk niet betrouwbaar (bevat user input).
if (DEBUG) {
echo '<pre>'.print_r($_SESSION, true).'</pre>';
}
} // function __header
// Standaard HTML footer
protected function __footer() {
?></body>
</html><?php
} // function __footer
// We hebben nu alle stukjes om een volledig (en) kloppend HTML document te bouwen.
// Laten we beginnen met de landingspagina van deze class: actionDefault. Alle action methods
// zijn van "buitenaf" op te vragen. De actionDefault methode is benaderbaar via "?action=default"
// of door simpelweg het aanroepen van dit script omdat het de default is.
// Wat ons dus nog rest is het bouwen van de formulierstappen en het tussentijds verwerken van de
// data, om uiteindelijk uit te monden in een action method die die uiteindelijke query bouwt en
// uitvoert.
protected function actionDefault() {
// DEBUG - voor resetten sessie data
if (DEBUG) {
$_SESSION = array();
}
// Alle pagina's (action methods) zullen de volgende opbouw hebben: header - content - footer.
// Header en footer zijn min of meer standaard, de content wordt bepaald door / is specfiek voor
// de action method.
$this->__header('Hello World');
?><div>
<h1>Hello world</h1>
<p>Dit is de landingspagina.</p>
<p>Hier zou je wat uitleg kunnen geven over het verloop van de "questionnaire".</p>
<p>Middels <a href="?action=step1">deze link</a> kun je naar de eerste stap navigeren.</p>
</div><?php
$this->__footer();
} // function actionDefault
// De volgende action method bevat de eerste stap van je questionnaire, hierin zit een formulier wat
// geinitialiseerd kan worden met eerder ingevulde data.
protected function actionStep1() {
$this->__header('Stap 1');
?><div>
<h1>De eerste stap</h1>
<p>Hier eventueel wat uitleg bij de vraag.</p><?php
// Ging er iets mis bij verwerking (zie hieronder)?
if (isset($_GET['errors'])) {
?><div class="error">
<p>Er ging iets mis bij de verwerking van deze stap, controleer uw invoer.</p>
</div><?php
}
?><div class="form">
<form action="?action=step1Process" method="post" accept-charset="UTF-8">
<p>
<label for="step_1_select">Omschrijving</label>
<select name="step_1_select" id="step_1_select">
<option value="">- selecteer -</option><?php
// Druk hier een lijst van waarden => namen af waarbij je
// tegelijkertijd controleert of er eerder iets ingevuld was.
if (array_key_exists(1, $_SESSION['questionnaire']['data'])) {
$selectedValue = $_SESSION['questionnaire']['data'][1];
} else {
$selectedValue = false;
}
// Het makkelijkste lijkt mij om alle "select data" op 1 plek op te slaan,
// we introduceren hiervoor een interne hulpmethode __getStepData.
foreach ($this->__getStepData(1) as $k => $v) {
$selected = ($k == $selectedValue ? ' selected="selected"' : '');
?><option value="<?php echo $this->escape($k) ?>"<?php echo $selected ?>><?php echo $this->escape($v) ?></option><?php
}
?></select>
</p>
<div>
<button type="submit">verder</button>
</div>
</form>
</div>
</div><?php
$this->__footer();
}
// Hier verwerken we de invoer van het formulier uit stap 1. Omdat deze actie geen output produceert,
// hoeven we ook geen __header of __footer te gebruiken.
protected function actionStep1Process() {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// We voeren hier verder geen specifieke controles uit of de waarde klopt, dit kan aan het einde
// ook. Dit houdt wel in dat we de data in $_SESSION['questionnaire'] niet 100% kunnen vertrouwen
// dus hier zullen we rekening mee moeten houden.
if (!empty($_POST['step_1_select'])) {
// De $_POST waarde bestaat tenminste, dus voor nu gaan we er vanuit dat alles ok is.
// We slaan de waarde op in het data-subarray op index 1 (correspondeert met stap 1).
$_SESSION['questionnaire']['data'][1] = $_POST['step_1_select'];
// We zijn klaar, door naar stap 2.
$this->redirect('?action=step2');
}
}
// Deze actie werd niet aangeroepen via POST, $_POST['step_1_select'] bestond niet of was leeg,
// keer terug naar de bijbehorende stap. Hierbij is het ook handig om aan te geven dat er iets mis
// ging, we sturen de extra indicatie "errors=1" mee.
$this->redirect('?action=step1&errors=1');
}
protected function actionStep2() {
// Dit is weer een volledige pagina, dus gebruik header en footer.
$this->__header('Step 2');
// Dit zou je grotendeels kunnen copy-pasten van step1.
// Zorg wel dat je je namen en actions aanpast zodat je e.e.a. een beetje consistent houdt.
?><div>
<h1>Stap twee</h1>
<p>Hier eventueel wat uitleg bij de vraag.</p><?php
if (isset($_GET['errors'])) {
?><div class="error">
<p>Er ging iets mis bij de verwerking van deze stap, controleer uw invoer.</p>
</div><?php
}
?><div class="form">
<form action="?action=step2Process" method="post" accept-charset="UTF-8">
<p>
<label for="step_2_select">Omschrijving</label>
<select name="step_2_select" id="step_1_select">
<option value="">- selecteer -</option><?php
if (array_key_exists(2, $_SESSION['questionnaire']['data'])) {
$selectedValue = $_SESSION['questionnaire']['data'][2];
} else {
$selectedValue = false;
}
foreach ($this->__getStepData(2) as $k => $v) {
$selected = ($k == $selectedValue ? ' selected="selected"' : '');
?><option value="<?php echo $this->escape($k) ?>"<?php echo $selected ?>><?php echo $this->escape($v) ?></option><?php
}
?></select>
</p>
<div>
<button type="submit">verder</button>
</div>
</form>
</div>
</div><?php
$this->__footer();
}
protected function actionStep2Process() {
// Dit zou je grotendeels kunnen copy-pasten van step1Process.
// Zorg wel dat je je namen en actions aanpast zodat je e.e.a. een beetje consistent houdt.
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (!empty($_POST['step_2_select'])) {
$_SESSION['questionnaire']['data'][2] = $_POST['step_2_select'];
// Je kunt zo zoveel stappen inbouwen als je wilt, uiteindelijk wordt je naar een
// overzichtspagina gestuurd: actionSummary.
$this->redirect('?action=summary');
}
}
$this->redirect('?action=step2&errors=1');
}
// Overzichtspagina van ingevulde gegevens.
protected function actionSummary() {
$this->__header('Overzicht ingevulde gegevens');
?><div>
<h1>Overzicht ingevulde gegevens</h1>
<p>Hier kun je nog een omschrijving geven wat te doen als je iets aan wilt passen.</p>
<table border="0" cellspacing="0" cellpadding="5"><?php
foreach ($this->__getStepDescriptions() as $step => $description) {
?><tr>
<td><?php echo $this->escape($description) ?></td>
<td style="text-align: right;"><?php
$stepData = $this->__getStepData($step);
if (
array_key_exists($step, $_SESSION['questionnaire']['data']) &&
array_key_exists($_SESSION['questionnaire']['data'][$step], $stepData)
) {
echo $this->escape($stepData[$_SESSION['questionnaire']['data'][$step]]);
} else {
?>ongeldige waarde :(<?php
}
?></td>
</tr><?php
}
?></table>
<p><a href="?action=processData">Data verwerken!</a></p>
</div><?php
$this->__footer();
}
// Hier zou je nog last minute checks kunnen uitvoeren op $_SESSION['questionnaire']['data']
// voordat je je query gaat bouwen. Ook zou je hier een "tussenstap zonder output" van kunnen maken
// alvorens je iemand doorstuurt naar een resultaat- of bedankpagina, tis maar net wat je wilt.
protected function actionProcessData() {
// ... en wat je hier verder wilt doen met je data ...
?>processing...<?php
}
protected function __getStepData($step) {
$stepData = array(
// Data uit stap 1.
1 => array(
'9' => '< 10mm',
'10' => '10mm',
'20' => '20mm',
'30' => '30mm',
'40' => '40mm',
'50' => '50mm',
'51' => '> 51mm',
),
// Data uit stap 2.
2 => array(
'een' => 'een',
'twee' => 'twee',
'drie' => 'drie',
'vier' => 'vier',
),
// Et cetera
);
if (array_key_exists($step, $stepData)) {
return $stepData[$step];
} else {
die('[fatal] unable to fetch data of current step');
}
} // function __getStepData
// Bevat een lijst van korte omschrijvingen van wat je bij elke stap hebt ingevuld
protected function __getStepDescriptions() {
return array(
1 => 'Dit is de omschrijving bij stap 1',
2 => 'Korte omschrijving bij stap 2',
// Et cetera
);
} // function __getStepDescriptions
} // class MyQuestionnaire
// Maak een instantie van de MyQuestionnaire klasse aan en voer deze uit.
$c = new MyQuestionnaire();
$c->execute();
?>
define('DEBUG', true); // of we aan het ontwikkelen zijn
// DEBUG - melden en weergeven van fouten
if (DEBUG) {
error_reporting(E_ALL);
ini_set('display_errors', 'stdout');
}
// We definieren deze functionaliteit als een klasse.
// Deze klasse doet van zichzelf niets, maar aan het einde van deze code
// wordt een instantie van deze klasse aangeroepen en uitgevoerd.
// Aanname: ALLE data volgt een UTF-8 encodering.
class MyQuestionnaire
{
protected $action; // bevat de huidige uit te voeren actie
public function __construct() {
// Bepaal bij de creatie welke actie uitgevoerd dient te worden, deze actie wordt
// ingesteld middels de querystring parameter "action". Een bijbehorende (proctected)
// "action method" wordt uitgevoerd. Indien geen actie is opgegeven, wordt de default
// action method "actionDefault" aangeroepen.
$action = isset($_GET['action']) ? $_GET['action'] : 'default';
if (method_exists($this, 'action'.ucfirst($action))) {
$this->action = $action;
} else {
$this->action = 'default';
}
// De __construct methode kan ook gebruikt worden om andere zaken te initialiseren
// zoals sessie- en databasemanagement.
session_start();
// Het is wellicht handig om alle tussengelegen resultaten op te slaan in een sub-array
// van je sessie om deze gescheiden te houden van de rest van eventuele sessie-data, dit
// doen we bijvoorbeeld in $_SESSION['questionnaire'].
if (empty($_SESSION['questionnaire'])) {
$_SESSION['questionnaire'] = array(
'data' => array(), // de data uit de verschillende stappen
);
}
} // function __construct
// Voer de berekende action method uit.
public function execute() {
$action = 'action'.ucfirst($this->action);
$this->$action();
}
// Hulpfunctie voor het escapen van (HTML) output.
protected function escape($in) {
return htmlspecialchars($in, ENT_QUOTES, 'UTF-8');
} // function escape
// Hulpfunctie voor redirect.
protected function redirect($link) {
header('HTTP/1.1 303 See Other');
header('Location: '.$link);
exit;
} // function redirect
// Omdat we vaak een complete HTML-pagina construeren en hier herhalende delen in zitten
// introduceren we twee (interne) hulpfuncties: __header() en __footer(). Hierin zitten
// (you guessed it) respectievelijk de standaard HTML header en de standaard HTML footer.
// De __header() methode bevat een optionele parameter $title die je kunt gebruiken om
// een documenttitel in te stellen.
protected function __header($title='') {
header('Content-Type: text/html; charset=UTF-8');
// Noot: we springen hier expres niet in zodat er geen spaties/linebreaks voor het begin van het document staan.
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?php echo $this->escape($title) ?></title>
<!-- minimale stylesheet -->
<link rel="stylesheet" type="text/css" href="questionnaire.css">
<!-- hier kun je eventueel nog meer stylesheets of JavaScript invoegen die je in de individuele "pagina's" gebruikt -->
</head>
<body><?php
// DEBUG - let op; inhoud is mogelijk niet betrouwbaar (bevat user input).
if (DEBUG) {
echo '<pre>'.print_r($_SESSION, true).'</pre>';
}
} // function __header
// Standaard HTML footer
protected function __footer() {
?></body>
</html><?php
} // function __footer
// We hebben nu alle stukjes om een volledig (en) kloppend HTML document te bouwen.
// Laten we beginnen met de landingspagina van deze class: actionDefault. Alle action methods
// zijn van "buitenaf" op te vragen. De actionDefault methode is benaderbaar via "?action=default"
// of door simpelweg het aanroepen van dit script omdat het de default is.
// Wat ons dus nog rest is het bouwen van de formulierstappen en het tussentijds verwerken van de
// data, om uiteindelijk uit te monden in een action method die die uiteindelijke query bouwt en
// uitvoert.
protected function actionDefault() {
// DEBUG - voor resetten sessie data
if (DEBUG) {
$_SESSION = array();
}
// Alle pagina's (action methods) zullen de volgende opbouw hebben: header - content - footer.
// Header en footer zijn min of meer standaard, de content wordt bepaald door / is specfiek voor
// de action method.
$this->__header('Hello World');
?><div>
<h1>Hello world</h1>
<p>Dit is de landingspagina.</p>
<p>Hier zou je wat uitleg kunnen geven over het verloop van de "questionnaire".</p>
<p>Middels <a href="?action=step1">deze link</a> kun je naar de eerste stap navigeren.</p>
</div><?php
$this->__footer();
} // function actionDefault
// De volgende action method bevat de eerste stap van je questionnaire, hierin zit een formulier wat
// geinitialiseerd kan worden met eerder ingevulde data.
protected function actionStep1() {
$this->__header('Stap 1');
?><div>
<h1>De eerste stap</h1>
<p>Hier eventueel wat uitleg bij de vraag.</p><?php
// Ging er iets mis bij verwerking (zie hieronder)?
if (isset($_GET['errors'])) {
?><div class="error">
<p>Er ging iets mis bij de verwerking van deze stap, controleer uw invoer.</p>
</div><?php
}
?><div class="form">
<form action="?action=step1Process" method="post" accept-charset="UTF-8">
<p>
<label for="step_1_select">Omschrijving</label>
<select name="step_1_select" id="step_1_select">
<option value="">- selecteer -</option><?php
// Druk hier een lijst van waarden => namen af waarbij je
// tegelijkertijd controleert of er eerder iets ingevuld was.
if (array_key_exists(1, $_SESSION['questionnaire']['data'])) {
$selectedValue = $_SESSION['questionnaire']['data'][1];
} else {
$selectedValue = false;
}
// Het makkelijkste lijkt mij om alle "select data" op 1 plek op te slaan,
// we introduceren hiervoor een interne hulpmethode __getStepData.
foreach ($this->__getStepData(1) as $k => $v) {
$selected = ($k == $selectedValue ? ' selected="selected"' : '');
?><option value="<?php echo $this->escape($k) ?>"<?php echo $selected ?>><?php echo $this->escape($v) ?></option><?php
}
?></select>
</p>
<div>
<button type="submit">verder</button>
</div>
</form>
</div>
</div><?php
$this->__footer();
}
// Hier verwerken we de invoer van het formulier uit stap 1. Omdat deze actie geen output produceert,
// hoeven we ook geen __header of __footer te gebruiken.
protected function actionStep1Process() {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// We voeren hier verder geen specifieke controles uit of de waarde klopt, dit kan aan het einde
// ook. Dit houdt wel in dat we de data in $_SESSION['questionnaire'] niet 100% kunnen vertrouwen
// dus hier zullen we rekening mee moeten houden.
if (!empty($_POST['step_1_select'])) {
// De $_POST waarde bestaat tenminste, dus voor nu gaan we er vanuit dat alles ok is.
// We slaan de waarde op in het data-subarray op index 1 (correspondeert met stap 1).
$_SESSION['questionnaire']['data'][1] = $_POST['step_1_select'];
// We zijn klaar, door naar stap 2.
$this->redirect('?action=step2');
}
}
// Deze actie werd niet aangeroepen via POST, $_POST['step_1_select'] bestond niet of was leeg,
// keer terug naar de bijbehorende stap. Hierbij is het ook handig om aan te geven dat er iets mis
// ging, we sturen de extra indicatie "errors=1" mee.
$this->redirect('?action=step1&errors=1');
}
protected function actionStep2() {
// Dit is weer een volledige pagina, dus gebruik header en footer.
$this->__header('Step 2');
// Dit zou je grotendeels kunnen copy-pasten van step1.
// Zorg wel dat je je namen en actions aanpast zodat je e.e.a. een beetje consistent houdt.
?><div>
<h1>Stap twee</h1>
<p>Hier eventueel wat uitleg bij de vraag.</p><?php
if (isset($_GET['errors'])) {
?><div class="error">
<p>Er ging iets mis bij de verwerking van deze stap, controleer uw invoer.</p>
</div><?php
}
?><div class="form">
<form action="?action=step2Process" method="post" accept-charset="UTF-8">
<p>
<label for="step_2_select">Omschrijving</label>
<select name="step_2_select" id="step_1_select">
<option value="">- selecteer -</option><?php
if (array_key_exists(2, $_SESSION['questionnaire']['data'])) {
$selectedValue = $_SESSION['questionnaire']['data'][2];
} else {
$selectedValue = false;
}
foreach ($this->__getStepData(2) as $k => $v) {
$selected = ($k == $selectedValue ? ' selected="selected"' : '');
?><option value="<?php echo $this->escape($k) ?>"<?php echo $selected ?>><?php echo $this->escape($v) ?></option><?php
}
?></select>
</p>
<div>
<button type="submit">verder</button>
</div>
</form>
</div>
</div><?php
$this->__footer();
}
protected function actionStep2Process() {
// Dit zou je grotendeels kunnen copy-pasten van step1Process.
// Zorg wel dat je je namen en actions aanpast zodat je e.e.a. een beetje consistent houdt.
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (!empty($_POST['step_2_select'])) {
$_SESSION['questionnaire']['data'][2] = $_POST['step_2_select'];
// Je kunt zo zoveel stappen inbouwen als je wilt, uiteindelijk wordt je naar een
// overzichtspagina gestuurd: actionSummary.
$this->redirect('?action=summary');
}
}
$this->redirect('?action=step2&errors=1');
}
// Overzichtspagina van ingevulde gegevens.
protected function actionSummary() {
$this->__header('Overzicht ingevulde gegevens');
?><div>
<h1>Overzicht ingevulde gegevens</h1>
<p>Hier kun je nog een omschrijving geven wat te doen als je iets aan wilt passen.</p>
<table border="0" cellspacing="0" cellpadding="5"><?php
foreach ($this->__getStepDescriptions() as $step => $description) {
?><tr>
<td><?php echo $this->escape($description) ?></td>
<td style="text-align: right;"><?php
$stepData = $this->__getStepData($step);
if (
array_key_exists($step, $_SESSION['questionnaire']['data']) &&
array_key_exists($_SESSION['questionnaire']['data'][$step], $stepData)
) {
echo $this->escape($stepData[$_SESSION['questionnaire']['data'][$step]]);
} else {
?>ongeldige waarde :(<?php
}
?></td>
</tr><?php
}
?></table>
<p><a href="?action=processData">Data verwerken!</a></p>
</div><?php
$this->__footer();
}
// Hier zou je nog last minute checks kunnen uitvoeren op $_SESSION['questionnaire']['data']
// voordat je je query gaat bouwen. Ook zou je hier een "tussenstap zonder output" van kunnen maken
// alvorens je iemand doorstuurt naar een resultaat- of bedankpagina, tis maar net wat je wilt.
protected function actionProcessData() {
// ... en wat je hier verder wilt doen met je data ...
?>processing...<?php
}
protected function __getStepData($step) {
$stepData = array(
// Data uit stap 1.
1 => array(
'9' => '< 10mm',
'10' => '10mm',
'20' => '20mm',
'30' => '30mm',
'40' => '40mm',
'50' => '50mm',
'51' => '> 51mm',
),
// Data uit stap 2.
2 => array(
'een' => 'een',
'twee' => 'twee',
'drie' => 'drie',
'vier' => 'vier',
),
// Et cetera
);
if (array_key_exists($step, $stepData)) {
return $stepData[$step];
} else {
die('[fatal] unable to fetch data of current step');
}
} // function __getStepData
// Bevat een lijst van korte omschrijvingen van wat je bij elke stap hebt ingevuld
protected function __getStepDescriptions() {
return array(
1 => 'Dit is de omschrijving bij stap 1',
2 => 'Korte omschrijving bij stap 2',
// Et cetera
);
} // function __getStepDescriptions
} // class MyQuestionnaire
// Maak een instantie van de MyQuestionnaire klasse aan en voer deze uit.
$c = new MyQuestionnaire();
$c->execute();
?>
questionnaire.css (minimale opmaak)