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
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.