PHP has include(index.php); what does Perl have?

I've done a little more with Perl and web design, but I've encountered a problem that has left me a bit perplexed. There's something PHP does that I'm sure Perl CAN do, but I'm just not sure how. That said, I'm not a huge fan of PHP, and to be quite honest the only function I've utilized has been include(), which is what I need to replicate. As you know, being able to standardize a page layout (header, body, footer) with separate pages makes things much easier to update. Instead of correcting/adding a navigation link to twenty pages, you only make one change! However, using PHP within a Perl script (without the aid of the PHP or PHP::Include modules - my host doesn't have 'em installed) doesn't work as the browser doesn't get the chance to parse/execute the PHP.

Some people have pointed me in the direction of the system() function, but I don't think that's quite what I need (please correct me if I'm wrong). Also, I don't really know how I'd use it - there's nothing to really 'execute' in the PHP I want; I guess all I really need is to read in a .php or .html file and store it to a scalar variable and then place the variable where I would normally use

<?php include(); ?>

In that case, I guessed that just opening the file and storing it to some array/list would allow me to simply print the array, but I can't figure out how to do it!

I resorted to Google, and came up with this page.

I've tried every method there, but I always end up with a blank page. Does anyone have insight on this?

For reference, I've been testing this with:

http://www.masterrex.com/test/include/test.pl
http://www.masterrex.com/test/include/i/head.html



print "Content-type: text/html\n\n";
open (HTML, "</i/head.html");
print <HTML>;
close (HTML);

############

open (HTMLDOC, "</i/head.html");
flock (HTMLDOC, 1);
my @htmlFile = <HTMLDOC>;
close (HTMLDOC);
print "Content-type: text/html\n\n";
foreach (@htmlFile) {
print $_;
}

Also, if I were to not use a bareword, what kind of variable would I end up using? I've read somewhere that opening a file to a scalar only works if there are no return characters in the file - so I'd assume that I'd want an array/list. I'm a bit confused at this point :P

6 Comments

I used the following as a test and it prints the head.html out fine.

#!/usr/bin/env perl

use strict;
use warnings;

open(HTMLDOC, " flock(HTMLDOC, 1);
my @htmlfile = |HTMLDOC|; # should be angle brackets I know
close(HTMLDOC);

print "Content-type: text/html\n\n";
for my $line (@htmlfile) {
print $line;
}

I am not familiar with MT markup so the above should have angle brackets for the my @htmlfile. I ran that locally and it prints out what I would expect. Leads me to believe you are getting the actual file.

PHP was designed for web developers - you couldn't even use it on the command line until a couple of years ago. As such, with it's 8 billion functions, it blurs the line between programming and template language.

The include function as you're using it is more within the range of a template language. For example, Template Toolkit has [% PROCESS 'file' %] and [% INCLUDE 'file' %].

In fact, you might want to consider TT instead of rolling your own templating:

http://template-toolkit.org/docs/manual/Directives.html#section_INCLUDE


If you're looking to process code at run time, Perl has require, but I don't think it's what you want for this situation.

The closest equivalent of PHP's include is require, but the issue with require is that it will only include a specific file once, so you'll have to settle for do 'file'. So your code could be something like:

print "Content-type: text/html\n\n";
do('head.pl');
# code to output body of page
do('foot.pl');

and in head.pl (and similarly in foot.pl):

print <<END_OF_HEADER
<html>
<head>
<title>Page Title</title>
</head>
END_OF_HEADER


Obviously you should be using the strict and warnings pragmas, and lexical filehandles instead of Typeglobs, as well as handling errors and exceptions in your code, which I have left out here.

All that being said, you should be looking at using a templating module like TT instead of hand rolling your own solution, and using a web framework, something like Catalyst or CGI-Application instead of printing directly to STDOUT.

To run external scripts, you don't need "system", you can use "do".

Since others before me recommended TT, let me recommend also HTML::Template, a.k.a. "HT".


HT is very simply to learn/use and very simple to install (only core dependencies).


It follows the principle of separating code (Perl) from design (HTML) and provides a flexible yet simple framework for building your site. Did I mention I'm a fan? :)


You could for example save the following file as test.tmpl:


<html>
<head><title>Test Template</title>
<body>
<TMPL_INCLUDE NAME="header.tmpl">
<TMPL_INCLUDE NAME="body.tmpl">
<TMPL_INCLUDE NAME="footer.tmpl">
</body>
</html>


Now in your CGI program:


#!/usr/bin/perl -w
use HTML::Template;

# open the html template
my $template = HTML::Template->new(filename => 'test.tmpl');

# fill in some parameters
#     (whatever tmpl_vars are used in your included templates)

# send the obligatory Content-Type and print the template output
print "Content-Type: text/html\n\n", $template->output;


Now if you have several pages all using the same included header.tmpl, you can change just the one file in order to change all your pages.


Hope this helps :)

Template::Tiny

That is another if you like TT syntax better. Although it might still be in flux.

Leave a comment

About masterrex

user-pic I blog about the dumb little things I'm doing with Perl. I am by no means an expert; if you find that I've done something wrong or in a poor fashion, please correct me! I appreciate any and all knowledge you'd care to part with :)