Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
98 - 1
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><title>5.23. Example - Complete Web Form with Plot</title><link rel="stylesheet" type="text/css" href="phplotdoc.css" /><meta name="generator" content="DocBook XSL Stylesheets V1.78.1" /><link rel="home" href="index.html" title="PHPlot Reference Manual" /><link rel="up" href="examples.html" title="Chapter 5. PHPlot Examples" /><link rel="prev" href="ex-annotate.html" title="5.22. Example - Annotating a Plot Using a Callback" /><link rel="next" href="ex-truecolor-histogram.html" title="5.24. Example - Using Truecolor To Make a Histogram" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">5.23. Example - Complete Web Form with Plot</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ex-annotate.html">Prev</a> </td><th width="60%" align="center">Chapter 5. PHPlot Examples</th><td width="20%" align="right"> <a accesskey="n" href="ex-truecolor-histogram.html">Next</a></td></tr></table><hr /></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="ex-webform"></a>5.23. Example - Complete Web Form with Plot</h2></div></div></div><p>
3
This section shows a complete mini-application which uses PHPlot to display
4
a graph based on user input through a web form. The purpose of this example
5
is to illustrate form handling and parameter passing from a form-handling
6
script to an image-generating script.
7
</p><p>
8
Here a screen-shot of the application, as seen from a web browser.
9
(The bottom section with the graph will only be shown after the form is
10
submitted.)
11
</p><div class="example"><a id="example-webform"></a><p class="title"><strong>Example 5.23. Screen Shot of Web Form with Plot</strong></p><div class="example-contents"><div class="informalfigure"><div class="mediaobject"><img src="images/webform.png" alt="Screen Shot of Web Form with Plot" /></div></div></div></div><br class="example-break" /><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
12
Unlike the other examples in this chapter, the web form example consists of
13
two scripts, and only works with a web server. The two scripts are
14
shown in their entirety, but are broken up into blocks, with comments
15
preceding each block, for presentation purposes.
16
  </p></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a id="ex-webform-mainpage"></a>5.23.1. Web Form Main Script</h3></div></div></div><p>
17
This section presents the main script <code class="filename">webform.php</code>
18
which displays the web form and handles form submission.
19
This script does not use PHPlot. When first accessed from a browser (with
20
no parameters), it displays only the form and descriptive text. When the
21
form is submitted, the same script runs again.  This time, the script receives
22
form parameters, and displays the graph in addition to the form. To display
23
the graph, the script generates an image (img) tag which references the
24
second script (which is described in the next section).
25
That second script actually generates the plot image.
26
</p><p>
27
The script begins with a descriptive comment, and then defines constants
28
for the name of the other script, the image size, and the parameter defaults.
29
</p><pre class="programlisting">&lt;?php
30
/*  PHPlot web form example
31
 
32
  Parameter names and parameter array keys:
33
    'deposit' = Amount deposited per month.
34
    'intrate' = Interest rate as a percentage (e.g. 4 means 4% or 0.04)
35
*/
36
 
37
# Name of script which generates the actual plot:
38
define('GRAPH_SCRIPT', 'webform_img.php');
39
# Image size. It isn't really necessary that this script know this image
40
# size, but it improves page rendering.
41
define('GRAPH_WIDTH', 600);
42
define('GRAPH_HEIGHT', 400);
43
 
44
# Default values for the form parameters:
45
$param = array('deposit' =&gt; 100.00, 'intrate' =&gt; 4.0);
46
</pre><p>
47
</p><p>
48
Function <code class="function">build_url()</code>
49
is a general-purpose function used to generate a URL to a script with
50
parameters. The parameters are in a PHP associative array. The return value
51
is a relative or complete URL which might look like this:
52
<code class="literal">webform_img.php?deposit=100&amp;intrate=4.0&amp;h=400&amp;w=600</code>.
53
 
54
</p><pre class="programlisting"># Build a URL with escaped parameters:
55
#   $url - The part of the URL up through the script name
56
#   $param - Associative array of parameter names and values
57
# Returns a URL with parameters. Note this must be HTML-escaped if it is
58
# used e.g. as an href value. (The &amp; between parameters is not pre-escaped.)
59
function build_url($url, $param)
60
{
61
    $sep = '?';  // Separator between URL script name and first parameter
62
    foreach ($param as $name =&gt; $value) {
63
        $url .= $sep . urlencode($name) . '=' . urlencode($value);
64
        $sep = '&amp;';   // Separator between subsequent parameters
65
    }
66
    return $url;
67
}
68
</pre><p>
69
</p><p>
70
The function <code class="function">begin_page()</code>
71
creates the HTML at the top of the page.
72
In a real application, this might include a page header.
73
</p><pre class="programlisting"># Output the start of the HTML page:
74
function begin_page($title)
75
{
76
    echo &lt;&lt;&lt;END
77
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
78
                      "http://www.w3.org/TR/html4/loose.dtd"&gt;
79
&lt;html&gt;
80
&lt;head&gt;
81
&lt;title&gt;$title&lt;/title&gt;
82
&lt;/head&gt;
83
&lt;body&gt;
84
&lt;h1&gt;$title&lt;/h1&gt;
85
 
86
END;
87
}
88
</pre><p>
89
</p><p>
90
The function <code class="function">end_page()</code>
91
creates the HTML at the end of the page.
92
In a real application, this might include a page footer.
93
</p><pre class="programlisting"># Output the bottom of the HTML page:
94
function end_page()
95
{
96
    echo &lt;&lt;&lt;END
97
&lt;/body&gt;
98
&lt;/html&gt;
99
 
100
END;
101
}
102
</pre><p>
103
</p><p>
104
The function <code class="function">show_descriptive_text()</code>
105
produces HTML text which describes the form.
106
This will go above the form on the web page.
107
</p><pre class="programlisting"># Output text which describes the form.
108
function show_descriptive_text()
109
{
110
    echo &lt;&lt;&lt;END
111
&lt;p&gt;
112
This page calculates the balance over time in an interest-earning savings
113
account when fixed monthly deposits are made and there are no withdrawals.
114
&lt;/p&gt;
115
&lt;p&gt;
116
Fill in the values below and click on the button to display a
117
graph of the account balance over time.
118
&lt;/p&gt;
119
 
120
END;
121
}
122
</pre><p>
123
</p><p>
124
The function <code class="function">show_form()</code>
125
outputs the HTML form. This includes entry boxes for the two
126
parameters and a submit button. The form action URL is this script
127
itself, so we use the SCRIPT_NAME value to self-reference the script.
128
</p><pre class="programlisting"># Output the web form.
129
# The form resubmits to this same script for processing.
130
# The $param array contains default values for the form.
131
# The values have already been validated as containing numbers and
132
# do not need escaping for HTML.
133
function show_form($param)
134
{
135
    $action = htmlspecialchars($_SERVER['SCRIPT_NAME']);
136
 
137
    echo &lt;&lt;&lt;END
138
&lt;form name="f1" id="f1" method="get" action="$action"&gt;
139
&lt;table cellpadding="5" summary="Entry form for balance calculation"&gt;
140
&lt;tr&gt;
141
  &lt;td align="right"&gt;&lt;label for="deposit"&gt;Monthly Deposit Amount:&lt;/label&gt;&lt;/td&gt;
142
  &lt;td&gt;&lt;input type="text" size="10" name="deposit" id="deposit"
143
       value="{$param['deposit']}"&gt;
144
&lt;/tr&gt;
145
&lt;tr&gt;
146
  &lt;td align="right"&gt;&lt;label for="intrate"&gt;Interest Rate:&lt;/label&gt;&lt;/td&gt;
147
  &lt;td&gt;&lt;input type="text" size="10" name="intrate" id="intrate"
148
      value="{$param['intrate']}"&gt;%
149
&lt;/tr&gt;
150
&lt;tr&gt;
151
  &lt;td colspan="2" align="center"&gt;&lt;input type="submit" value="Display Graph"&gt;&lt;/td&gt;
152
&lt;/tr&gt;
153
&lt;/table&gt;
154
&lt;/form&gt;
155
 
156
END;
157
}
158
</pre><p>
159
</p><p>
160
The function <code class="function">check_form_params()</code>
161
performs the important task of validating the parameters received from a
162
form submission. Each parameter is checked for presence and syntax, then
163
converted to the appropriate PHP type. This function is also used to
164
determine if a plot should be displayed. A plot is displayed only if valid
165
form parameters were received.
166
</p><pre class="programlisting"># Check for parameters supplied to this web page.
167
# If there are valid parameters, store them in the array argument and
168
# return True.
169
# If there are no parameters, or the parameters are not valid, return False.
170
function check_form_params(&amp;$param)
171
{
172
    $valid = True;
173
 
174
    if (!isset($_GET['deposit']) || !is_numeric($_GET['deposit'])
175
           || ($deposit = floatval($_GET['deposit'])) &lt; 0)
176
        $valid = False;
177
 
178
    if (!isset($_GET['intrate']) || !is_numeric($_GET['intrate'])
179
           || ($intrate = floatval($_GET['intrate'])) &lt; 0 || $intrate &gt; 100)
180
        $valid = False;
181
 
182
    if ($valid) $param = compact('deposit', 'intrate');
183
    return $valid;
184
}
185
</pre><p>
186
</p><p>
187
The function <code class="function">show_graph()</code>
188
produces the HTML which will will invoke the second script to produce the
189
graph. This is an image (img) tag which references the second script,
190
including the parameters the script needs to generate the plot. This is one
191
of several ways to pass parameters from the form handling script and the
192
image generating script. The other way is using session variables. Using
193
URL parameters is simpler, especially when there are only a few parameters.
194
Note the HTML also specifies the width and height of the plot image. This
195
is not necessary, however it helps the browser lay out the page without
196
waiting for the image script to complete.
197
</p><pre class="programlisting"># Display a graph.
198
# The param array contains the validated values: deposit and intrate.
199
# This function creates the portion of the page that contains the
200
# graph, but the actual graph is generated by the $GRAPH_SCRIPT script.
201
function show_graph($param)
202
{
203
    # Include the width and height as parameters:
204
    $param['w'] = GRAPH_WIDTH;
205
    $param['h'] = GRAPH_HEIGHT;
206
    # URL to the graphing script, with parameters, escaped for HTML:
207
    $img_url = htmlspecialchars(build_url(GRAPH_SCRIPT, $param));
208
 
209
    echo &lt;&lt;&lt;END
210
&lt;hr&gt;
211
&lt;p&gt;
212
Graph showing the account balance over time, with monthly deposits of
213
{$param['deposit']} and earning annual interest of {$param['intrate']}%:
214
 
215
&lt;p&gt;&lt;img src="$img_url" width="{$param['w']}" height="{$param['h']}"
216
    alt="Account balance graph."&gt;
217
 
218
END;
219
}
220
</pre><p>
221
</p><p>
222
Finally, with all the functions defined, the main code is just a few lines.
223
</p><pre class="programlisting"># This is the main processing code.
224
begin_page("PHPlot: Example of a Web Form and Plot");
225
$params_supplied = check_form_params($param);
226
show_descriptive_text();
227
show_form($param);
228
if ($params_supplied) show_graph($param);
229
end_page();
230
</pre><p>
231
</p></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a id="ex-webform-imgpage"></a>5.23.2. Web Form Image Script</h3></div></div></div><p>
232
This section presents the second script <code class="filename">webform_img.php</code>,
233
which generates the plot using PHPlot. The URL to this script, along with
234
its parameters, is embedded in the web page produced by the main script in
235
<a class="xref" href="ex-webform.html#ex-webform-mainpage" title="5.23.1. Web Form Main Script">Section 5.23.1, &#8220;Web Form Main Script&#8221;</a>.
236
When the user's browser asks the web server for the image,
237
this second script runs and generates the plot.
238
</p><p>
239
The script begins with a descriptive comment and then includes the PHPlot
240
source.
241
</p><pre class="programlisting">&lt;?php
242
/*  PHPlot web form example - image generation
243
 
244
    This draws the plot image for webform.php
245
    It expects the following parameters:
246
       'deposit' = Amount deposited per month. Must be &gt;= 0.
247
       'intrate' = Interest rate as a percentage (e.g. 4 means 4% or 0.04)
248
       'w', 'h' = image width and height. (Must be between 100 and 5000)
249
*/
250
require_once 'phplot.php';
251
</pre><p>
252
</p><p>
253
Function <code class="function">check_form_params()</code>
254
validates the parameters supplied to the script. Two parameters are
255
required (intrate and deposit), and two are optional (h and w).
256
Even though the main script validated the parameters it passes to this
257
script, it is still necessary for the script to do its own validation. That
258
is because any accessible script can be called from any other web page, or
259
directly from a browser, with arbitrary parameters. (Error handling details
260
can be found below.)
261
 
262
</p><pre class="programlisting"># Check for parameters supplied to this web page.
263
# Parameters must be checked here, even though the calling script checked them,
264
# because there is nothing stopping someone from calling this script
265
# directly with arbitrary parameters.
266
# Parameter values are stored in the param[] array (valid or not).
267
# If the parameters are valid, return True, else return False.
268
function check_form_params(&amp;$param)
269
{
270
    $valid = True;
271
    $depost = 0;
272
    $intrate = 0;
273
 
274
    if (!isset($_GET['deposit']) || !is_numeric($_GET['deposit'])
275
           || ($deposit = floatval($_GET['deposit'])) &lt; 0)
276
        $valid = False;
277
 
278
    if (!isset($_GET['intrate']) || !is_numeric($_GET['intrate'])
279
           || ($intrate = floatval($_GET['intrate'])) &lt; 0 || $intrate &gt; 100)
280
        $valid = False;
281
 
282
    # If width and height are missing or invalid, just use something reasonable.
283
    if (empty($_GET['w']) || !is_numeric($_GET['w'])
284
           || ($w = intval($_GET['w'])) &lt; 100 || $w &gt; 5000)
285
        $w = 1024;
286
    if (empty($_GET['h']) || !is_numeric($_GET['h'])
287
           || ($h = intval($_GET['h'])) &lt; 100 || $h &gt; 5000)
288
        $h = 768;
289
 
290
    $param = compact('deposit', 'intrate', 'h', 'w');
291
    return $valid;
292
}
293
</pre><p>
294
</p><p>
295
Function <code class="function">calculate_data()</code>
296
computes the data for the plot. This uses the parameters supplied to
297
the script, and populates a data array suitable for PHPlot. Because the
298
script uses the data-data format, each row in the array consists of a label
299
(unused), X value (this is the month number), and 2 Y values (account
300
balance without interest, and account balance with interest).
301
 
302
</p><pre class="programlisting"># Calculate the data for the plot:
303
# This is only called if the parameters are valid.
304
# The calculation is simple. Each month, two points are calculated: the
305
# cumulative deposts (balance without interest), and balance with interest.
306
# At time 0 the balance is 0. At the start of each month, 1/12th of
307
# the annual interest rate is applied to the balance, and then the deposit
308
# is added, and that is reported as the balance.
309
# We calculate for a fixed amount of 120 months (10 years).
310
function calculate_data($param, &amp;$data)
311
{
312
    $deposit = $param['deposit'];
313
    $monthly_intrate = 1.0 + $param['intrate'] / 100.0 / 12.0;
314
    $balance_without_interest = 0;
315
    $balance = 0;
316
    $data = array(array('', 0, 0, 0)); // Starting point
317
    for ($month = 1; $month &lt;= 120; $month++) {
318
        $balance_without_interest += $deposit;
319
        $balance = $balance * $monthly_intrate + $deposit;
320
        $data[] = array('', $month, $balance_without_interest, $balance);
321
    }
322
}
323
</pre><p>
324
</p><p>
325
Function <code class="function">draw_graph()</code>
326
uses PHPlot to actually produce the graph. This function is similar to the
327
other code examples in this chapter. A PHPlot object is created, set up,
328
and then told to draw the plot. If the script parameters are not valid,
329
however, an attempt is made to draw the plot without a data array. This
330
results in an error, which PHPlot handles by creating an image file with an
331
error message. This method of error handling is used because the script
332
cannot return a textual error message since it is referenced from a web
333
page via an image (img) tag.  An alternative to this error handling is to
334
have the script return an HTTP error code such as error 500 (server error).
335
 
336
</p><pre class="programlisting"># Draw the graph:
337
function draw_graph($valid_params, $param, $data)
338
{
339
    extract($param);
340
 
341
    $plot = new PHPlot($w, $h);
342
    $plot-&gt;SetTitle('Savings with Interest');
343
    $plot-&gt;SetDataType('data-data');
344
    # Don't set data values if parameters were not valid. This will result
345
    # in PHPlot making an image with an error message.
346
    if ($valid_params) {
347
        $plot-&gt;SetDataValues($data);
348
    }
349
    $plot-&gt;SetLegend(array('Deposits only', 'Deposits with Interest'));
350
    $plot-&gt;SetLegendPixels(100, 50); // Move legend to upper left
351
    $plot-&gt;SetXTitle('Month');
352
    $plot-&gt;SetXTickIncrement(12);
353
    $plot-&gt;SetYTitle('Balance');
354
    $plot-&gt;SetYLabelType('data', 2);
355
    $plot-&gt;SetDrawXGrid(True);
356
    $plot-&gt;SetPlotType('lines');
357
    $plot-&gt;DrawGraph();
358
}
359
</pre><p>
360
</p><p>
361
Lastly, the main code for the image drawing script simply uses the above
362
functions.
363
</p><pre class="programlisting"># This is our main processing code.
364
$valid_params = check_form_params($param);
365
if ($valid_params) calculate_data($param, $data);
366
draw_graph($valid_params, $param, $data);
367
</pre><p>
368
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ex-annotate.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="examples.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ex-truecolor-histogram.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5.22. Example - Annotating a Plot Using a Callback </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 5.24. Example - Using Truecolor To Make a Histogram</td></tr></table></div></body></html>