读 Slim 框架代码(3)

View

Slim 框架提供了一个 View Engine (\Slim\View 类),在使用的时候通过 $app->render('myTemplate.php', array('id' => $id)); 的方法可以把模板转换成页面。还可以自定义 View Engine,只需要继承 \Slim\View 类,并实现其 render() 方法,并在创建 \Slim\Slim 类实例的时候通过 settings 指定自定义的 View:

$app = new \Slim\Slim(array(
    'view' => new CustomView()
));

默认 View

In slim.php

public function render($template, $data = array(), $status = null)
{
    if (!is_null($status)) {
        $this->response->status($status); 
    }
    $this->view->setTemplatesDirectory($this->config('templates.path'));
    $this->view->appendData($data);
    $this->view->display($template);
}

在执行 $app->render('myTemplate.php', array('id' => $id)) 的时候,会依次执行 View 的 setTemplatesDirectoryappendDatadisplay 方法。

setTemplatesDirectory 设置模板的目录,默认是 ./templates 目录。

\Slim\View 类有个 data 成员变量,是一个 \Slim\Helper\Set 类,这个类是对关联数组的一个封装,在关联数组的基础上提供了一些自定以的方法。appendData 会把调用 render 函数时传进来的关联数组的键值对写到这个成员变量中。

In View.php

public function appendData($data)
{
    if (!is_array($data)) {
        throw new \InvalidArgumentException('Cannot append view data. Expected array argument.');
    }
    $this->data->replace($data);
}
...
public function replace($items)
{
    foreach ($items as $key => $value) {
        $this->set($key, $value); // Ensure keys are normalized
    }
}
...
public function set($key, $value)
{
    $this->data[$this->normalizeKey($key)] = $value;
}

最后的 display 方法经过 \Slim\Viewfetch 方法的的结果打印出来,而 fetch 方法直接调用了 render 方法。这也是为什么自定义的 View 类要实现 render 方法。

In View.php

protected function render($template)
{
    $templatePathname = $this->getTemplatePathname($template);
    if (!is_file($templatePathname)) {
        throw new \RuntimeException("View cannot render `$template` because the template does not exist");
    }
    extract($this->data->all());
    ob_start();
    require $templatePathname;

    return ob_get_clean();
}

extract 会把关联数组的键值对抽成变量和对应的值(extract 方法)。然后 ob_start 开启缓存捕获输出,这样在模板中的 echo $var 之类的输出会被捕获成字符串,最后随着模板一起返回。这样就实现了变量的替换。

自定义 View

自定义的 View 渲染过程和默认的 View 一样,只是通过实现 render 方法有更灵活的使用场景,比如可以给用自定义的 View 来实现其他框架的 layout 功能(实例1,实例2)。

你可能感兴趣的:(PHP,framework,slim,读代码)