简体   繁体   中英

Custom stream wrapper with include or eval?

Overview

I'm currently writing a template engine. It even supports multiple "format"s. Currently it can parse .php files and .tpl (specific to this engine).

I'll give you a little example of both, just to give you an Idea.

template.php:

Name: <?php echo $this->h($name) ?>
Posts: 
<?php foreach($posts as $post): ?>
    - <?php echo $this->h($post->name) ?> (<?php echo count($post->comments) ?> comments)
      <?php echo $this->render('post/shortpost', array('post' => $post)) ?>
<?php endforeach ?>

This is basicly just a standard PHP.

template.tpl

Name: {>$name}
Posts: 
{foreach($posts as $post):}
    - {>$post->name} ({=count($post->comments)} comments)
      {=:render('post/shortpost', array('post' => $post))}
{endforeach}

This templating "language" simply gets translated into PHP above.

Comparission

eval()

Currently these template's are parsed using eval() .

Pro

  • I don't have to change any code

Contra

  • when an error occurs in a template you only get a useless error message which doesn't tell you in which file the error occurs and sometimes the line number is even wrong.
  • Security? Template files are only need to be readable?
  • It's difficult to debug the code.
  • Code is harder to understand
  • more .. ?

stream wrappers and include()

I recently read about stream wrappers in php. You even could create your own. A other solution than eval would be to create a custom stream wrapper for every template "format" and use include to parse the template.

This has the following (potential) flaws:

Pro

  • may solve the problems with showing the wrong file/line-number in error messages (has anyone experiences with this?)
  • you could handle the template file exactly how to want it to be handled. Full control.

Contra

  • allow_url_(fopen|include) has to be on?
  • it is slow? (is eval() slow too?)
  • no gain in security. include does basically the same thing as eval.
  • more ... ?

EDIT: cached parsed files and include()

A third option would to to parse the template to PHP code and cache them (as suggested by @Jen-YaKovalev).

Pro

  • includes caching

Contra

  • if an error occurs while including the rendered template and an error occurs the error message doesn't point you to the correct file/eventually shows you the wrong line number.
  • You need an extra tmp/ directory to save the parsed files. You need write permissions for PHP/webserver. Would be more insecure because hackers would append some malicious code easier.

EDIT: stream filters and include('php://filter')

lately found the following php.net pages:

This would be an other possibility to solve this problem. Using include('php://filter/read=filtername/resource=file.php') , I could include a file which would first go through the filter filtername , before it gets executed.

Pro

  • doesn't need so much code as stream wrappers

Contra

  • not so much possibilities as with stream wrappers (caching?)
  • security?
  • speed?

Question

  • Have experiences using stream wrappers for parsing template files or similar?
  • Is there yet an other solution?
  • Are there more pro's and contras?
  • Which one would you recommend?

I think it's just a taste of one's coding-style, you'd better vote it or something.

  • I personnaly think eval is evil (in every language),
  • had bad experiences with include + php wrappers (even integrated ones*),
  • knowing all big(gish) template systems use compiling to a php file (smarty, twig), this it the one, i would use.

(*) In an earlier project we used a 1-line code (an empty class-extension) in a data-url wrapped include, and its performance was awful.

您当然不希望在生产环境中的每个请求上解析模板,这将浪费资源,因此是一种缓慢而不是非常智能的方法,因此我强烈建议使用缓存的解析文件并包含( )方法。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM