分析网站结构
既然我们已经安装 CI ,我们开始了解它如何工作。
读者已经知道 CI 实现了MVC式样。 通过对目录和文件的内容进行分类, 而不是让代码大块大块地纠集在一起。
这一章,我们将会对 MVC 理论做个简短的介绍, 然后再介绍 CI 的MVC实现方式。特别地,要了解那些目录和文件如何互相交换信息?网站结构是怎样的?以及CI是如何自如地动作于其中的?
这一章将会介绍:
。MVC 如何架构一个动态网站
。CI如何接收和分析request以及如何调配指定的代码来reponse
。这些指定的代码如何编制
。CodeIgniter 语法
。CI提供的各种类和函数,你自己编写的类和函数
。如控向controllers传递URL参数
。如何编写运行良好的视图并把动态内容传递给它们。
。如何返回信息给上网者
。文件和类如何传递信息和互相调用
。助手类文件有什么用?
。有助于网站设计的一些特别提示
MVC-到底有什么用?
MVC,在本文领域内,指的是一个动态网站的组织方法。 设计模式是1979年由挪威人,Trygve Reenskaug首次提出来的,这里是一些概要:
。模型是包含数据的对象,他们与数据库交互,对这些数据进行存取,使其在不同的阶段包含不同的值,不同的值代表了不同的状态,具有特定的含意。
。视图显示模型的状态,他们负责向使用者显示数据。(虽然他们通常是 HMTL 视图, 但是,他们可能是任何形式的接口。 比如PDA屏幕或WAP手机屏幕)
。控制器用来改变模型的状态,他们操作模型,提供动态的数据给视图。
CI框架包含模型、视图和控制器的子目录。 他们里面的每个文件都有.php文件后缀, 包含有特定命名约定的类。
CI 帮助你遵循MVC的约定, 使你更有效地组织代码。 CI允许你有最大的灵活性,你可以获得 MVC 结构的所有好处。
当你编程的時候,试着始终用 MVC 来思考问题。尽可能确保你的 '视图' 聚焦于显示, '控制器'纯粹地用来控制数据流。 把应用逻辑保留在数据模型和数据库中。
这样,如果你决定开发新的视图,你不必在任何一个控制器或模型中修改代码。 如果你需要更新 '商业规则' ,你只需要在模型中修改代码。
另一方面,你必须认识到,MVC只是用来帮助你的一种设计方式,而不是用来约束你的。MVC可以有不同的实现方式。CI 论坛包含许多如何 '正确合理'地实现 MVC 的方式。 ( 我应该在控制器部分实现数据库查询功能吗?我能直接从视图发送数据到模型层吗?或者我必须通过控制器来访问?)
与其寻找理论上的正确方式,不如遵循二项有用的原则。 这些在 CI 用户手册上有相关描述:
。松藕合: 类之间尽可能不要彼此依赖。
。组件智能化: 智能化是组件独立实现特定目标的能力。在 CI框架中,每个类和它内部的函数高度地自治。
这些是Rick开发CI要实现的目标, 他们也会成为你开发你自己的网站时的目标。实现这些目标之后,你代码中使用这些类时就不需要担心有什么副作用了。
CI做到了这一点,我的经验是那助手类和类库中的其它类使用用起来十分容易,工作起来效果也不错。
因此, 如果你的控制器直接操作数据库, 或你的在模型层调用视图, CI 代码将会以适当的方式工作-通常没有技术上的问题-但是从MVC理论来看这样似乎是 '不正确的'. 不要烦恼,如果非要这样做,做吧!
CI 的网站结构: 控制器和视图
你的整个 CI 网站是动态的。 就是, 可能找不到制作 '静态' 网页的简单的 HTML 代码。 (如果需要你可以添加,但是他们将会在 CI 结构之外.) 那么, 你的网站文件到底在哪里?
当我们安装 CI 的时候,我们注意到应用目录包括名为models、views和controllers的子目录。 每个 CI 框架应用都包含这三大类型。
让我们看看内部细节。
再次强调我们并不处理静态网页和对应的URL,我们将会给你看CI如何分析URL请求和如何响应它。 首先,考虑一个正常的英特网请求。用户建立一个连接到你的网站: www.example.com,
然后经过端口发出一个如下的HTTP request:
GET /folder/file.html HTTP/1.0
GET是请求的类型, HTTP/1.0 指定 HTTP 协议的版本, 中间是相对路径和文件名。但是在你的网站上,找不到简单的静态 HTML 文件。取代它的,所有的收入请求被 index.php 文件拦截并进行处理。
如果使用者正在以正确的URL在你的网站上位置上请求页面-一般是通过点击你网页上的超级链接-request一般看起来象这样:
GET /index.php/tests/showall HTTP/1.0
如果使用者不知道精确的URL, CI 会设定一个默认页面(我们一会儿就告诉你怎么做.)
CI的处理步骤是:
+--------------------------------+
| internet request comes in: |
| "GET http://127.0.0.1" |
+--------------------------------+
|
v
+--------------------------------+
| Router:decides which controller|
| should handle this request |
+--------------------------------+
|
v
+--------------------------------+ +-------------------+
| Controller: analyzes the | -----> | |
| request and responds:maybe | |Model:provides data|
| by getting data from the model | >----- | |
+--------------------------------+ +-------------------+
|
v
+--------------------------------+
| View:formats the response |
| (in this case as an HTML page) |
+--------------------------------+
|
v
+--------------------------------+
| Page is served up to enquirer |
+--------------------------------+
一个从英特网到你的网站根目录的请求被 index.php 文件拦截,作用就象一个“站由器”。 换句话说, 它调用一个 '控制器', 然后返回一个'视图'.
“路由器”怎么知道调用哪一个控制器? 就象我们已经见到的,有时候request本身包含的信息会告诉它调用哪个控制器。 举例来说,如果请求说:
GET http://127.0.0.1/index.php/welcome/index
并且如果你有一个控制器叫做welcome,这就是被调用的控制器。
welcome控制器
所以, 让我们看welcome控制器。 它被存放在如下路径:
system/application/controllers/welcome.php
它的内容是这样的:
PHP复制代码
class Welcome extends Controller {
function Welcome() {
parent::Controller();
}
function index() {
$this->load->view('welcome_message');
}
}
?>
复制代码
文件的第二行开始是一个类。 每个控制器从一个Controller类继承。 在类中包含二个函数或称为方法-welcome() 和incex().
注:
CI 要求控制器名字从一个大写字母(class Welcome) 开始, 但文件名是小写字母:
/system/application/controllers/welcome.php。
PHP复制代码
function Welcome() {
parent::Controller();
}
复制代码
这三行组成构造函数。 注意到 CI 使用PHP 4 构造函数命名规则,兼容于 PHP 5.-CI在PHP 4 和PHP 5 两个版本中都能工作得很好。构造函数在类实例化时被调用,你可以做一些初始化的工作,比如调用函数库和模型层,或者对类的成员变量进行寝化。
这个例子中构造函数中仅一行,调用父类的构造函数。parent::Controller() 。这只是显式地使用父类功能的一种方法。如果你想要详细地了解CI框架中controller类,你可以研读文件 /system/libraries/controller.php 。
(可以放心的是你可以随时查看CI的源代码,它们已经保存在你机器上的某个目录内。)
让视图开始工作
让我们回到发出request那个部分。 “路由器”需要知道, 除了哪一个控制器应该处理请求, 而且要知道是哪一个控制器里面的哪一个函数。 那是为什么request中还包含了特定的action信息 http://127.0.0.1/welcome/index. “index”指示路由器寻找“welcome"控制器里的一个函数"index"。你要确保存在index函数!
来看看index()函数。这个函数只是用CI的装载函数(this->load->view)装入一个视图('welcome_view')。在现阶段,它不对视图任何操作,只是传递给你动态内容。稍后才会执行。
'welcome_view' 在CI中有特定的含义,实际上它指向了如下文件:
system/application/views/welcome_view.php
这个视图文件中只是一些简单的HTML代码,但是因为在稍后运行时CI会向文件里存入PHP编码,因此使用了PHP文件后缀。(如果只是使用简单的静态的HTML不需要修改后缀.)
下面是视图文件中HTML代码示例(作了精简处理):
HTML复制代码
Welcome to Code Igniter Welcome to Code Igniter!
The page you are looking at is being generated dynamically by Code Igniter.
If you would like to edit this page you'll find it located at:
system/application/views/welcome_message.php
If you are exploring Code Igniter for the very first time, you should start by reading the :
如果你担心机器人从你的网站搜集电子邮件并使用它们发垃圾邮件,用safe_mailto 代替 mailto。屏幕内容相同,并且工作也正常。但是如果检查你的HTML代码,现在变成了复杂的JS代码,机器人也许什么也抓不到。
JS复制代码
<script type="text/javascript">
//var l=new Array();
l[0]='>';l[1]='a';l[2]='/
';l[3]='<';
...
for(var i=l.length-1; i>=0; i=i-1){
if (l.substring(0,1)=='|')
document.write(""+unescape(l.substring(1))+";");
else document.write(unescape(l));}
//]]>
《script》
复制代码
你, 和你的用户,不需要看到这些代码。 它只是用来迷惑机器人的,以确保你的电子邮件地址的安全。而你只需要增加四个字母和一个下划线: 你用 safe_mailto 代替 mailto, CI框架为你做其它所有的一切。
在URL helper中有一些其它有用函数。请查阅用户手册。
总结一下URL helper符合我们在这一章开始时讨论的话题:
。松藕合: URL helper有一个简单的接口,不依赖调用它的代码。你可以在任何CI框架项目中使用它。许多项目需要许许多多的超链接,你可以使用这个helper一遍一遍地创建它们。
。组件智能化: URL helper只做它要做的事情, 简化对应的编码工作。
如果你要研读URL helper的代码,它们保存在system/application/helpers/
url_helper.php) 你将会见到它是过程式的代码-只是一组函数功能而不是OO类。 它不装载任何其他的 CI 类或helpers。(它本身不是对象,不能这样做)
一个简单的librariy例子: 创建一个菜单
现在让我们看一些在CI框架中实际使用的代码。
举例来说,这里是一个创建三个菜单项的library文件:
PHP复制代码
class show_menu() {
function show_menu() {
$obj= & get_instance();
$obj->load->helper('url');
$menu = anchor("start/hello/fred","Say hello to Fred
|");
$menu .= anchor("start/hello/bert","Say hello to Bert|");
$menu .= anchor("start/another_function","Do something
else |");
return $menu;
}
}
?>
复制代码
(这时,不要为不寻常的语法担心,如“$obj->” 还有第六行的$this->. 这在第 7 章会详细介绍。)
注意:这些代码是 OO 代码, 在函数 show_menu() 中包含一个简单的类,“menu”。它能存取其他的 CI 类和helper: 在这个例子中,它调用URL helper--我们刚刚介绍过它。
首先,它装载URL helper, 然后它创建一个字符串 ($menu), 包含指向三个控制器和函数的HTML代码,然后它返回 $menu字符串。
你可以在一个控制器里这样调用它:
$mymenu=$this->menu->show_menu();
然后控制器能使用 $menu变量调用视图:
$data['menu'] = $mymenu;
$this->load->view('myview',$data);
这个类生成一个菜单,每个菜单项指向一个新的页面。 正因为这样,我把它保存在:
/system/application/libraries
而不是
/system/libraries
它与URL helper 藕合,并且我可以在任何CI框架构建的网站中使用它。
它还是智能化的,它创建一个菜单,我可以从任何的控制器调用它,显示一个标准菜单。
摘要
MVC 框架已被广泛地用于构建复杂的动态网站。CI 使用它帮助你编写高度可重用的代码。
始终保证代码的'松藕合' 和 '组件智能化', 当你编写你自己的代码时。不要担心你的项目是否严格遵守 MVC 的理论。 关键是理解文件的类型和它们如何彼此交互。然后, 你再确定使用library, model, helper或是plug-in编写代码。
我们已经看了CI框架的文件和目录结构, 你还能研读源代码,并请不要在不是很深入理解CI的动作原理时去修改它们。
config文件中包含网站的基本信息,可以使我们方便地修改信息,有利于我们快速迁移服务器,减少出错的机会。
我们已经见到控制器的基本结构, 而且用构造函烽从config 文件中读取数据并把它存入对象的属性中。我们还动态地把数据从控制器传递给视图。到现在为止, CI框架中的一些重要知识已经学习过了,当我们继续学习时,我们会很清楚这些知识是非常重要的。
同时,我们也学习了CI控件间传递数据的方式,了解这些对你编程是很重要的。
最后,我们分析了两个例子,一个是URL helper, 还有一个是创建菜单的例子。