Проблема определения объема системы шаблонов - PullRequest
3 голосов
/ 21 июля 2009

Я пытаюсь создать скелетную систему View в PHP, но не могу понять, как получить встроенные представления для получения переменных их родителей. Например:

Просмотр класса

class View
{
    private $_vars=array();
    private $_file;

    public function __construct($file)
    {
        $this->_file='views/'.$file.'.php';
    }

    public function set($var, $value=null)
    {
        if (is_array($var))
        {
            $this->_vars=array_merge($var, $this->_vars);
        }
        else
            $this->_vars[$var]=$value;

        return $this;
    }

    public function output()
    {
        if (count($this->_vars))
            extract($this->_vars,  EXTR_REFS);
        require($this->_file);
        exit;
    }

    public static function factory($file)
    {
        return new self($file);
    }
}

test.php (вид верхнего уровня)

<html>
    <body>
        Hey <?=$name?>! This is <?=$adj?>!
        <?=View::factory('embed')->output()?>
    </body>
</html>

embed.php (встроен в test.php

<html>
    <body>
        Hey <?=$name?>! This is an embedded view file!!
    </body>
</html>

Код:

$vars=array(
    'name' => 'ryan',
    'adj' => 'cool'
);
View::factory('test')->set($vars)->output();

Выход:

Hey ryan! This is cool! Hey [error for $name not being defined] 
this is an embedded view file!!

Проблема в том, что переменные, которые я установил в представлении верхнего уровня, не передаются во встроенное представление. Как я мог это сделать?

Ответы [ 4 ]

1 голос
/ 21 июля 2009

Итак, я не совсем отвечаю на ваш вопрос, но вот моя сверхпростая система шаблонов, созданная вручную.Он поддерживает то, что вы пытаетесь сделать, хотя интерфейс другой.

// Usage
$main = new SimpleTemplate("templating/html.php");
$main->extract($someObject);
$main->extract($someArray);
$main->name = "my name";
$subTemplate = new SimpleTemplate("templating/another.php");
$subTemplate->parent($main);
$main->placeholderForAnotherTemplate = $subTemplate->run();
echo $main; // or $main->run(); 

// html.php
<html><body><h1>Title <?= $name ?></h1><p><?= $placeHolderForAnotherTemplate ?></p></body></html>

    <?php
// SimpleTemplate.php
function object_to_array($object)
{
    $array = array();
    foreach($object as $property => $value)
    {
        $array[$property] = $value;
    }

    return $array;
}

class SimpleTemplate
{
    public $source;
    public $path;
    public $result;
    public $parent;

    public function SimpleTemplate($path=false, $source=false)
    {
        $this->source = array();
        $this->extract($source);
        $this->path($path);
    }

    public function __toString()
    {
        return $this->run();
    }

    public function extract($source)
    {
        if ($source)
        {
            foreach ($source as $property => $value)
            {
                $this->source[$property] = $value;
            }
        }
    }

    public function parent($parent)
    {
        $this->parent = $parent;
    }

    public function path($path)
    {
        $this->path = $path;
    }

    public function __set($name, $value)
    {
        $this->source[$name] = $value;
    }

    public function __get($name)
    {
        return isset($this->source[$name]) ? $this->source[$name] : "";
    }

    public function mergeSource()
    {
        if (isset($this->parent))
            return array_merge($this->parent->mergeSource(), $this->source);
        else
            return $this->source;
    }

    public function run()
    {
        ob_start();
        extract ($this->mergeSource());
        include $this->path;
        $this->result = ob_get_contents();
        ob_end_clean();
        return $this->result;
    }
}
0 голосов
/ 22 июля 2009

Вы можете сделать ваше свойство $ _vars статичным, не особенно элегантным, но оно будет работать для того, чего вы пытаетесь достичь.

На заметку ... ваш array_merge () в функции set () неверен, поменяйте местами две переменные.

0 голосов
/ 21 июля 2009

Основная проблема в том, что ваши взгляды не имеют прямого знания друг о друге. Позвонив по этому номеру:

<?=View::factory('embed')->output()?>

в своем «родительском» представлении вы создаете и выводите шаблон, который не знает о том, что он находится внутри другого шаблона.

Есть два подхода, которые я мог бы порекомендовать здесь.

# 1 - свяжите ваши шаблоны.

Сделав ваши встроенные шаблоны «дочерними» для родительского шаблона, вы можете позволить им иметь доступ к родительским переменным во время output(). Я использую этот подход в построенной мной системе View. Это выглядит примерно так:

$pView = new View_Parent_Class();
$cView = new View_Child_Class();
$pView->addView($cView);

Во время $pview->render() дочернему представлению легко предоставляется доступ к переменным родителя.

Для этого метода может потребоваться много рефакторинга, поэтому я опущу грязные детали и перейду ко второму подходу.

# 2 - передать родительские переменные

Вероятно, это будет самый простой метод для реализации, учитывая подход, который вы уже использовали. Добавьте необязательный параметр в ваш метод вывода и слегка переписайте его, например:

public function output($extra_vars = null)
{
    if (count($this->_vars))
        extract($this->_vars,  EXTR_REFS);
    if (is_array($extra_vars)) extract($extra_vars, EXTR_REFS);
    require($this->_file);
    exit;
}

Если вы добавите также простой метод получения:

public function get_vars()
{
    return $this->_vars;
}

Затем вы можете встраивать свои файлы с тем, что фактически обеспечивает доступ для чтения к родительским переменным:

<?=View::factory('embed')->output($this->get_vars())?>

$this будет ссылкой на текущий шаблон, т.е. родитель. Обратите внимание, что с помощью этого метода вы можете столкнуться с именами переменных из-за двух вызовов extract.

0 голосов
/ 21 июля 2009

хорошо, вы создаете новый экземпляр класса, поэтому во встроенном шаблоне не определены переменные. Вы должны попытаться скопировать объект, а не создавать новый.

редактировать: я говорю о заводском методе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...