简化 HTML 页面和表格设计
这一章介绍了又一个节约你的时间并且使你的代码更具安全性和逻辑性的领域。
第一,咱们将会介绍建立视图的各类不一样方法-与你的控制器和模型协同并用来显示结果的页面。
而后,你将会学到如何很快地建立 HTML 表格, 与实现内建的保护; 并且你也将会看到该如何校验你的表格。
我假定这本书的读者熟悉 HTML 和 CSS 。 下列的例子很是简单,所以,咱们能把重点放在 CI 代码上。 并且我已经假定咱们已经写一个 CSS 文件并已把它保存在网站的某个目录中。
编写视图
视图是用户用户能看到你的网站的全部。 他们使用一个统一的接口, 并且能够根据须要进行修改。 MVC 的好处之一是你分开了表示层和逻辑层, 一切都显得很干净。
到如今为止, 咱们已经完成了那很是简单的 'welcome' 页面,(记得第 3 章吗?) 如今让咱们看看该如何使它变得更精细。
视图其实是一组包含有你的内容的HTML结构。结构中有各类元素,如颜色,字体,文字布局等; 不过视图不关心这些,它要作的只是取来内容,显示出来。
建立视图, 首先你须要建立一个HTML 网页的骨架,并保存为.php后缀。 让咱们称它为 basic_view.php 。保存在application/views目录中。 (CI的loader会在这个目录寻找视图文件。)
<html>
<head>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
而后当你想要从一个控制器装载它时, 使用在某个函数中调用$this->load->view():
function index() {
$this->load->view('basic_view');
}
注意,若是这是一个model或者一个helper,你将会首先装载它, 而后根据须要使用它。 经过视图,调用它只须要一行代码。
固然,那是一个空的视图。 为了要使它有用,咱们须要内容。所以咱们要增长名称和一些文本。 首先咱们在控制器中定义他们:
function() {
$data['mytitle'] = "A website monitoring tool";
$data['mytext'] = "This website helps you to keep track of the other websites you control";
}
注意咱们并无把它们定义为单独的变量, 而是做为数组$data的元素。 对于第一个元素, 键名是 'mytitle',值是 "A website monitoring tool".
而后,咱们调用装载函数:
function index() {
$data['mytitle'] = "A website monitoring tool";
$data['mytext'] = "This website helps you to keep track of the other websites you control.";
$this->load->view('basic_view',$data);
}
咱们把$data数组做为$this->load->view()的第二个叁数,在视图名称以后。视图接收到$data数组后,使用PHP函数extract()把数组中的每一个元素转换成内存变量,数组的键名即为变量名,值为变量内所包含的值。这些变量的值能直接被视图引用:
<html>
<head>
</head>
<body>
<h1 class='test'><?php echo $mytitle; ?></h1>
<p class='test'><?php echo $mytext; ?></p>
</body>
</html>
虽然你只能传送一个变量到视图, 可是经过创建数组,你能把大量变量整洁地传入视图。它彷佛复杂, 可是其实是一种紧凑和优秀的信息传输方式。
PHP标记的长格式和短格式
在咱们继续以前, 先了解一下PHP标记的两种不一样格式。
经常使用的方式是:
<?php echo $somevariable?>
然而,若是你不喜欢这种, CI 也支持一个较短的版本:
<?=$somevariable?>
<?php ?>被<??>取代,并且echo由“=”代替,你也能用短格式来使用if, for, foreach, 和while循环。完整的介绍请参考在线用户手册。
我我的偏好标准格式,由于我已习惯使用它。若是你使用短格式,注意有些服务器不能正确地解释短格式。 若是你仍然想要使用短标签, 能够打开 config 文件, 改变下列设置:
$config['rewrite_short_tags']= FALSE;
如设置为TRUE,CI在把它们送到服务器以前,将把短格式改为标准格式。 不过这样作会对调试形成困难。所以,建议使用标准格式。
CI 也有一个 '模板语法分析器' 类,容许你把变量放入HTML代码而不须要任何的PHP代码。本文不涉及这个内容。若是在与可能被 PHP 代码弄糊涂的 HTML 设计者合做,它至关有用,细节请参见用户手册。
嵌套视图
为了最大程度地重用代码,咱们能够提取HTML页面的公共部分,例如,header和footer,而后在显示实际视图时把它们组合起来。
让咱们建立一个视图的header部分, 这是一个符合W3C标准的header、包含HTML声明和 meta数据。
首先, 咱们列出header部分的代码:
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 strict//EN'http://www.w3.org/TR/xhtml1/DTD/xhtml-strict.dtd'>< html xmlns='http://www.w3.org/1999/xhtml'>
<title><?php echo $mywebtitle?></title>
<base href=<?php echo "$base"; ?>>
<?php echo $myrobots?>
<link=" stylesheet" type="text/css" href="<?php echo "$base/$css;?>">
把这保存为views/header_view. 下面介绍它包含的变量:
。$mywebtitle, 是标题 (meta标签; 这将不在屏幕上出现,可是搜索引擎将会读取,每一个页面的meta有可能有变化,所以,我把它设为一个变量。)
。$myrobots, 这个变量用来告诉机器人当前页面不须要被编入索引。
。$base和 $css, 描述基本网址的字符串。$css包含css文件的路径信息, 这些信息会从CI的config 文件读取(也能够用 CI config 变量 site_url代替。)
如今咱们须要知道:
。咱们如何调用嵌套视图?
。咱们如何获取变量的值?
有二个方法可选择。 第一,在主调用视图中读入其它视图,所以咱们的主视图,也就是basic_view,应该加上一行:
<html><head>
<?php $this->load->view ('header_view'); ?>
</head><body>
<?php echo $mytitle; ?>
<?php echo $mytext; ?>
</>
</html>
变量能够在控制器中加上两行:
function index() {
$data['mytitle'] = "A website monitoring tool";
$data['mytext'] = "This website helps you to keep
track of the other websites you control.";
$data['myrobots'] = '<meta name="robots" content
="noindex,nofollow">';
$data['mywebtitle'] = 'Web monitoring tool';
$data['base'] = $this->config->item('base_url');
$data['css'] = $this->config->item('css');
$this->load->view('basic_view',$data);
}
在这里新的变量 $myrobots,$css, $base, $mywebtitle被建立为数组$data的新元素,当header_view被basic_view调用时,CI使用extract()解开他们, 在视图中显示出来(在两个视图中不要出现同名的变量,不然会引发冲突)。
第二个方法将把视图加入控制器里面, 给它分配一个变量:
function index() {
$data['mytitle'] = "A website monitoring tool";
$data['mytext'] = "This website helps you to keep
track of the other websites you control.";
$data['myrobots'] = '<meta name="robots" content
="noindex,nofollow">';
$data['mywebtitle'] = 'Web monitoring tool';
$data['base'] = $this->config->item('base_url');
$data['css'] = $this->config->item('css');
$data['header'] = $this->load->view('header_view', '', TRUE);
$this->load->view('basic_view',$data);
}
从严格的 MVC 设计原则来看,这样作彷佛更正确。
实际上有三个叁数可传给load->view函数。
。 第一个, header_view, 是要装载的视图的名字。 这是必选。
。 第二个,是可选项, 是装入视图的数据。
。 第三个是布尔值。若是你不指定它,默认是FALSE, 将视图送到浏览器。 然而,在嵌套视图这种状况下,你须要将header_view送到主视图basic_view中,所以须要将第三项参数设置为TRUE。
如今咱们已经创建了与 stylesheet 的关联, 咱们可以用定义好的css中的类来更新视图中的显示部分:
<html><head>
<?php $this->load->view('header_view'); ?>
</head><body>
<h1 class='test'><?php echo $mytitle; ?></h1>
<p class='test'><?php echo $mytext; ?></p>
</body>
</html>
请注意CI的 MVC 系统能让你分离显示的内容。 视图只为内容提供结构, 结构的风格则由css stylesheet控制。
视图不关心什么 $mytext的内容是什么,它只是按照正确的格式在正确的位置上显示它。 定义 $mytext 的控制器甚至不知道 (也不关心) 它产生的数据如何被显示。
所以, 若是咱们须要改变咱们网页的外观, 或在一个不一样的系统 (如WAP)上显示他们,那么咱们只须要改变视图和CSS stylesheet。 咱们不须要修改控制器。
并且若是咱们想要改变在网页上的信息,咱们不须要去改动视图, 而是只须要改变控制器里的变量值。
记得 '松藕合' 原则吗? 这里再一次体会到了这个原则,这使设计,升级, 和维持你的网站比较容易。
网站结构的现实问题
请稍等片刻,咱们在header_view动态地生成了 CSS stylesheet地址:
<link="stylesheet" type="text/css" href="<?php echo "$base/$css";?>">
这意味着控制器必须生成变量的值,这些值与数据如何被显示有关, 可是咱们在上面说过控制器不该该知道或者关心它们具体的值是什么。这样不就符合了咱们刚才说起的所谓'松藕合'原则? 动态地产生这些数据须要这样一些操做: 首先,控制器必须在 config 文件中读取它们,而后控制器必须在$data数组中装入它们并且传送它们到视图,而后视图必须解开成为内存变量$base和$css, 真正使用这两个变量的是HTML协议。
彷佛这样作太绕圈子了,为何不直接在视图中静止地插入数据?
<link="stylesheet" type="text/css" href="http://www.mysite.com/mystylesheet.css";">
用变量方式作这件事情的好处是:若是你迁移网站, 或移动你的 CSS 文件,你只须要在 config 文件中改变设置,并且每一个控制器和视图将会马上反映变化。 而若是把CSS位置硬编码到每一个视图的后果是一旦须要变化,你必须到每一个视图中去修改它们,明白这样作的好处了吧?
CI 的表格助手: 录入数据
让咱们把目光转向你如何使用你的 HTML 页。任何动态的网站最重要部份之一是和用户互动,并且这一般意味着使用 HTML 表格。 编写表格是重复和无聊的。
CI 的表格助手是密码的很是有用的代码片段。 它有一个稍稍不一样的定义, 使表格建立起来比较容易。 让咱们创建一个表格,这个表格容许咱们在浏览器中录入数据。 在websites数据库的sites表中,咱们想要录入网站的名字、类型和网址, 和更新的日期。
你能用简单的 HTML代码 创建表格, 或你能在一个控制器内创建它,把它赋给一个变量, 而后调用视图, 并且传送该变量到视图。 我正在按第二种方式作。
第一,咱们必须装载表格助手到咱们须要使用它的控制器内。 而后, 咱们把下列的代码放入控制器的构造函数:
$this->load->helper('form');
而后,咱们必须开始编写表格。
如今, 为了生成表格的输入项, 咱们不用这样写:
$variable .= <input type='text' name='name' value=''>
CI 让你这样作:
$variable .= form_input('name','');
(记得'name'是输入项的名称, 'value'是你想输入的内容。 在这里能够设定value的初始值,或你能动态地从表格中获取.)
能够看到,使用CI的表格助手列方便。
使用表格助手的好处之一: 清楚
使用 CI 表格助手的第一个利益是你的代码绝对的清楚。 若是你想要一个比较精细的输入框, 若是用HTML是这样的:
$variable = 'input type="text" name=" url" id="url" value=" www.mysite.com" maxlength="100" size="50" style="yellow"/>';
name是将在$_POST数组中取得的变量名称。
id是在网页上定位这个输入框的标识符,若是你使用JavaScript的话。
value是输入框里显示的值,它一开始是一个默认值,用户也能够在输入一个新的值。
maxlength 和size是明显的; style一组 HTML 格式或者在css stylesheet 中定义。)
CI 用一个数组代替上述的HTML代码:
$data = array(
'name' => 'url',
'id' => 'url',
'value' => 'www.mysite.com',
'maxlength'=> '100',
'size' => '50',
'style' => 'yellow',
);
$variable = form_input($data);
它看上去蛮长的, 实际上并不比HTML代码长,并且,它很是清楚, 容易理解和维护。并且是动态的。
隐藏的表格输入框很是简单。若是咱们想要自动地记录咱们的数据库被更新的日期。 咱们把日期放入一个$date变量, 而后:
form_hidden('updated', $date);
若是你想要一个'文本'输入框, 给你的使用者提供一个能够输入超过一行的地方,可使用CI的form_textarea()函数,下面的代码使用默认的长度,在网页上显示一个文件输入框:
$data = array(
'name' => 'url',
'id' => 'url',
'value' => 'www.mysite.com',
);
$variable = form_textarea($data);
CI的表格助手在你编写下拉框,多选框和单选框时特别有用,若是咱们要改变咱们的URL输入框为一个下拉框,容许用户从下拉列表中选取一个URL。首先,把下拉列表的选项存入一个数组,而后调用form_dropdown()函数:
$urlarray= array(
'1' => 'www.this.com',
'2' => 'www.that.com',
'3' => 'www.theother.com',
);
$variable = form_dropdown('url' 、 $urlarray, '1');
被传给表格中url下拉框的第一个参数是输入框的名字; 第二个是包含下拉列表的数组,第三个默认选项。 换句话说,若是使用者接受默认值, 你的 $_POST数组将会包含值 'url=>1' ,可是你的用户将会见到选项 'www.this.com'.
若是使用HTML代码编写:
<select name="type">
<option value="1" selected>www.this.com</option>
<option value="2">www.that.com</option>
<option value="3">www.theother.com</option>
</select>
CI实现的代码实际上比较短, 很容易学会。
若是你在一个数据库表('urls')中储存你的可能选择的网址的目录,那么生成一个动态下拉框很容易。 首先把数据从表中读出放到一个数组中:
$urlarray = array();
$this->db->select('id,url');
$query = $this->db->get('urls');
if ($query->num_rows()>0) {
foreach($query->result() as $row) {
$urlarray[$row->id] = $row->url;
}
}
而后重复咱们之前用过的 CI form_dropdown() 功能:
echo form_dropdown('type', $urlarray,'1');
只有$urlarray 的内容会发生变化; 代码老是同样的。
若是你正在更新一个表中的记录而不是插入, 你不想为你的用户显示默认值。你想要为那一个记录显示已经存在的值。你应该已经知道你想要的修改的记录的id值,所以,你须要先读取数据库中'site'表中相关记录。肯定把查询结果赋给一个变量,使用第二个变量取出第一个变量的中的相关记录, 再调用CI的form_dropdown函数,把第二个变量和对应的列名做为参数传入:
$this->db->select('id, url, name');
$this->db->where('id','$id');
$sitequery = $this->db->get('sites');
$siterow = $sitequery->row();
而后你的 CI 下拉框函数会从中读取相关信息:
echo form_dropdown('url' 、 $urlarray, $siterow->url);
本书没有太多的篇幅讨论全部的表格助手。 它还能编写单选框,隐藏文件框,多选框和一些其它的输入框,完整的资料请参考CI用户手册。
表格助手的好处之二: 自动化
使用表格助手的第二个好处是能够自动化实现一些功能,否则的话,你只能本身编写相关的脚本了。
首先, 它拦截HTML的一些字符,好比用户输入的引号,而且转义它们以避免破坏表格。
其次,它自动链接。当你打开一个表格时,你必须声明目标页,它将会接受表格的数据而且处理它。(在CI中,这是一个控制器里面的一个功能而不是一个静态页。 好比它指向控制器的更新函数.) 所以,若是你正在使用简单的 HTML 代码,你将会这样写:
<form method="post" action="http:/www.mysite.com/index.php/websites/update"/>
若是你用 CI 打开你的表格,你只须要这样作:
form_open(websites/update);
CI 自动地在你的 config 文件中取出基本URL并定位到对应的控制器函数。 再次强调,若是你迁移你的网站,你只须要修改config文件,而不是去一个一个地修改代码文件。
顺便提一下, CI 假定你的表格将会老是以POST的方式提交数据而不是GET方式。CI广泛使用URL自己,所以,不要搞错。
个人 '显示' 模型
做为示范(稍微简化了一下),这里是个人显示模型:
<?php
class Display extends Model {
/*create the array to pass to the views*/
var $data = array();
/*two other class variables*/
var $base;
var $status = '';
/*
the constructor function: this calls the 'model' parent class, loads other CI libraries and helpers it requires, and dynamically sets variables
*/
function Display()
{
parent::Model();
$this->load->helper('form');
$this->load->library('user_agent');
$this->load->library('errors');
$this->load->library('menu');
$this->load->library('session');
/*now set the standard parts of the array*/
$this->data['css'] = $this->config->item('css');
$this->data['base'] = $this->config->item('base_url');
$this->base = $this->config->item('base_url');
$this->data['myrobots'] = '<meta name="robots"
c>';
/*
note that CI's session stuff doesn't automatically recall the extra variables you have added, so you have to look up the user's status in the ci_sessions table
*/
$sessionid = $this->session->userdata('session_id');
$this->db->select('status');
$this->db->where('session_id', $sessionid);
$query = $this->db->get('ci_sessions');
if ($query->num_rows() > 0)
{
$row = $query->row();
$this->status = $row->status;
}
}
/*
function to assemble a standard page. Any controller can call this. Just supply as $mydata an array, of key/value pairs for the contents you want the view to display. Available variables in this view are:
mytitle. menu, mytext, diagnostic
*/
function mainpage($mydata)
{
$this->data['mytitle'] = 'Monitoring website';
$this->data['diagnostic'] = $diagnostic;
foreach($mydata as $key => $variable)
{$this->data[$key] = $variable;}
/*here's the menu class we looked at in Chapter 3*/
$fred = new menu;
$this->load->library('session');
$mysess = $this->session->userdata('session_id');
if(isset($this->status) && $this->status > 0)
{$this->data['menu']=
$fred->show_menu($this->status);}
$this->load->view('basic_view', $this->data);
}
}
?>
我能用下面的代码在任何的控制器中调用这个主页:
$this->load->model('display');
$this->display->mainpage($data);
而且我也知道个人视图正在被动态地装配,彻底符合个人须要。
CI 的校验类: 方便地检验数据
在你编写HTML表格时一个重要的工做是检查输入。咱们都知道咱们应该这样作,可是…直到如今为止,咱们已经编写过一种简单的表格, 将会信任地接受任何用户输入的任何数据。 你应该意识到可能有一些用户是不怀好意的,并且全部的其他都是不负责任的。(别直接告诉他们.) 若是他们有可能犯一个简单的错误,他们就会犯。确保你始终检查用户输入的数据,并使它们符合你的要求。
你能在客户端用javascript作到这一点, 可是这样作做用有限,使用者能容易地绕过它。 而在服务器端的校验须要一个额外的信息来回,这点额外的开销是值得的。
编写校验代码也至关复杂, 可是-你必定猜到了-CI 提供了一个校验类可使这项工做变得很是容易。
让咱们改变咱们本身的表格处理过程来实现校验。 你须要在表格里做一些调整, 还要在它指向的函数里做一些调整。
若是你的表格由 form_open('sites/update') 开始, 你须要修改的函数是'sites控制器里的'update'函数。 若是你没有使用 CI 的表格助手, HTML等价代码是:
<form method="post" action="http://www.mysite.com/index.php/sites/update"/>
你须要作三件事情:
1. 设置校验
2. 设置控制器
3. 设置表格
设置校验
在你的表格指定的那个函数中装载校验类并声明你的校验规则:
$this->load->library('validation');
$rules['url'] = "required";
$rules['name'] = "required";
$this->validation->set_rules($rules);
'url'和 'name'输入框必定要有输入内容。 CI提供了各类操做,确保一些操做必定要进行,用户手册全面地解释了这些内容。 他们的含义很是明了: min_length[6] 显然意味着输入的信息长度必定要大于等于六个字符。numeric意味着只能输入数字,等等。你还能组合规则,用“|”把它们链接起来:
$rules['name'] = "required |alpha| max_length[12]";
意味着不能为空,字母,长度至少12个字符。你甚至能编写你本身的规则。
设置控制器
仍然在相同的函数中,建立一个 'if/else'语句:
if ($this->validation->run() == FALSE) {
$this->load->view('myform');
} else {
$this->load->view('success');
}
你进行确认测试,并且若是输入内容不能经过测试的话,就再返回到输入页面。(若是你在一个控制器内的一个函数中生成你的视图, 则使用$this->myfunction 代替$this->load->view('myform')。
若是校验成功,就生成view("success"),告诉用户输入的信息已被接受, 而后给出一个连接让他进到下一步。
设置表格
录入信息的表格也要作相应的调整。 每次校验没有经过的话,你不但要让系统返回到录入界面,并且必须说明哪一项出错, 以及为何出错。 所以你必须在表格的某处给出一个附加信息:
$this->validation->error_string;
这行代码显示适当的信息, 避免用户在那里犯嘀咕。
你也须要自动地填写用户已正确输入的那些内容,不然,用户必须再次录入上一次他们已经正确录入的信息。
首先,你须要在控制器里增长更多的代码。并且是马上加在校验规则以后,加入一个数组来存放给用户的提示信息。 数组的键名是你表格中的输入框名,值是给出的错误提示信息:
$fields['url'] = '你的网址';
而后,增长一行代码:
$this->validation->set_fields($fields);
如今你已经在控制器里声明了一个存有信息的数组,你只须要在表格内加入显示它们的代码。 对于HTML代码,这会是:
<input type="text" name="url" value="<?php echo $this->validation->url; ?>"/>
或, 若是你正在使用 CI 的表格助手:
$variable .= form_input('url', "$this->valication->url");
若是使用这个表格插入一个新的记录到数据库的表中,上面的代码已经够用了。若是你正在使用表格更新一个已经输入过的记录,当表格第一次显示时,应该在输入框中显示数据库表中的实际信息,这个时候,它的值应该是从数据库里读回来的(记得前面的例子吗?咱们把代码再显示在这里:
$this->db->select('id, url, name');
$this->db->where('id','$id');
$sitequery = $this->db->get('sites');
$siterow = $sitequery->row();
echo form_dropdown('url' 、 $urlarray, $siterow->url);
若是你在更新一个现有的记录时,上一次的录入内容因为一个输入框内容没有录入而没法经过校验,在从新回到表格以前,你须要在经过校验的输入框中填写用户刚录入的信息,而在校验出错的输入框里再次放入从数据库表中读入的信息,不然,你就须要再次录入已经校验经过的信息了。
还好,这能够经过一个简单的“if/else”语句来实现:
if (isset($_post['url'])) {
$myvalue=$this->validation->url;
} else {
$myvalue=$siterow->url;
}
第一次表格显示的时候,在$_POST数组中将会没有内容; 所以你从数据库的相关表中读取信息。但当你提交一次之后,$_POAT数组中有数据存在,因此你选择validation函数中返回的值。
查阅CI用户手册,了解表格校验的其它内容,你还能够作到:
。自动地准备你的数据, 举例来讲, 经过它消除可能产生的跨站脚本攻击
。编写你本身的复杂校验标准,举例来讲, 用户录入的值不能已经存在于数据库中
。编写你本身的错误信息
CI的校验类很是有用而又功能强大,值得花时间好好研读并掌握。
摘要
咱们已经学习了CI中生成视图的方法, 以及它如何让你建立'迷你-视图', 你能把视图嵌套到其它视图中去。这意谓你能创建共用的HTML header,HTML footer, 实现视图的重用。
咱们也已经见到 CI 如何帮助你编写 HTML 录入表格,经过表格助手函数简化HTML form的编写工做。
最后,咱们学习了 CI 的校验类,这是检查用户录入信息的有用工具。没有什么是完美的,可是这个工具的确能阻击你的用户录入垃圾,或企图进行攻击。它也使你的网站看起来更加专业,可以有效地捕捉用户形成的各类输入错误,而不是一味地接受无心义的输入。
在整个学习过程当中,咱们也再次玩味了MVC的原则, 并且有时稍稍地作一些变通会让生活变得更容易。 CI 有一种很是有柔性的哲学: 若是要有效率地解决问题,就要学会灵活地使用工具。
javascript