笔者的话:之前和几个朋友一起研究了一下PHP的Phalcon框架的几个组件的用法和源代码,做了一些笔记,拿出来和大家分享一下。
笔者水平有限,如有瑕疵请大家指正,我定会知错就改。
动态生成HTML标签
如果我们把一个网页的前端视图写好之后,其中的标签,样式等内容等同于被写死了,也就是说它不会根据后端处理后返回的不同状态而做出改变,这样这个视图就是一成不变的摆在了那里。这大大降低了网页的灵活性,使其变得很死板。 </br>而当我们用php动态的生成html标签,就可以在每次生成html标签之前设置判断条件,根据返回值再确定是否要生成这个标签输出给视图。在Phalcon中,Tag组件很好的实现了这些。
举例来说:假设有这样的一个网页,会显示用户的部分信息,比如用户昵称。如果用户没有填写过这些信息,那么会显示一个表单包含输入框和提交按钮。如果用户之前已经填写过这些信息了,则会将这些信息显示出来。
这样的话,如果这个页面的html标签是写死的,那么当用户已经填写过信息了,却还是会有一个提交按钮,这样的网页是不合格的。 所以我们就要用到动态生成html标签的方式,经过逻辑判断应该输出什么样的视图。
tag组件封装了一套生成html标签的函数,让使用者可以很简单的用php语言写出html标签。很大程度上减少了代码量,节省了开发者的时间。
因为tag组件生成的视图助手大多只需要传入某些参数就可以生成相应的html标签,这样方便了使用者,也就是说使用者并不需要掌握前后端语言,就可以根据某些配套的文档,按照自己的意愿修改参数,来得到自己想要的页面。(并且使用tag组件生成标签这种方式,在volt模板中做到了面向前端将前后端彻底分离,也就是说在前端视图文件中不会存在php的代码。)
举例来说:像新闻网站这样模式化的网页,不同的新闻模块除了题头和新闻内容外基本没有太大差异。如果我们使用html代码,就需要在每个模块都进行一次循环输出,造成代码重复,而且代码量也很大。这时我们可以自己做一个“视图助手”,专门用来根据模板题头循环输出相应的新闻内容。也就是说在前端我们只需要修改传给这个助手的参数就可以让不同的模块展示相应的新闻。这样极大减少了代码量,使得前端文件更加简洁。
使用tag组件的重要意义还在于,它将前端多种标签的样式规范化。
举例来说:当我们在做一个网站项目之前,为了保证各个页面之间的统一性,要定制好一套统一的样式,如果把这些页面的前端交给不同的程序员来写,由于各人的命名习惯和编码方式的差异,可能会造成同样的一个标签,由不同人写出的代码有很大不同。但是如果我们使用了Tag组件来生成标签,各个标签的样式是已经在组件中提前写好的,这样使用的话就保证了页面的统一性。
使用Tag组使得前后端的分工变得不那么分明,造成php与html代码混写。而且由于Tag组件是把大部分方法都封装在了一个类中,每次调用其中的方法时都需要把这个类全都加载进来,这增大了内存压力,降低了服务器性能。
(值得思考的是,我们能否在使用某个方法时,将其单独实例化,这样就解决了这个问题。)
长时间的使用会使得开发者对框架的依赖越来越大。
在controller层中,我们首要做的是设置文档类型
设置文档类型
在开始使用这些视图助手之前,我们要先确定视图文档的类型。因为不同的文档类型会导致其他html标签输出的格式不同,我们可以使用下面这个函数来确定文档类型。
<?php
use Phalcon\Tag;
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
public function indexAction(){
//其中的HTML5为tag中定义的常量
$this->tag->setDoctype(Tag::HTML5);
}
}
设置默认值
我们可以用tag组件来给某些元素设置默认值。下面我们用例子来说明一下这个用法
<?php
...
class IndexController extends Controller
{
public function indexAction(){
$this->tag->setDoctype(Tag::HTML5);
//给id为search的标签设置默认值为"请输入文字"
$this->tag->setDefault("search", "请输入文字");
}
}
这个例子会在下文视图层的使用中做出展示。
获取文档类型
设置好了文档类型,接下来要在输出标签之前获得文档类型,这个操作在../views/index/index.phtml文件中完成。
<?= $this->tag->getDoctype() ?>
<html>
<!-- 这里是html代码,tag生成的标签也在这个位置 -->
</html>
这样生成的html代码会是这样
<!DOCTYPE html>
<html>
<!-- 这里是html代码,tag生成的标签也在这个位置 -->
</html>
引入样式表和脚本文件
引入css样式表
<?= $this->tag->stylesheetLink("public/css/bootstrap.min.css");?>
对应的html代码
<link rel="stylesheet" type="text/css" href="/demo/public/css/bootstrap.min.css">
脚本文件的引入与之类似
<?=$this->tag->javascriptInclude("http://localhost/javascript/jquery.min.js", false);?>
对应的html代码
<script type="text/javascript" src="http://localhost/javascript/jquery.min.js"></script>
生成超链接
超链接是我们在页面中经常用到的标签,tag提供了生成超链接的方法
<?= $this->tag->linkTo("index/index", "Search") ?>
这样会生成下面这样的html代码
<a href="/demo/index/index">Search</a>
下面我们来给超链接设置css样式
<?= $this->tag->linkTo(array('index/index', 'Search', 'class' => 'the_link')) ?>
生成的html代码如下
<a href="/demo/index/index" class="the_link">Search</a>
除了使用css的类来设置样式之外,我们有时也需要单独设置某个属性,tag组件的每一个视图助手都可以接收一个数组,数组的第一个参数作为名称即id和name,其他的用于生成额外的HTML属性。
<?=$this->tag->textField(
array(
"price",
"size" => 20,
"maxlength" => 30,
"placeholder" => "Enter a price"
)
) ?>
生成的html代码如下
<input type="text" id="price" name="price" size="20" maxlength="30" placeholder="Enter a price">
接下来我们来看看另一个重要的标签——表单标签
<?= $this->tag->form("index/show") ?>
<label for="search">Search:</label>
<?= $this->tag->textField("search") ?>
<?= $this->tag->submitButton("Search") ?>
<?= $this->tag->endForm() ?>
可以看到,表单的使用是以两个tag方法作为开头和结尾,中间添加了表单控件,如输入框和按钮等。
对应的html代码如下
<!--这里的提交方式为post-->
<form method="post" action="/demo/index/show">
<label for="search">Search:</label>
<!--由于之前在controller中设置了id为search的默认值为"请输入文字",所以这里的value="请输入文字"-->
<input id="search" type="text" value="请输入文字" name="search">
<input type="submit" value="Search">
</form>
值得一说的是,这样的表单默认是提交post请求。如果要修改提交请求的方式,要对这个表单做如下修改
<?= $this->tag->form(array("index/show", "method" => "get")); ?>
<label for="search">Search:</label>
<?= $this->tag->textField("search"); ?>
<?= $this->tag->submitButton("Search"); ?>
<?= $this->tag->endForm() ?>
这样这个表单就变成了提交get请求。
生成选择菜单
下面我们来看一下选择框的使用,tag提供了Phalcon\Tag::select() 和 Phalcon\Tag::selectStatic()这两种生成选择框的方式,两种方式使用环境有所不同,接下来我们对比着看一下这两种用法。
Phalcon\Tag::select() 是专门设计与 Phalcon\Mvc\Model 一起使用,
Phalcon\Tag::selectStatic()则是与PHP数组一起使用。
Phalcon\Tag::select()的使用
<?= $this->tag->select(
array(
"productId",
Users::find("username = '[email protected]'"),
"using" => array("id", "creat_at")
)
);?>
对应html代码
<select id="productId" name="productId">
<option value="1">2016-01-20 13:01:46</option>
<option value="2">2016-01-20 13:05:20</option>
<option value="3">2016-01-20 13:24:23</option>
<option value="4">2016-01-20 13:39:43</option>
</select>
这个函数调用了model层,根据要求从数据库中取到了数据,作为选择菜单的选项。
Phalcon\Tag::selectStatic()的使用
<?= $this->tag->selectStatic(
array(
"status",
array(
"male" => "男",
"female" => "女",
)
)
);?>
对应的html代码
<select id="status" name="status">
<option value="male">男</option>
<option value="female">女</option>
</select>
在某些情况下我们需要给选择菜单添加一个空值,防止用户没有选择的时候却有值传给后端造成不必要的麻烦,这时我们就要把上边的代码做如下修改
<?= $this->tag->select(
array(
"productId",
Users::find("username = '[email protected]'"),
"using" => array("id", "creat_at")
'useEmpty' => true,
'emptyText' => 'Please, choose one...',
'emptyValue' => '@'
)
);?>
到这里我们已经了解并掌握了Tag组件的常用的视图助手的使用方法,其他的视图助手我们可以参考官方文档,再进一步掌握。
为了应付各种环境的需求,除了Phalcon提供的视图助手,我们可以自己做一个视图助手,下面我们来做一个属于自己的视图助手。
自动播放背景音乐的视图助手
虽然我们已经建立好了视图助手的文件,但是它还没有被自动加载,在开始写视图助手的代码之前,我们要修改一下/public/index.php中的一段代码,将这个文件自动加载到我们项目中。代码如下:
<?php
...
$loader = new Loader();
$loader->registerDirs(
array(
'../app/controllers/',
'../app/models/',
//增加自定义视图助手的路径
'../app/myhelpers'
)
)->register();
ps:从这里我们也可以知道,当我们自己为项目增添组件的时候,也要在这里增加组件路径,把组件自动加载到项目中
准备工作完成了,下面该写我们视图助手的代码了
<?php
use Phalcon\Tag;
class MyTags extends Tag
{
static public function audioField($parameters)
{
// 判断传入的参数,如果不是数组的话,则把其转化为数组
if (!is_array($parameters)) {
$parameters = array($parameters);
}
// 设置id和name属性,使其为数组中的第一个参数
if (!isset($parameters[0])) {
$parameters[0] = $parameters["id"];
}
$id = $parameters[0];
if (!isset($parameters["name"])) {
$parameters["name"] = $id;
} else {
if (!$parameters["name"]) {
$parameters["name"] = $id;
}
}
// 设置value值(也可以使用\Phalcon\Tag::setDefault()设置默认值)
if (isset($parameters["value"])) {
$value = $parameters["value"];
unset($parameters["value"]);
} else {
$value = self::getValue($id);
}
//设置自动播放
$parameters["autoplay"] = 'autoplay';
// 生成html代码,即把传入的数组中的参数格式化为html代码
$code = '<audio id="'.$id.'" value="'.$value.'" ';
foreach ($parameters as $key => $attributeValue) {
if (!is_integer($key)) {
$code.= $key.'="'.$attributeValue.'" ';
}
}
$code.="/></audio>";
return $code;
}
}
这段代码很好理解,就是将传入的参数,以数组的方式给不同的html属性赋值,最后再将这些属性格式化成html的代码,输出给视图。
这样我们已经揭开了Tag神秘的面纱,它的原理就是这样简单。
使用这个视图助手
<?= MyTags::audioField(
array(
'name' => 'test',
'id' => 'audio_test',
//本例将音乐放在了/public/music/文件夹中,音乐文件命名为audio.mp3
'src' => '/demo/public/music/audio.mp3',
)
); ?>
对应的html代码
<audio id="audio_test" value="" name="test" src="/demo/public/music/audio.mp3" autoplay="autoplay"></audio>
循环输出新闻的视图助手
代码如下
static public function newsShow($parameters,$style)
{
$id = $parameters;
$name = $parameters;
$news = News::find("title = '$parameters'");
for ($i = 0; $i < 4; $i++) {
$new = $news[$i];
$sh = $new->news;
$code = '<p id="' . $id . '" ';
$code .= 'id' . '="' . $id . '" ';
$code .= 'name' . '="' . $name . '" ';
foreach ($style as $key => $attributeValue) {
if (!is_integer($key)) {
$code.= $key.'="'.$attributeValue.'" ';
}
}
$code .= "/>$sh</p>";
echo $code;
}
}
看出我们根据传入的第一个参数在数据库中查询这个参数所对应的新闻,然后做了一步限制,只输出4条新闻。第二个输入的参数为一个数组,数组中的键值对对应相应的元素和属性值。
(这个视图助手只是简单的实现了之前例子里的功能,你可以为其增加一些功能,完善它。)
使用方法
<?= MyTags::newsShow('sport', array(
//这里设置了背景颜色
'style'=> 'background:#FFB6C1'
));?>
对应的html代码
<p id="sport" name="sport" style="background:#FFB6C1">hello world</p>