3v4l.org

run code in 300+ PHP versions simultaneously
<?php class Template { private $_template = ''; private $_assigns = array(); /** Variables with leading __ are reserved for internal using */ const VALID_VARIABLE = '(?!__)[a-zA-Z0-9_\x7f-\xff]*'; const TAG_SIGN_OPEN = '{'; const TAG_SIGN_CLOSE = '}'; public function __construct($template) { $this->_template = $template; } public function assign($name, $value) { if (!preg_match('/^' . self::VALID_VARIABLE . '$/', $name)) throw new Exception('Invalid name: "' . $name . '"'); if (is_array($value)) foreach ($value as $key_name => $val) if (!preg_match('/^' . self::VALID_VARIABLE . '$/', $key_name)) throw new Exception('Invalid key name: "' . $key_name . '"'); $this->_assigns[$name] = $value; } private function _getToken($string, $sign, $pos, &$token) { $position = strpos($string, $sign, $pos); if ($position === false) { $token = substr($string, $pos); $pos = false; } else { $token = substr($string, $pos, $position - $pos); $pos = $position + strlen($sign); } return $pos; } /** * To avoid the existence of extra variables * and overwriting assigns params * @param type $prepared_code * @param array $assigns * @return type */ private static function _execute($prepared_code, array $assigns) { $__prepared_code = $prepared_code; unset($prepared_code); $__assigns = $assigns; unset($assigns); extract($__assigns); unset($__assigns); ob_start(); eval($__prepared_code); $content = ob_get_contents(); ob_end_clean(); return $content; } public function parse() { $prepared_code = '?' . '>'; $pos = 0; while ($pos !== false) { $pos = $this->_getToken($this->_template, self::TAG_SIGN_OPEN, $pos, $token); $prepared_code .= $token; if ($pos !== false) { $pos = $this->_getToken($this->_template, self::TAG_SIGN_CLOSE, $pos, $token); if ($pos === false) throw new Exception('Template syntax error. Expected "}"'); switch (true) { case preg_match('/^' . self::VALID_VARIABLE . '$/', $token): $prepared_code .= '<?php echo ${\'' . $token . '\'} ?' . '>'; break; case preg_match('/^loop +(' . self::VALID_VARIABLE . ')$/', $token, $match): $prepared_code .= '<?php foreach (${\'' . $match[1] . '\'} as $__index => $__tmp)' . '{extract($__tmp); unset($__tmp); ?' . '>'; break; case preg_match('/^end +loop$/', $token): $prepared_code .= '<?php } ?>'; break; case preg_match('/^\%index\%$/', $token): $prepared_code .= '<?php echo $__index ?' . '>'; break; default: throw new Exception('Template syntax error. Unexpected token "' . $token . '"'); break; } } } echo $prepared_code; return self::_execute($prepared_code, $this->_assigns); } } $templateHtml = <<<END_HTML <div>{my_var}</div> {loop items} <div>{%index%}. {name}</div> {end loop} END_HTML; $template = new Template($templateHtml); $template->assign('my_var', 'test'); $template->assign('items', array( array('name' => 'First'), array('name' => 'Second') )); echo $template->parse();

preferences:
40.33 ms | 402 KiB | 5 Q