Вы создаете своего рода систему шаблонов.Вы можете заново изобрести колесо (вроде), кодируя его самостоятельно или просто используя облегченную систему шаблонов, такую как усы .
. Для очень легкого подхода вы можете использоватьрегулярные выражения для формулировки синтаксиса переменных вашего шаблона.Просто определите, как можно записать переменную, затем извлеките используемые имена / метки и замените их по желанию.
Функция, используемая для этого, - preg_replace_callback
.Вот небольшой пример кода ( Demo ), который отражает только простую замену, однако вы можете изменить подпрограмму замены для доступа к нужным значениям (в этом примере я использую переменную, которая либоArray
или реализует ArrayAccess
):
<?php
$template = <<<EOD
This is my template,
I can use [vars] at free [will].
EOD;
class Template
{
private $template;
private $vars;
public function __construct($template, $vars)
{
$this->template = $template;
$this->vars = $vars;
}
public function replace(array $matches)
{
list(, $var) = $matches;
if (isset($this->vars[$var]))
{
return $this->vars[$var];
}
return sprintf('<<undefined:%s>>', $var);
}
public function substituteVars()
{
$pattern = '~\[([a-z_]{3,})\]~';
$callback = array($this, 'replace');
return preg_replace_callback($pattern, $callback, $this->template );
}
}
$templ = new Template($template, array('vars' => 'variables'));
echo $templ->substituteVars();
Пока это не выглядит впечатляющим, это просто замена тегов шаблона значением.Однако, как уже упоминалось, теперь вы можете добавить в шаблон преобразователь, который может преобразовывать теги шаблона в значение, а не использовать простой массив.
Вы указали в своем вопросе, что хотели бы использовать _
символ для отделения от элементов / функций объекта.Ниже приведен класс распознавателя, который разрешает все глобальные переменные в этой записи.Он показывает, как обрабатывать как члены, объекты и методы, так и обход переменных.Однако он разрешается не в $this
, а в глобальное пространство имен:
/**
* Resolve template variables from the global namespace
*/
class GlobalResolver implements ArrayAccess
{
private function resolve($offset)
{
$stack = explode('_', $offset);
return $this->resolveOn($stack, $GLOBALS);
}
private function resolveOn($stack, $base)
{
$c = count($stack);
if (!$c)
return array(false, NULL);
$var = array_shift($stack);
$varIsset = isset($base[$var]);
# non-set variables don't count
if (!$varIsset)
{
return array($varIsset, NULL);
}
# simple variable
if (1 === $c)
{
return array($varIsset, $base[$var]);
}
# descendant
$operator = $stack[0];
$subject = $base[$var];
$desc = $this->resolvePair($subject, $operator);
if (2 === $c || !$desc[0])
return $desc;
$base = array($operator => $desc[1]);
return $this->resolveOn($stack, $base);
}
private function resolvePair($subject, $operator)
{
if (is_object($subject))
{
if (property_exists($subject, $operator))
{
return array(true, $subject->$operator);
}
if (method_exists($subject, $operator))
{
return array(true, $subject->$operator());
}
}
if (is_array($subject))
{
if (array_key_exists($operator, $subject))
{
return array(true, $subject[$operator]);
}
}
return array(false, NULL);
}
public function offsetExists($offset)
{
list($isset) = $this->resolve($offset);
return $isset;
}
public function offsetGet($offset)
{
list($isset, $value) = $this->resolve($offset);
return $value;
}
public function offsetSet ($offset, $value)
{
throw new BadMethodCallException('Read only.');
}
public function offsetUnset($offset)
{
throw new BadMethodCallException('Read only.');
}
}
Этот класс преобразователя можно использовать затем для использования некоторых примеров значений:
/**
* fill the global namespace with some classes and variables
*/
class Foo
{
public $member = 'object member';
public function func()
{
return 'function result';
}
public function child()
{
$child->member = 'child member';
return $child;
}
}
$vars = 'variables';
$foo = new Foo;
$template = <<<EOD
This is my template,
I can use [vars] at free [foo_func] or [foo_member] and even [foo_child_member].
EOD;
/**
* this time use the template with it's own resolver class
*/
$templ = new Template($template, new GlobalResolver);
echo $templ->substituteVars();
См. полная демонстрация в действии .
Для этого потребуется лишь небольшое изменение, чтобы соответствовать вашим потребностям, и, наконец,