views:

116

answers:

4

I was looking at templating systems for php, and I've come to believe that pure php code seems to be the solution I want to use.

I'm the lone developer, so there's no designers who need a nerfed arena to work in. Template engines like smarty seem to suffer from the "Inner-platform effect". If I stick with good practices ( pre-computed values, use only foreach ), I think this will work.

My goal is to have a single source for the string of the html shared by each page. My thought is that a separate php file, accessed via include, is a good way to meet this goal.

However, I'm concerned that that might pose a security hazard for the site -- I can't think of anything specific at the moment, but someone could guess the name of the template and request it directly, perhaps exposing something they needn't see. (I suppose I could put in a check to see if it itself is the request.) I have a hunch this could be bad, so I don't want to go ahead and do it, create what I feared would happen, and then throw that work away.

If a separate file is not the best idea, what else should I use to basically store a string for the whole site? A string constant in an include, that I could use in sprintf()? A function that returns the html string from arguments of the page-specific html parts?

+9  A: 

Files that should not be served via HTTP should be stored in a directory from which your webserver will not allow anything (not PHP, at least) to be served to the users.

Two possibilities :

  • put those files outside of the DocumentRoot
  • or put those files in a sub-directory, from which Apache will not be able to serve any file.

Such "not served" files generally include stuff like :

  • configuration files
  • libraries / frameworks
  • data files (like an SQLite database, for instance ; or i18n files)


The first solution : your directories could look like this :

  • data/
    • i18n/
    • i18n/your-file-here.php
  • library/
  • www/            <- this is Apache's DocumentRoot
    • index.php
    • another-php-file.php


And for the second solution, just disable access to the directory containing your "data" or "libraries" files, putting in it a .htaccess (If your webserver is Apache) file containing something like

Deny From All

With that, Apache will not allow anyone to directly access via HTTP the files in that directory, but your executable PHP script (in another directory) will still be able to include them.

Pascal MARTIN
+1 I would have suggested just the first, but the second works great. I agree with these.
Lucas Oman
I prefer the first one (this way, you don't risk forgetting a hidden .htaccess file) ;; but, with some shared hosting services, you cannot put anything "higher" than the DocumentRoot... in which cases you can't use the first solution :-(
Pascal MARTIN
-1 until you change "Files that should not be "executed" should be stored in a directory from which your webserver will not interpret PHP." to something like "Files that should not be directly accessible through the webserver should be stored outside the directory tree(s) it publishes." at face value, you're suggesting a setup where such php templates are served unprocessed, leaking the source. that's much worse a security problem than having them exposed but processed.
just somebody
@just somebody : I've edited that first sentence, trying to make it a bit more clear -- and I've added a couple of more things later in the post ;; hope it's understandable ^^
Pascal MARTIN
@Pascal MARTIN: thx, downvote retracted
just somebody
@just somebody : thanks :-)
Pascal MARTIN
+4  A: 

Simple, really; Name the file whatever you want, but use ".inc.php" as the extension, then include this line at the top of the file:

if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
    die;
}

this will kill the script if the file is accessed directly.

EDIT: Pascal Martin's solution is probably more in keeping with BCP, whereas mine is more quick-and-dirty. I've used both, and either seems to be fine.

Dereleased
I like this, because the functionality is in the page, and travels with it. An `.htaccess` file might get lost -- it's already invisible!
What is BCP? Need 15 characters in a comment.
Either "Best Common Practice" or "Best Current Practice", they mean the same thing: the best thing we know how to do and are doing right now.
Dereleased
I've accepted Martin's answer, but I still like this one. It all keeps functionality in a single unit, and it's in the same language as php, instead of breaking functionality out into another file and language.
+1  A: 

I like using a separate template file as well. Generally I'll define a constant in my config file and then put a check for that constant at the top of the included file like such:

Set constant in config:

define('_VALIDPAGE', true);

Check constant in included file:

defined('_VALIDPAGE') or die('Not allowed');

This makes it so that the included file can only be loaded from within your application.

cOle2
A: 

you're right in that php is a fine templating system in itself, as long as you stick to a certain subset of it in the "template" files. but insistance on a single template per web page is impractical: more often than not you'll find that you have fragments duplicated over several templates.

anyway, separate files are fine. putting templates into a directory (tree) separate from the source directory (tree) is in my experience bad idea: the conceptual distance grows, you loose sight of what's really used and what's not, and as a result, you have quite a few templates that are dead but not buried, since their state is not so obvious.

my suggestion: keep the "templates" together with "program" files, protected with appropriate web server configuration

DocumentRoot /www
AddType application/x-httpd-php .php

<Files ~ \.tpl$>
 deny from all
</Files>

/www/
  dir1/
    file.php
    file.tpl
    another-file.tpl
  dir2/
    other-file.php
    other-file.tpl
    yet-another-file.tpl
  ...
  common/
    shared-file.tpl
    another.tpl
just somebody