File: IntroEmbperlObject.pod

package info (click to toggle)
libhtml-embperl-perl 1.3.6-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 2,596 kB
  • ctags: 1,190
  • sloc: ansic: 8,985; perl: 4,584; makefile: 83
file content (653 lines) | stat: -rw-r--r-- 24,087 bytes parent folder | download | duplicates (2)
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
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
=pod

=head1 NAME

Introduction to EmbperlObject

=head1 Contents

=over 4

=item	Introduction

=item	Getting Started

=item	Hello World

=item	Website-Global Variables

=item	Modular Files

=item	Modular File Inheritance

=item	Subroutines in EmbperlObject

=item	Conclusions

=back


=head1 Introduction

This tutorial is intended as a complement to the Embperl
documentation, not a replacement. We assume a basic familiarity with
Apache, mod_perl, and Perl, and the Embperl documentation. No prior
experience with EmbperlObject is assumed. The real purpose here is to
give a clearer idea of how EmbperlObject can help you to build large
websites. We give example code which could serve as a starting
template for your own projects, and hints about best practices which
have come out of real experience using the toolkit. As always, there
is more than one way to do it!

Since EmbperlObject is an evolving tool, it is likely that these
design patterns will evolve over time, and it is recommended that the
reader check back on the Embperl website for new versions from time to
time.

=head2 Motivation: Constructing Modular Websites

Embperl is a tool which allows you to embed Perl code in your HTML
documents. As such, it could by itself handle just about everything
you need to do with your website. So what is the point of
EmbperlObject? What does it give us that we don't already get with
basic Embperl?

As often seems to be the case with Perl, the answer has to do with
laziness. We would all like the task of building websites to be as
simple as possible. Anyone who has had to build a non-trivial site
using pure HTML will have quickly experienced the irritation of having
to copy-and-paste common code between documents - stuff like
navigation bars and table formats. We have probably all wished for an
"include" HTML tag. EmbperlObject goes a long way toward solving this
problem, without requiring the developer to resort to a lot of
customized Perl code. 

In a nutshell, EmbperlObject extends Embperl by enabling the
construction of websites in a modular, or object-oriented, fashion. I
am using the term "object-oriented" (OO) loosely here in the context
of inheritance and overloading, but you don't really need to know
anything about the OO paradigm to benefit from EmbperlObject. As you
will see from this short tutorial, it is possible to benefit from
using EmbperlObject with even a minimal knowledge of Perl. With just a
little instruction, in fact, pure HTML coders could use it to improve
their website architecture. Having said that, however, EmbperlObject
also provides for more advanced OO functionality, as we'll see later.


=head1 Getting Started

We'll assume here that you've successfully installed the latest
Apache, mod_perl and Embperl on your system. That should all be
relatively painless - problems normally occur when mixing older
versions of one tool with later versions of another. If you can, try
to download the latest versions of everything.

Having done all that, you might want to get going with configuring a
website. The first thing you need to do is set up the Apache config
file, usually called F<httpd.conf>.

=head2 Configuring F<httpd.conf>

The following is an example configuration for a single virtual host to
use EmbperlObject. There are, as usual, different ways to do this; but
if you are starting from scratch then it may be useful as a
template. It works with the later versions of Apache (1.3.6 and
up). Obviously, substitute your own IP address and domain name. 

	NameVirtualHost 10.1.1.3:80

	<VirtualHost 10.1.1.3:80>
		ServerName www.mydomain.com
		ServerAdmin webmaster@mydomain.com
		DocumentRoot /www/mydomain/com/htdocs
		DirectoryIndex index.html
		ErrorLog /www/mydomain/com/logs/error_log
		TransferLog /www/mydomain/com/logs/access_log
		PerlSetEnv EMBPERL_ESCMODE 0
		PerlSetEnv EMBPERL_OPTIONS 16
		PerlSetEnv EMBPERL_MAILHOST mail.mydomain.com
		PerlSetEnv EMBPERL_OBJECT_BASE base.epl
		PerlSetEnv EMBPERL_OBJECT_FALLBACK notfound.html
		PerlSetEnv EMBPERL_DEBUG 0
	</VirtualHost>

	# Set EmbPerl handler for main directory
	<Directory "/www/mydomain/com/htdocs/">
		<FilesMatch ".*\.html$">
			SetHandler  perl-script
			PerlHandler HTML::EmbperlObject
			Options     ExecCGI
		</FilesMatch>
		<FilesMatch ".*\.epl$">
			Order allow,deny
			Deny From all
		</FilesMatch>
	</Directory>

Note that you could change the .html file extension in the FilesMatch
directive; this is a personal preference issue. Personally, I use
.html for the main document files simply because I can edit files
using my favorite editor (emacs) and it will automatically load html
mode. Plus, this may be a minor thing - but using .html rather than a
special extension such as .epl adds a small amount of security to your
site since it provides no clue that the website is using Embperl. If
you're careful about the handling of error messages, then there never
be any indication of this. These days, the less the script kiddies can
deduce about you, the better...

Also, note that we have added a second FilesMatch directive, which
denies direct access to files with .epl extensions (again, you could
change this extension to another if you like, for example .obj). This
can be helpful for cases where you have Embperl files which contain
fragments of code or HTML; you want those files to be in the Apache
document tree, but you don't want people to be able to request them
directly - these files should only included directly into other
documents from within Embperl, using Execute(). This is really a
security issue. In the examples that follow, we name files which are
not intended to be requested directly with the .epl extension. Files
which are intended to be directly requested are named with the
standard .html extension. This can also be helpful when scanning a
directory, to see which are the main document files and which are the
modules. Finally, note that using the Apache FilesMatch directive to
restrict access does not prevent us from accessing these files (via
Execute) in Embperl.

So how does all this translate into a real website? Let's have a look
at the classic first example, Hello World.


=head1 Hello World

The file specified by the EMBPERL_OBJECT_BASE apache directive
(usually called F<base.epl>) is the lynchpin of how EmbperlObject
operates. Whenever a request comes in for any page on this website,
Emperl will look for F<base.epl> - first in the same directory as the
request, and if not found there then working up the directory tree to
the root dir of the website. For example, if a request comes in for
http://www.yoursite.com/foo/bar/file.html, then Embperl first looks
for F</foo/bar/base.epl>. If it doesn't find F<base.epl> there, then
it looks in F</foo/base.epl>. If no luck, then finally
F</base.epl>. (These paths are all relative to the document root for
the website). What is the point of all this?

In a nutshell, F<base.epl> is a template for giving a common
look-and-feel to your web pages. This file is what is actually used to
build the response to any request, regardless of the actual filename
which was asked for. So even if F<file.html> was requested,
F<base.epl> is what is actually executed. F<base.epl> is a normal
file containing valid HTML mixed with Perl code, but with a couple of
small differences. Here's a simple 'Hello World' example of this
approach:

F</base.epl>

	<HTML>
	<HEAD>
		<TITLE>Some title</TITLE>
	</HEAD>
	<BODY>
	Joe's Website
	<P>
	[- Execute ('*') -]
	</BODY>
	</HTML>

F</hello.html>

	Hello world!

Now, if the file http://www.yoursite.com/hello.html is requested, then
F<base.epl> is what will actually get executed initially. So where
does the file F<hello.html> get into the picture? Well, the key is the
'*' parameter in the call to Execute(). '*' is a special filename,
only used in F<base.epl>. It means, literally, "the filename which
was actually requested".

What you will see if you try this example is something like this:

	Joe's Website

	Hello world!

As you can see here, the text "Joe's Website" is from F<base.epl> and
the "Hello world!" is from F<hello.html>.

This architecture also means that only F<base.epl> has to have the
boilerplate code which every HTML file normally needs to contain -
namely the <HTML> <BODY>, </HTML> and so on. Since the '*' file is
simply inserted into the code, all it needs to contain is the actual
content which is specific to that file. Nothing else is necessary,
because F<base.epl> has all the standard HTML trappings. Of course,
you'll probably have more interesting content, but you get the point.


=head1 Website-Global Variables

Now let's look at a slightly more interesting example. When you create
Perl variables in Embperl usually, their scope is the current file;
so, they are effectively "local" to that file. When you come to split
your website up into modules, however, it quickly becomes apparent
that it is very useful to have variables which are global to the
website, i.e. shared between multiple files.

To achieve this, EmbperlObject has special object which is
automatically passed to every page as it is executed. This object is
usually referred to as the "Request" object, because we get one of
these objects created for every document request that the web server
receives. This object is passed in on the stack, so you can retrieve
it using the Perl "shift" statement. This object is also automatically
destroyed after the request, so the Request object cannot be used to
store data between requests. The idea is that you can store variables
which are local to the current request, and shared between all
documents on the current website; plus, as we'll see later, we can
also use it to call object methods. For example, Let's say you set up
some variables in F<base.epl>, and then use them in F<file.html>:

F</base.epl>

	<HTML>
	<HEAD>
		<TITLE>Some title</TITLE>
	</HEAD>
	[- 
		$req = shift;
		$req->{webmaster} = 'John Smith'
	-]
	<BODY>
	[- Execute ('*') -]
	</BODY>
	</HTML>

F</file.html>

	[- $req = shift -]
	Please send all suggestions to [+ $req->{webmaster} +].

You can see that EmbperlObject is allowing us to set up global
variables in one place, and share them throughout the website. If you
place F<base.epl> in the root document directory, you can have any
number of other files in this and subdirectories, and they will all
get these variables whenever they are executed. No matter which file
is requested, F</base.epl> is executed first, and then the requested
file.

You don't even need to include the requested '*' file, but the usual
case would be to do so - it would be a little odd to completely ignore
the requested file!


=head1 Modular Files

The previous example is nice, it demonstrates the basic ability to
have website-wide variables set up in F<base.epl> and then
automatically shared by all other files. Leading on from this, we
probably want to split up our files, for both maintainability and
readability. For example, a non-trivial website will probably define
some website-wide constants, perhaps some global variables, and maybe
also have some kind of initialization code which has to be executed
for every page (e.g. setting up a database connection). We could put
all of this in F<base.epl>, but this file would quickly begin to look
really messy. It would be nice to split this stuff out into other
files. For example:

F</base.epl>

   	<HTML>
	[- Execute ('constants.epl')-]
	[- Execute ('init.epl')-]
   	<HEAD>
		<TITLE>Some title</TITLE>
	</HEAD>
	<BODY>
	[- Execute ('*') -]
	</BODY>
	[- Execute ('cleanup.epl') -]
	</HTML>

F</constants.epl>

	[-
		$req = shift;
		$req->{bgcolor} = "white";
		$req->{webmaster} = "John Smith";
		$req->{website_database} = "mydatabase";
	-]

F</init.epl>

	[-
		$req = shift;
		# Set up database connection
		use DBI;
		use CGI qw(:standard);
		$dsn = "DBI:mysql:$req->{website_database}";
		$req->{dbh} = DBI->connect ($dsn);
	-]

F</cleanup.epl>

	[-
		$req = shift;
		# Close down database connection
		$req->{dbh}->disconnect();
	-]

You can see how this would be useful, since every page on your site
now has available a database connection, in $req->{dbh}. Also notice
that we have a F<cleanup.epl> file which is always executed at the
end - this is very useful for cleaning up, shutting down connections
and so on.


=head1 Modular File Inheritance

To recap, we have seen how we can break our site into modules which
are common across multiple files, because they are automatically
included by F<base.epl>. Inheritance is a way in which we can make
our websites even more modular.

Although the concept of inheritance is one that stems from the
object-oriented paradigm, you really don't need to be an OO guru to
understand it. We will demonstrate the concept through a simple
example, leading on from the previous one.

Say you wanted different parts of your website to have different
<TITLE> tags. You could set the title in each page manually, but if
you had a number of different pages in each section, then this would
quickly get tiresome. Now we could split off the <HEAD> section into
its own file, just like F<constants.epl> and F<init.epl>, right? But
so far, it looks like we are stuck with a single F<head.epl> file for
the entire website, which doesn't really help much.

The answer lies in subdirectories. This is the key to unlocking
inheritance, and one of the most powerful features of
EmbperlObject. You may use subdirectories currently in your website
design, maybe for purposes of organization and maintenance. But here,
subdirectories actually enable you to override files from upper
directories. This is best demonstrated by example (simplified to make
this specific point clearer - assume F<constants.epl>, F<init.epl>
and F<cleanup.epl> are the same as in the previous example):

F</base.epl>

   	<HTML>
	[- Execute ('constants.epl')-]
	[- Execute ('init.epl')-]
   	<HEAD>
	[- Execute ('head.epl')-]
	</HEAD>
	<BODY>
	[- Execute ('*') -]
	</BODY>
	[- Execute ('cleanup.epl') -]
	</HTML>

F</head.epl>

	<TITLE>Joe's Website</TITLE>

F</contact/head.epl>

	<TITLE>Contacting Joe</TITLE>

Assume here that we have an F<index.html> file in each directory that
does something useful. The main thing to focus on here is
F<head.epl>. You can see that we have one instance of this file in
the root directory, and one in a subdirectory, namely
F</contact/head.epl>. Here's the neat part: When a page is requested
from your website, EmbperlObject will search automatically for
F<base.epl> first in the same directory as the requested page. If it
doesn't find it there, then it tracks back up the directory tree until
it does find the file. But then, when executing F<base.epl>, any
files which are Executed (such as F<head.epl>) are first looked for
in the B<original directory> of the requested file. Again, if the file
is not found there, then EmbperlObject tracks back up the directory
tree.

So what does this mean exactly? Well, if we have a subdirectory, then
we can if we want just have the usual F<index.html> file and nothing
else. In that case, all the files included by F<base.epl> will be
found in the root document directory. But if we redefine F<head.epl>,
as in our example, then EmbperlObject will pick up that version of the
file whenever we are in the /contact/ subdirectory.

That is inheritance in action. In a nutshell, subdirectories inherit
files such as F<head.epl>, F<constants.epl> and so on from upper,
"parent" directories. But if we want, we can redefine any of these
files in our subdirectories, thus specializing that functionality for
that part of our website. If we had 20 .html files in /contact/, then
loading any one of them would automatically get
F</contact/head.epl>.

This is all very cool, but there is one more wrinkle. Let's say we
want to redefine F<init.epl>, because there is some initialization
which is specific to the /contact/ subdirectory. That's fine, we could
create F</contact/init.epl> and that file would be loaded instead of
F</init.epl> whenever a file is requested from the /contact/
subdir. But this also means that the initialization code which is in
F</init.epl> would never get executed, right? That's bad, because the
base version of the file does a lot of useful set up. The answer is
simple: For cases like this, we just make sure and call the parent
version of the file at the start. For example:

F</contact/init.epl>

	[- Execute ('../init.epl') -]

	[-
		# Do some setup specific to this subdirectory
	-]

You can see that the very first thing we do here is to Execute the
parent version of the file (i.e. the one in the immediate parent
directory). Thus we can ensure the integrity of the basic
initialization which every page should receive.

EmbperlObject is very smart about this process. Say, for example, we
have a situation where we have several levels of subdirectory; then,
say we only redefine F<init.epl> in one of the deeper levels, say
F</sub/sub/sub/init.epl>. Now, if this file tries to Execute
F<../init.epl>, there may not be any such file in the immediate
parent directory - so EmbperlObject automatically tracks back up the
directories until it finds the base version, F</init.epl>. So, for
any subdirectory level in your website, you only have to redefine
those files which are specific to this particular area. This results
in a much cleaner website.

You may break your files up into whatever level of granularity you
want, depending on your needs. For instance, instead of just
F<head.epl> you might break it down into F<title.epl>,
F<metatags.epl> and so on. It's up to you. The more you split it up,
the more you can specialize in each of the subdirectories. There is a
balance however, because splitting things up too much results in an
overly fragmented site that can be harder to maintain. Moderation is
the key - only split out files if they contain a substantial chunk of
code, or if you know that you need to redefine them in subdirectories,
generally speaking.


=head1 Subroutines in EmbperlObject

There are two kinds of inheritance in EmbperlObject. The first is the
one which we described in the previous section, i.e. inheritance of
modular files via the directory hierarchy. The other kind, closely
related, is the inheritance of subroutines (both pure Perl and
Embperl). In this context, subroutines are really object methods, as
we'll see below. As you are probably already aware, there are two
kinds of subroutine in Embperl, for example:

	[!
		sub perl_sub
		{
			# Some perl code
		}
	!]

	[$ sub embperl_sub $]
		Some HTML
	[$ endsub $]

In EmbperlObject, subroutines become object methods; the difference is
that you always call an object method through an object reference. For
example, instead of a straight subroutine call like this:

	foo();

We have instead a call through some object:

	$obj->foo();

EmbperlObject allows you to inherit object methods in much the same
way as files. Because of the way that Perl implements objects and
methods, there is just a little extra consideration needed. (Note:
This is not really a good place to introduce Perl's object
functionality. If you're not comfortable with inheritance, @ISA and
object methods, then I suggest you take a look at the book
"Programming Perl" (O'Reilly) or "Object Oriented Perl" by Damien
Conway (Manning).)

A simple use of methods can be demonstrated using the following
example:

F</base.epl>

	[! sub title {'Joe's Website'} !]
	[- $req = shift -]
	<HTML>
	<HEAD>
	<TITLE>[+ $req->title() +]</TITLE>
	</HEAD>
	</HTML>

F</contact/index.html>

	[! sub title {'Contacting Joe'} !]
	[- $req = shift -]
	<HTML>
		A contact form goes here
	</HTML>

This is an alternative way of implementing the previous "contact"
example, which still uses inheritance - but instead of placing the
<TITLE> tag in a separate file (F<head.epl>), we use a method
(title()). You can see that we define this method in
F</base.epl>, so any page which is requested from the root directory
will get the title "Joe's Website". This is a pretty good default
title. Then, in F</foo/index.html> we redefine the title() method
to return "Contacting Joe". Inheritance insures that when the call to
title() occurs in F</base.epl>, the correct version of the method
will be executed. Since F</foo/index.html> has its own version of that
method, it will automatically be called instead of the base
version. This allows every file to potentially redefine methods
which were defined in F</base.epl>, and it works well. But, as your
websites get bigger, you will probably want to split off some routines
into their own files.

EmbperlObject also allows us to create special files which just
contain inheritable object methods. EmbperlObject can set up @ISA for
us, so that the Perl object methods will work as expected. To do this,
we need to access our methods through a specially created object
rather than directly through the Request object (usually called $r or
$req). This is best illustrated by the following example, which
demonstrates the code that needs to be added to F<base.epl> and also
shows how we implement inheritance via a subdirectory. Once again,
assume that missing files such as F<constants.epl> are the same as
previously (Note that the 'object' parameter to Execute only works in
1.3.1 and above).

F</base.epl>

   	<HTML>
	[- $subs = Execute ({object => 'subs.epl'}); -]
	[- Execute ('constants.epl') -]
	[- Execute ('init.epl') -]
   	<HEAD>
	[- Execute ('head.epl') -]
	</HEAD>
	<BODY>
	[- Execute ('*', $subs) -]
	</BODY>
	[- Execute ('cleanup.epl') -]
	</HTML>

F</subs.epl>

	[!
		sub hello
		{
			my ($self, $name) = @_;
			print OUT "Hello, $name";
		}
	!]

F</insult/index.html>

	[-
		$subs = $param[0];
		$subs->hello ("Joe");
	-]

F</insult/subs.epl>

	[! Execute ({isa => '../subs.epl'}) !]

	[!
		sub hello
		{
			my ($self, $name) = @_;
			$self->SUPER::hello ($name);
			print OUT ", you schmuck";
		}
	!]

If we requested the file F</insult/index.html> then we would see
something like

	Hello, Joe, you schmuck

So what is happening here? First of all, note that we create a $subs
object in F<base.epl>, using a special call to Execute(). We then
pass this object to files which will need it, via an Execute()
parameter. This can be seen with the '*' file.

Next, we have two versions of F<subs.epl>. The first, F</subs.epl>,
is pretty straightforward. All we need to do is remember that all of
these subroutines are now object methods, and so take the extra
parameter ($self). The basic hello() method simply says Hello to the
name of the person passed in.

Then we have a subdirectory, called /insult/. Here we have another
instance of F<subs.epl>, and we redefine hello(). We call the parent
version of the function, and then add the insult ("you schmuck"). You
don't have to call the parent version of methods you define, of
course, but it's a useful demonstration of the possibilities.

The file F</insult/subs.epl> has to have a call to Execute() which
sets up @ISA. This is the first line. You might ask why EmbperlObject
doesn't do this automatically; it is mainly for reasons of
efficiency. Not every file is going to contain methods which need
to inherit from the parent file, and so simply requiring this one line
seemed to be a good compromise. It also allows for a bit more
flexibility, as you can if you want include other arbitrary files into
the @ISA tree. 


=head1 Conclusions

So there you have it - an introduction to the use of EmbperlObject for
constructing large, modular websites. You will probably use it to
enable such things as website-wide navigation bars, table layouts and
whatever else needs to be modularized.

This document is just an introduction, to give a broad flavor of the
tool. You should refer to the actual documentation for details.

EmbperlObject will inevitably evolve as developers find out what is
useful and what isn't. We will try to keep this document up-to-date
with these changes, but also make sure to check the Embperl website
regularly for the latest changes.


=head1 Author

Neil Gunton neil@nilspace.com