public function index(View $view)
{
//定义一个data变量,是个关联数组
$data = [
'data'=>'我是变量data',
'msg'=>'我是变量msg'
];
//直接调用View实例中的fetch方法进行渲染。并把data传入进去
return $view->fetch('index',$data);
//第二种方式
$strings = "{$data}-{$msg}";
return $view->assign($data)->display($strings,$data);
}
上图代码所示,tp的渲染模板。默认有两种方式,一种是调用fetch直接进行渲染。第二种就是先调用assign方法传入要渲染的数据。然后再调用display方法进行渲染。(还有助手函数view().这里就不过多描述了)。
public function fetch(string $template = '', array $vars = []): string
{
//调用类中的getContent方法,并将模板文件、渲染的数据
//封装成匿名函数传入到getContent方法中
return $this->getContent(function () use ($vars, $template) {
$this->engine()->fetch($template, array_merge($this->data, $vars));
});
}
//这个方法,主要就是把传入过来的匿名函数给运行一下
//通过ob_系列函数捕捉到缓冲区的输出
//然后将捕捉到的缓冲区内容返回
protected function getContent($callback): string
{
//开启缓存
ob_start();
//取消缓存输出到页面上
ob_implicit_flush(0);
//开始渲染
try {
//执行闭包
$callback();
} catch (\Exception $e) {
//如果闭包函数执行失败则清空缓存
ob_end_clean();
//然后弹出异常
throw $e;
}
//获取并清空缓存
$content = ob_get_clean();
//如果filter有闭包。一般为替换当前页面的什么东西。执行一下
if ($this->filter) {
$content = call_user_func_array($this->filter, [$content]);
}
//最后直接返回
return $content;
}
//大概就是获取视图驱动,然后传入模板和数据,渲染模板
$this->engine()->fetch($template, array_merge($this->data, $vars));
//这个就不多解释什么了,主要就是获取视图驱动的实例
public function engine(string $type = null)
{
return $this->driver($type);
}
public function fetch(string $template, array $vars = []): void
//判断是否有数据如果有则合并this->data
if ($vars) {
$this->data = array_merge($this->data, $vars);
}
//判断有没有缓存,如果有。则直接输出缓存
if (!empty($this->config['cache_id']) && $this->config['display_cache'] && $this->cache) {
// 读取渲染缓存
if ($this->cache->has($this->config['cache_id'])) {
echo $this->cache->get($this->config['cache_id']);
return;
}
}
//解析传入过来的模板名
$template = $this->parseTemplateFile($template);
if ($template) {
//这里生成一下缓存路径+模板
$cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($this->config['layout_on'] . $this->config['layout_name'] . $template) . '.' . ltrim($this->config['cache_suffix'], '.');
//判断缓存文件是否还有效,或者存在
if (!$this->checkCache($cacheFile)) {
// 缓存无效 重新模板编译
//如果不存在,读取模板。并调用compiler重新编译
$content = file_get_contents($template);
$this->compiler($content, $cacheFile);
}
//开启页面缓存
ob_start();
//禁止直接输出
ob_implicit_flush(0);
// 读取编译存储
$this->storage->read($cacheFile, $this->data);
// 获取并清空缓存
$content = ob_get_clean();
if (!empty($this->config['cache_id']) && $this->config['display_cache'] && $this->cache) {
// 缓存页面输出
$this->cache->set($this->config['cache_id'], $content, $this->config['cache_time']);
}
//输出编译后的内容
echo $content;
}
}
private function compiler(string &$content, string $cacheFile): void
{
// 判断是否启用布局
if ($this->config['layout_on']) {
if (false !== strpos($content, '{__NOLAYOUT__}')) {
// 可以单独定义不使用布局
$content = str_replace('{__NOLAYOUT__}', '', $content);
} else {
// 读取布局模板
$layoutFile = $this->parseTemplateFile($this->config['layout_name']);
if ($layoutFile) {
// 替换布局的主体内容
$content = str_replace($this->config['layout_item'], $content, file_get_contents($layoutFile));
}
}
} else {
$content = str_replace('{__NOLAYOUT__}', '', $content);
}
//这里是替换模板内的tp语法例如 {$data} = echo $data
//{if (1==1))} ==
//{/endif} ==
$this->parse($content);
if ($this->config['strip_space']) {
/* 去除html空格与换行 */
$find = ['~>\s+<~', '~>(\s+\n|\r)~'];
$replace = ['><', '>'];
$content = preg_replace($find, $replace, $content);
}
// 优化生成的php代码
$content = preg_replace('/\?>\s*<\?php\s(?!echo\b|\bend)/s', '', $content);
// 模板过滤输出
$replace = $this->config['tpl_replace_string'];
$content = str_replace(array_keys($replace), array_values($replace), $content);
// 添加安全代码及模板引用记录
$content = 'includeFile) . '*/ ?>' . "\n" . $content;
//写入缓存
$this->storage->write($cacheFile, $content);
$this->includeFile = [];
}
// 读取编译存储
$this->storage->read($cacheFile, $this->data);
public function read(string $cacheFile, array $vars = []): void
{
$this->cacheFile = $cacheFile;
if (!empty($vars) && is_array($vars)) {
//通过extract方法,将数据写到符号表内
extract($vars, EXTR_OVERWRITE);
}
//载入模版缓存文件
include $this->cacheFile;
}
//这个和第一种流程第一步一样,不多解释
public function display(string $content, array $vars = []): string
{
return $this->getContent(function () use ($vars, $content) {
//调用template中的display方法,并将content和数据传入进去
$this->engine()->display($content, array_merge($this->data, $vars));
});
}
public function display(string $content, array $vars = []): void
{
//判断有没有要编译的数据/如果有就和this->data叔祖1合并
if ($vars) {
$this->data = array_merge($this->data, $vars);
}
//获取到编译后的缓存模板
$cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($content) . '.' . ltrim($this->config['cache_suffix'], '.');
//调用checkCahce把缓存模板传入进去,查看是否过期
//或不存在
if (!$this->checkCache($cacheFile)) {
//如果模板无效或不存在,就调用
//compiler方法重写缓存
$this->compiler($content, $cacheFile);
}
// 读取编译存储
$this->storage->read($cacheFile, $this->data);
}