来源:http://trac.seagullproject.org/wiki/Howto/Templates/WorkingWithTemplates

如何使用模板

简介

Seagull默认提供了Flexy模板引擎,但是你可以换成喜欢的引擎之间切换,特别是当你要创建自己的主题时。

主要概念

  • Seagull遵循沿用已久的简化表现层和商业逻辑之间的关系传统方法–最理想的是没有关系或者是有一点点关系。把所有数据处理放在商务逻辑层(MVC模型),数据可以发送到表现层(MVC视图)并根据主题(外观主题)显示,为一部分客户端生成页面。目前Seagull提供两种使用Flexy主题,这些主题最终转化成XHTML输出到浏览器。
  • 一个主题包含一组文件夹,每一个文件夹包含它所代表模块的HTML模板。
  • Flexy将所有HTML模板编译成开发人员从末碰到的PHP脚本。

简单的模板语法

简单的Flexy模板语法,下面这个结构遍历了一组用户对象:

<tr class="{switchRowClass()}" flexy:foreach="results,key,valueObj">
    <td align="center"><input type="checkbox" name="frmDelete[]" value="{valueObj.id}"></td>
    <td>{valueObj.id}</td>
    <td>{valueObj.username}</td>
    <td>{valueObj.link_gid.name}</td>
    <td>{valueObj.email}</td>
</tr>

创建自己的主题

要创建你自己的主题最简单的方法是在theme目录中创建一个新的目录并把default模块的模板文件拷贝到你的新文件夹。

  • 创建一个新的主题文件:
seagull/www/themes/myTheme
  • 从这个目录拷贝default模块的模板文件
seagull/modules/default/templates

到你的新建主题目录

seagull/www/themes/myTheme/default
  • 复制样式和图像文件目录到你的主题目录。因为seagull不会对这些自定义的模板自动使用默认主题。

记住你不需要包含整个default目录,只需包含你计划修改的文件。

最明显的可以通过改变headr和footer模板和修改样式表实现。这些默认的模板在default的模板文件夹:

  • master.html: 主模板,它包含其它模板。
  • header.html: 包含所有的从<html>标签开始的HTML代码,包括<head>,一直到<body>标签之前。
  • banner.html: 包含从<body>开始到页头信息结束的所有HTML代码,如,你要在你的页面顶部放置的所有东西。
  • footer.html: 从' Powered by Seagull Framework' 往下的所有内容的HTML代码

启用你的新建主题

默认主题,通常匿名用户浏览你的站点时应用这个主题,是常规设置区段的一个设置。

惯例约定

  • 你可以在模板中包含模板
<flexy:include src="banner.html" />
  • 你可以使用HTML标签内循环遍历一个数组,如
<tr flexy:foreach="aPagedData[data],key,aValue">
  • 调用函数
<th>{translate(#Role#)}</th>
  • 调用全局配置文件中的键值来判断条件
 {if:conf[OrgMgr][enabled]}

查看Flexy文档以获得更多详细资料。

而且,Seagull习惯将表单对象作为一个关联数组传递给PHP

<tr>
    <td class="fieldName">{translate(#First Name#)}</td>
    <td align="left"><input name="user[first_name]" type="text" value="{user.first_name}" /></td>
</tr>
<tr>
    <td class="fieldName">{translate(#Last Name#)}</td>
    <td align="left"><input name="user[last_name]" type="text" value="{user.last_name}" /></td>
</tr>

然后在脚本中将他们转换成对象:

$input->user = (object)$req->get('user');

主题继承

很重要提一点就是Seagull允许你使用继承模型,换句话说,如果你想改变header和footer,只需在你的主题中定义这些模板,用它们替换default中的设置。因为其它的任何主题不能在你的主题中显示,只有default会被使用。

FlexyStrategy.php文件中的下列代码片断解释了Flexy模板的继承规则,列表中的第一个元素具有最高的优先级。

$options = array(
                       // the current module's templates dir from the custom theme
'templateDir'       => SGL_THEME_DIR . '/' . $data->theme . '/' . $data->moduleName . PATH_SEPARATOR .

                       // the default template dir from the custom theme
                       SGL_THEME_DIR . '/' . $data->theme . '/default'. PATH_SEPARATOR .

                       // the current module's templates dir from the default theme
                       SGL_MOD_DIR . '/'. $data->moduleName . '/templates' . PATH_SEPARATOR .

                       // the default template dir from the default theme
                       SGL_MOD_DIR . '/default/templates',

为某个manager设置主题

从Seagull 0.6.3 版本开始你可以为某个manager设置特定的主题,如下 [FooMgr] requiresAuth = false showUntranslated = false theme = my_theme

修改翻译过的字符串

用户界面中所有字符串是以下列格式进行翻译过的:

<th width="5%">{translate(#disable#)}</th>

可以通过指定一个PHP函数作为第二个参数来修改,如

<th width="5%">{translate(#disable#,#ucfirst#)}</th>

扩展性

你可以定义你自己的要在模板中使用的方法,查看Howto/Templates/Flexy/Plugins。不要忘了参考Alan K的Flexy完全测试程序

NB:感谢Harry收集了大量的PHP模板引擎

调试

一个非常有用的技巧来查看到底输出到模板什么内容:

  • 查看整个输出对象,可以放在模板中的任何地方
{t:r}
  • 检查一个特殊的属性,数组或对象,可以放在变量初始化后的任何地方,如,在一个foreach循环中:
{myObject:r}

在语言字符串中使用变量

在0.6版本中printf方法可以在模板中的任何地方调用。

应用实例:

{printf(#User %s registered successfully. The password sent to email %s#,user[name],user[email])}

或同样的方法也可以用在translation方法中。假设键

'user registered successfully' ⇒ 'User %s registered successfully. The password sent to email %s'

'user registered successfully' => 'User %1 registered successfully. The password sent to email %2'

或 - translators的最好最简单的读取方法

 $words['user %name registered successfully. The password sent to email %email'] =
  'User %name registered successfully. The password sent to email %email';

你可以调用:

{translate(#user %name registered successfully. The password sent to email %email#,#vprintf#,user)}

where user is an array of arguments you want to be replaced in your translation string e.g. user是一个存放翻译字符串的数组参数,如$username?, $useremail?

Javascript

Flexy不能使用在<script>标签内部。你可以在这里找到解决办法http://blog.iworks.at/?/archives/2_Javascript__Flexy.html

你可以像Flexy手册说的那样使用<flexy:toJavascript>。不幸的是你不能传递Flexy函数(像translate())给flexy:toJavascript。因此你必须使用下列解决办法,如果你想翻译出错信息。

<div id="alertPleaseWait" class="hide">{translate(#Please wait while document uploads#)}</div>
<script type='text/javascript'>
    /* alert messages: */
    var alertPleaseWait = document.getElementById('alertPleaseWait').innerHTML;
 </script>

问题解决

PHP5 and overloading (Flexy)

如果你使用PHP5你可能想通过重载简化代码

PHP5类

class ModernObject {
    private $mySecret = array();

    public function __get($key) {
        if (isset($this->mySecret[$key])) {
            return $this->mySecret[$key];
        }
    }

    public function __set($key, $value) {
    	$this->mySecret[$key] = $value;
    }
    
    public function get($key) {
    	if (isset($this->mySecret[$key])) {
            return $this->mySecret[$key];
        }
    }
}

页控制器行为方法

function _cmd_list(&$input, &$output) {
    
    $mo = new ModernObject();
    
    //  works via ModernObject::__set()
    $mo->objOne = new BusinessFormatter();
    $mo->objTwo = new FunnyLibrary();

    $output->mo = $mo;
}

现在我们来看我们的这个新类能做什么

PHP5 使你可以做

$mo->get('objOne')->methodOfObjOne();

Flexy不可以

{mo.get(#objOne#).methodOfObjOne()}
<!-- results in a fatal error: unexpected something: () -->

你可能想用重载来解决,因为访问对象的属性本来就是正常使用的。

{mo.objOne.anyMethod()}

… 但不幸的是它不会成功的,事实上anyMethod()永远不会被调用 ,知道为什么吗?

查看编译后的模板文件我们会发现这样的代码:

<?php 

if ($this->options['strict']
|| (isset($t->mo->objOne) && method_exists($t->mo->objOne, 'anyMethod')))
    echo $t->mo->objOne->anyMethod();

?>

你可能会说那只是想像中的那种但是关键是isset($t→mo→objOne)值是false因为ModernObject没有具有public可见性的属性objOne,这阻止了调用anyMethod()。

我们可以在ModernObject类中提供另一个方法:

public function __isset($key) {
    return isset($this->mySecret[$key]);
}

这个方法的isset()(和 unset())只能在PHP0.5.1以上版本中使用。

 
howto/templates/workingwithtemplates.txt · 最后更改: 2010/05/30 00:21 (外部编辑)
 
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2