phalcon提供的两种视图引擎,一种是php,还有一种是volt,另外还支持自定义和第三方视图引擎。
下面将按下图标注顺序逐渐完成该功能。
1、打开config下面的全局配置文件config.php
定义volt引擎服务配置和view视图服务配置,这是全局默认配置。
这里配置以volt为扩展名的模板使用viewEngineVolt引擎服务,以phtml为扩展名的模板使用viewEnginePhp引擎服务。这里的配置格式只是一种参考,你可以定义成任意你想要的格式,只要你能正确访问到就行了。
<?php
/**
* @desc 全局配置文件
* @author zhaoyang
* @date 2018年5月3日 下午7:54:47
*/
return [
// 服务配置
'services' => [
// volt引擎相关配置
'view_engine_volt' => [
// 编译模板目录
'compiled_path' => BASE_PATH . 'runtime/' . DEFAULT_MODULE . '/compiled/volt' . DS,
// 是否实时编译
'compile_always' => false,
// 附加到已编译的PHP文件的扩展名
'compiled_extension' => '.php',
// 使用这个替换目录分隔符
'compiled_separator' => '%%',
// 是否要检查在模板文件和它的编译路径之间是否存在差异
'stat' => true,
// 模板前缀
'prefix' => '',
// 支持HTML的全局自动转义
'autoescape' => false
],
// 模板相关配置
'view' => [
// 模板后缀
'view_suffix' => 'volt,phtml',
// 模板路径
'view_path' => APP_PATH . DEFAULT_MODULE . '/views' . DS,
// 模板引擎,暂时支持viewEngineVolt or viewEnginePhp,与模板后缀一一对应
'view_service' => 'viewEngineVolt,viewEnginePhp',
],
],
];
2、打开app/home/config下面的home模块配置文件,这里可以对模块进行针对性配置。
<?php
// 模块名称
defined('MODULE_NAME') || define('MODULE_NAME', 'home');
// 模块命名空间
defined('MODULE_NAMESPACE') || define('MODULE_NAMESPACE', APP_NAMESPACE . '\\Home');
return [
// 模块名称
'module_name' => MODULE_NAME,
// 需要注册的模块命名空间
'module_namespaces' => [
MODULE_NAMESPACE . '\\Controllers' => APP_PATH . MODULE_NAME . '/controllers' . DS,
MODULE_NAMESPACE . '\\Models' => APP_PATH . MODULE_NAME . '/models' . DS
],
// 模块默认的命名空间
'module_default_namespaces' => MODULE_NAMESPACE . '\\Controllers',
// 服务配置
'services' => [
// volt引擎相关配置
'view_engine_volt' => [
// 编译模板目录
'compiled_path' => BASE_PATH . 'runtime/' . MODULE_NAME . '/compiled/volt' . DS,
// 是否实时编译
'compile_always' => false,
// 附加到已编译的PHP文件的扩展名
'compiled_extension' => '.php',
// 使用这个替换目录分隔符
'compiled_separator' => '%%',
// 是否要检查在模板文件和它的编译路径之间是否存在差异
'stat' => true,
// 模板前缀
'prefix' => '',
// 支持HTML的全局自动转义
'autoescape' => false
],
// 模板相关配置
'view' => [
// 模板后缀
'view_suffix' => 'volt,phtml',
// 模板路径
'view_path' => APP_PATH . MODULE_NAME . '/views' . DS,
// 模板引擎,暂时支持viewEngineVolt or viewEnginePhp,与模板后缀一一对应
'view_service' => 'viewEngineVolt,viewEnginePhp',
],
]
];
3、在common目录下创建Common.php基础工具类,主要放些功能方法,例如目录格式化、创建目录等静态方法
<?php
/**
* @desc 基础工具类
* @author zhaoyang
* @date 2018年5月4日 下午11:21:11
*/
namespace Common;
class Common {
/**
* @desc 格式化目录
* @author zhaoyang
* @date 2018年5月4日 下午11:21:27
*/
public static function dirFormat(string $path) {
$path = str_replace('\\', '/', $path);
$path = preg_replace_callback('/(\{.+\})/U', function ($matches) {
return date(rtrim(ltrim($matches[0], '{'), '}'));
}, $path);
return $path;
}
/**
* @desc 创建目录
* @param string $pathname 路径
* @param int $mode 文件夹权限默认情况下,模式是0777
* @param bool $recursive 规定是否设置递归模式
* @param resource $context 规定文件句柄的环境。Context 是可修改流的行为的一套选项。
* @return bool
* @author zhaoyang
* @date 2018年5月4日 下午11:21:43
*/
public static function mkdir(string $pathname, int $mode = 0777, bool $recursive = true, resource $context = null) {
if (is_dir($pathname)) {
return true;
}
return is_resource($context) ? mkdir($pathname, $mode, $recursive, $context) : mkdir($pathname, $mode, $recursive);
}
/**
* @desc 将字符串中下划线转为驼峰
* @param string $string
* @return string
* @author zhaoyang
* @date 2018年5月4日 下午11:22:02
*/
public static function convertStrUnderline(string $string) {
if(strpos($string, '_') !== false){
$string = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $string))));
}
return $string;
}
/**
* @desc 将数组中键名下划线转换为驼峰
* @param array|object $arr
* @return mixed
* @author zhaoyang
* @date 2018年5月4日 下午11:22:21
*/
public static function convertArrKeyUnderline($arr) {
$type = is_array($arr) ? 1 : (is_object($arr) ? 2 : 0);
if ($type) {
foreach ($arr as $k => $v) {
$key = $k;
if (strpos($key, '_') !== false) {
$key = Common::convertStrUnderline($key);
if ($type == 1) {
unset($arr[$k]);
} else {
unset($arr->$k);
}
}
if (is_array($v) || is_object($v)) {
$v = static::convertArrKeyUnderline($v);
}
if ($type == 1) {
$arr[$key] = $v;
} else {
$arr->$key = $v;
}
}
}
return $arr;
}
}
4、打开config下的services.php文件,分别注册视图引擎volt服务、视图引擎php服务和视图服务。
phalcon的视图支持分层渲染,如果不需要Main Layout和Controller Layout渲染可以在这里设置关闭。分层渲染的具体使用方法请看官方文档。
<?php
/**
* @desc 注册服务
* @author zhaoyang
* @date 2018年5月3日 下午8:01:34
*/
use Common\Common;
use Phalcon\Config;
use Phalcon\DI;
use Phalcon\DI\FactoryDefault;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\Router;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt as ViewEngineVolt;
use Phalcon\Mvc\View\Engine\Php as ViewEnginePhp;
$di = new FactoryDefault();
/**
* @desc 注册调度器服务
* @author zhaoyang
* @date 2018年5月3日 下午8:38:34
*/
$di->setShared('dispatcher', function () {
$config = $this->getConfig();
$dispatcher = new Dispatcher();
$defaultNamespace = $config->module_default_namespaces ?? DEFAULT_MODULE_NAMESPACE . '\\Controllers';
$dispatcher->setDefaultNamespace($defaultNamespace);
return $dispatcher;
});
/**
* @desc 注册配置服务
* @author zhaoyang
* @date 2018年5月3日 下午8:38:53
*/
$di->setShared('config', function () use ($config) {
return new Config($config);
});
/**
* @desc 注册路由服务
* @author zhaoyang
* @date 2018年5月3日 下午8:39:06
*/
$di->setShared('router', function () use ($routerRules) {
$router = new Router();
// 自动删除末尾斜线
$router->removeExtraSlashes(true);
foreach ($routerRules as $k => $v) {
$router->add($k, $v);
}
return $router;
});
/**
* @desc 注册视图引擎volt服务
* @author zhaoyang
* @date 2018年5月4日 下午5:28:52
*/
$di->setShared('viewEngineVolt', function (View $view, DI $di) {
// 获取config服务有多种方法,这是其一
$voltConfig = $di->get('config')->services->view_engine_volt->toArray();
$voltConfig = Common::convertArrKeyUnderline($voltConfig);
$viewEngineVolt = new ViewEngineVolt($view, $di);
$voltConfig['compiledPath'] = isset($voltConfig['compiledPath']) ? Common::dirFormat($voltConfig['compiledPath']) : BASE_PATH . 'runtime/' . DEFAULT_MODULE . '/compiled/volt' . DS;
$mkdirRes = Common::mkdir($voltConfig['compiledPath']);
if (!$mkdirRes) {
throw new \Exception('创建目录 ' . $voltConfig['compiledPath'] . ' 失败');
}
$viewEngineVolt->setOptions($voltConfig);
return $viewEngineVolt;
});
/**
* @desc 注册视图引擎php服务
* @author zhaoyang
* @date 2018年5月4日 下午5:29:15
*/
$di->setShared('viewEnginePhp', function (View $view, DI $di) {
$viewEnginePhp = new ViewEnginePhp($view, $di);
return $viewEnginePhp;
});
/**
* @desc 注册视图服务
* @author zhaoyang
* @date 2018年5月3日 下午10:52:37
*/
$di->set('view', function () {
// 获取config服务有多种方法,这是其二
$viewConfig = $this->getConfig()->services->view;
$viewDir = $viewConfig->view_path ?? APP_PATH . DEFAULT_MODULE . '/views' . DS;
if (isset($viewConfig->view_suffix)) {
$viewSuffixs = explode(',', $viewConfig->view_suffix);
} else {
$viewSuffixs = [
'volt'
];
}
if (isset($viewConfig->view_service)) {
$viewServices = explode(',', $viewConfig->view_service);
} else {
$viewServices = [
'viewEngineVolt'
];
}
$engines = [ ];
foreach ($viewSuffixs as $k => $v) {
$suffix = '.' . ltrim($v, '.');
$engines[$suffix] = $viewServices[$k] ?? $viewServices[0];
}
$view = new View();
// 设置视图路径
$view->setViewsDir($viewDir);
// 注册视图引擎
$view->registerEngines($engines);
// 如果不需要“生成显示到控制器布局”和“生成显示到主布局”,则关闭这两个渲染级别
$view->disableLevel([
View::LEVEL_LAYOUT => true,
View::LEVEL_MAIN_LAYOUT => true,
]);
return $view;
});
5、在app/home/controllers目录下创建视图控制器ViewController.php来测试这两个视图引擎。
<?php
/**
* @desc 测试视图
* @author zhaoyang
* @date 2018年5月4日 下午5:45:49
*/
namespace App\Home\Controllers;
use Phalcon\Mvc\Controller;
class ViewController extends Controller {
public function voltAction() {
$this->view->name = 'volt';
}
public function phpAction() {
$this->view->name = 'php';
}
}
6、在app/home/views目录下创建view目录(与控制器名对应),在view目录下创建两个模板。一个是volt.volt,这个使用的viewEngineVolt引擎,另一个是php.phtml模板,使用的是 viewEnginePhp引擎。
volt.volt模板
<!DOCTYPE html>
<html lang="zh-CN">
<head>
</head>
<body>
volt引擎:{{name}}<br/>
</body>
</html>
php.phtml模板
<!DOCTYPE html>
<html lang="zh-CN">
<head>
</head>
<body>
php引擎:<?= $name?><br/>
</body>
</html>
7、这时我们访问view控制器的php方法,可以看到如下结果
这时可以看到runtime目录下生成了目录,但没有文件,因为viewEnginePhp引擎使用php原生语法,不需要编译,再访问volt方法就可以看到编译文件了
这是访问volt方法的结果
这就是产生的编译文件
至此,视图引擎已经注册成功。这里注册了两个视图引擎,你也可以再添加或者减少视图引擎,比如home模块中只使用volt引擎,则只需要把位于app/home/config目录下的模块配置文件config.php中的’view_suffix’改成’volt’,’view_service’改成’viewEngineVolt’。如下图所示
不过这时如果再去访问php方法就会因为没有找到模板而没有任何输出。因为home模块配置文件会覆盖合并全局配置文件。所以home模块其实只注册了viewEngineVolt视图引擎。
至于volt视图引擎的具体语法,请查看官方文档。如果你觉得smarty模板引擎用的比较顺手,也可以尝试创建smarty模板引擎的适配器。