使用CodeIgniter框架快速开发PHP应用(一)(转载请保留出处)
对 CodeIgniter 的介绍
大多数PHPer都想写出运行状态良好的应用程序,而且希望尽可能做得简单且不费事。这篇
文章是有关 CodeIgniter的(以后简称CI),CI是一个达成上面目的的所谓框架。
如果你只是要达成一个最终的结果,而把中间所有的编码细节和复杂统统丢给一个框架,
CI是你最好的朋友。
CI有很多优点:免费, 轻量级, 容易安装, 它能使你的编程生涯变得很轻松。 这一章我们会
告诉你:
. CI 能为你做什么?
. 什么是“框架” ?CI 为什么能被称为框架?
. “开源”商业模式
. CI的某些不足(是的, 它不完美)
CodeIgniter 能为你做什么?
如果你已经是一位PHPer, 开发过PHP应用, CodeIgniter 将会帮助你做得更好, 更容易达成
目标。 CI会减少你的代码数量。你的脚本可读性也会更好,更容易升级。它会使你的网站
结构更紧凑,代码更强健, 如果不是很好地研究CI的源代码的话,你可能还无法察觉到它的
强健。
对大多数兄弟来讲,你可能已经花了不少时间, 系统地学习了PHP、HTML和CSS,当然还
有MySQL什么的。不过如果使用CI,你只需要一些基本的LAMP(WAMP)知识, 你没有必
要先成为一个专家才能使用CI。 你完全可以先借助于CI或别的什么框架软件,成为一个有
生产力的PHP程序员,拿着高薪然后优雅地进一步学习PHP的中高级知识,直至成为一位真
正的PHP骨灰级人物。
下述情形,你最好不要使用CI:
. 你没有一点PHP和HTML的基本知识.
. 四五个页面的小程序.
. 只用极少的代码就要完成一个CMS或FORUM程序(CI做不到,神仙也做不到)
节约时间
CI学习周期短,见效快。 让我们试着评估一下相关的要素:
CI如何减少代码数量?
你真的可以减少很多工作量:敲击键盘的次数减少了, 代码错误减少了, 你只需要较少的时
间调试代码。 代码量减少还意味着你只需要较少的空间来存放应用程序。
举二个例子(稍后它们会被进一步分析, 因此不用担心如何了解它们的工作原理!)
想像你正在写一个MySQL数据库查询。 可能的代码如下:
$connection = mysql_connect("localhost","fred","12345"); mysql_select_db("websites", $connection); $result = mysql_query("SELECT * FROM sites", $connection); while ($row = mysql_fetch_array($result, MYSQL_NUM)) { foreach ($row as $attribute) { print "{$attribute[1]} "; } }
现在看看CI如何处理同一个问题:
$this->load->database('websites'); $query = $this->db->get('sites'); foreach ($query->result() as $row) { print $row->url; }
比较字符数: 前者 336,后者 112。
第二个例子,现在让我们想像你正在用HTML写一个数据输入窗口, 你想要一个下拉输入
框。下拉框中有三个选项。代码如下:
<select name="type"> <option value="1">www.this.com</option> <option value="2">www.that.com</option> <option value="3" selected>www.theother.com</option> </select>
CI的写法和前例一样,因为它把相关内容放入一个数组,更容易由PHP进行处理::
$urlarray = array( '1' => 'www.this.com', '2' => 'www.that.com', '3' => 'www.theother.com' ); $variable .= form_dropdown('url', $urlarray, '1');
在 HTML ,你需要键入 167; 在 CI, 148.
使你的网站更安全
你不需要写很多代码, 是因为CI提供了许多标准的功能, 这些经过仔细推敲的框架内的代码,
对安全性和输入进行了有效的校验和考虑。初学者往往没有足够的能力全面兼顾功能和安全
(这也是中高级程序中央委员新手之间能力差异的一个方面)
确保你的链接自动更新
设想你正在写一个菜单页, 有许多超链接可重定向到其他页。 他们全部以传统的HTML格
式编写:
<a href="http://www.mysite.com/index.php/start/hello/fred">Hello World</a>
然后, 你决定改变这个链接地址。这意谓你必须仔细地去查找并修改代码中的每一处地址,
否则它们将无法正常工作。
CI 给你一个简单的函数,可以这样写超链接:
echo anchor(start/hello/fred, Say hello to Fred);
CI推荐你把你的URL放入一个config文件供你的脚本读取。CI的anchor函数会自动从config
文件中提取相关URL。因此, 当你修改一个URL时,你只需要修改config文件中的的对应链
接,就一次那么简单。
防止对数据库的攻击: 对录入数据进行校验和处理
数据输入可能引发许多问题。 因为 HTML 和数据库的限制,数据中总包含特定的符号- 举
例来说, 省略符号和引号-可能导致你的数据库遭到攻击,最终得到你无法预料的结果。
解决方案是在把这些数据存入数据库前对这些数据进行相关处理。 这样做会浪费一些系统
时间, 增加一些额外编码。
CI的页面助手会自动地完成这些工作。 因此, 当你编写一个录入框时:
echo form_input('username','johndoe');
CI也隐式地执行下列校验函数:
function form_prep($str='') { { if ($str==='') { return ''; } $temp ='__ TEMP_AMPERSANDS__'; // 将录入内容放入临时变量进行处理以便 // htmlspecialchars不破坏原数据 $str= preg_replace;("/&#(\d+);/", "$temp\\1;",$str) $str= preg_replace;("/&(\w+);/", "$temp\\1;",$str) $str= htmlspecialchars($str); // htmlspecialchars函数会造成对一些符号的错误处理 $str= str_replace(array("'",'"'),array("'", "& quot;"), $str); // 把临时变量还原到输入变量中 $str= preg_replace;("/$temp (\d+);/","&#\\1;",$str) $str= preg_replace;("/$temp (\w+);/","&\\1;",$str) return $str; }
上述函数捕获象'&'这样的特殊字符, 以便在你的页面提交时不会造成混乱。你应该知道,
有些字符会引起问题。
并不是所有的用户都会中规中矩地录入符合要求的信息,你也不可能知道使用浏览器录入信
息的是什么人,他们在想什么,做什么。你可以使用CI来防上下系统录入不符合要求的信息。
自然,你大可不必知道CI是如何在幕后为你做到这一切的,你只需要简单地输入如下代码:
echo form_input('username', 'johndoe');
CI使你写代码更容易了。不象有些类库如PEAR等,集成比较困难,(有时候你会找不到支
持PEAR的空间),CI很容易集成,只要把它放入一个目录,它就能很好地工作。CI所有的
代码可读性好,也很强健,推出前经过社区用户的认真测试,所以在你可以使用时这些代码
已经历了很多考验。
让我们看二个例子。
发送电子邮件非常简单
传统的发送电子邮件功能实现起来比较复杂。CI提供的功能使这件事变得很简单:
$this->load->library('email'); $this->email->from('[email protected]', 'Your Name'); $this->email->subject('Email Text'); $this->email->message('Testing the eamil class.'); $this->email->send();
实现发送电子邮件功能中有一些不容易解决的技术问题: 比如文本封装和发送附件功能,标
准的PHP实现起来比较复杂,CI简化了这些工作, 它的email类使得发送附件很简单:
$this->email->attach('/path/to/photo1.jpg');
CI把内部的复杂部分悄悄地完成了, 举例来说,实现了列举近百种不同的附件的MIME类型
的功能。所以它知道你的相片photo1.jpg是一个‘image/jpeg'的MIME类型。因此它在在你附件
的适当位置填写必要的限制符号,它细致地封装你的文本,使你方便地设置需要标记的文本。
压缩用户需要下载的文件以加快下载速度
为了加快下载速度, 常见的做法是在下载之前压缩下载文件。你可能不知道如何处理。但CI
可以方便地让你用四行代码完成此功能:
$name = 'mydata1.txt'; $data = 'the contents of my file......'; $this->zip->add_data($name, $data); $this->zip->archive('c:/my_backup.zip');
执行这些代码,你会在你的C盘根目录下找到一个压缩文件,解压后即为原始文件。
你网站的用户并不清楚你是如何容易地实现下载压缩文件的功能,他们能体会到你的网站下
载速度很快,而你只用了数分种(而不是数小时)就实现了这个功能。
什么是框架,什么是CI?
三百六十行中新增编程这一行不久,人们注意到它牵涉了许多可重复的工作。 你或者其它
人也许不久以后就要用到几乎同样的功能,但是你必须花很长的时间来修改它。于是,人们
就发明了使用函数库的方法来重用代码。使用PHP的兄弟们也会使用函数库,并按用途分类
保存到不同的文件中,在编程时用require或include来使用它们。
同样的,框架是为重用而发明的,放在和你的代码分开的目录中,用来减少重复的劳动。
上面例子中连接数据库和写HTML页面的编程工作都可以调用相关的CI函数来进行简化。
有很多种方法实现同样的功能,大多数的框架会让你按照它实现的方法来做,一般来说,框
架的作者很有经验,并且作了精心的设计,你可以在几乎所有的场合下使用。
好的框架设计能实现需要的功能, 而且尽可能地不互相牵连。 一个好框架为你做出各种功
能的实现,并且给你提供一步一步的编程指导。
提到框架时,就不能不提到有名的框架:Ruby on Rails。
Rails做得相当成功, 因为它藉由最小量的编码, 明显地提供简便快捷的网站开发。 本质上,
它是一个结构和一组工具,专为使用Ruby语言的用户开发,允许你快速建立Ruby系统原型。
它不是Ruby语言中唯一的框架,但是它一定是最有开发效率和最有名的。
为PHP开发的框架有好多个,CI只是其中的一个。 其它的还包括Zend Framework、Cake、
Trax 和其他。 下列网址可以找到一个针对十来种框架的简明的图表分析:
http://www.phpit.net/article/ten-different-php-frameworks/ 。
如果你访问上述网址中相关产品的官方网站, 你将会注意到,每个论坛都有一个共同的热
点,就是到底哪个一个框架是最好的? 事实似乎是每个都有它的长处,而且又都有自己的弱
点。 我的评估标准是: 我很忙; 因此框架应该节约我的时间,从中选择一个后,就坚持使
用下去,因此就有了这篇介绍CI框架的文章。
关于开发者
Rick Ellis开发了CI,他曾经是一个摇滚音乐家,现在是一个软件设计师。 Rick还是pMachine
公司的CEO,该公司还有一个著名的CMS产品叫做Expression Engine. 2006 年 1 月,他在他
的博客中写道:
(http://ellislab.com)
"我花了数星期时间搜索和安装PHP框架, 也被它们中的许多打击了一把,令我惊讶的是:
我发现大多数框架存在以下问题:
. 文档不全或质量很差
. 他们假定你水平很高,希望你能很容易地掌握使用方法
. 他们是为那些有超级用户权限或者有权修改服务器设置的人写的
. 他们假定你偏爱命令行操作,事实上许多人无此爱好
. 偏爱使用PEAR类库或其它开源代码库
. 模板语法过于复杂
. 有的太笨重,有的又太简单
. 大多数框架只能在PHP5 中运行,只有 5%的使用率
我还没有找到一个简单的PHP框架, 健壮,易于使用, 文档完整,包含建立一个完整应用
需要的所有工具 彻底地从顶端被证明到根据,生来地包括不可或缺的建立强健的申请的所
有的工具, 并且有一个以浏览器为基础的接口, 使用普通用户权限就能安装。没有别的原因,
就是市场需要这一单一的原因促使我想开发这样一个框架产品..."
结果是CI诞生了, 作为一个业余时间开发的作品,Rick慷慨地决定使它成为开源作品。在跑
生意间隙,他保持经常更新CI。 他也创建了一个优秀的论坛, CI使用者能提出问题而且分享
开发心得。 所有这些资源可从下列网址获得:
http://www.codeigniter.com/
他能实现自己的设计目标吗?相信你使用后会得出自己的结论.
CI不能做什么
CI有它本身的缺点。Rick把CI定义为小的和'轻量级'的结构。(1.5 版压缩后只有 737KB可以
在几秒种内下载完毕。Zend Framework是 10MB) CI不能解决你所有的问题。 但是它能够:
. 使PHP编程更容易
. 帮助你架构网站或使你更容易地设计架构
作为 '轻量级' 框架的一个结果是它没有它的对手具有的许多特征。 象Rails因为它包含 '脚
手架'功能和"代码生成器",因此可以为你编写一些基本的脚本代码。 因此, 举例来说,一
经你已经建立一个数据库, Rails能自动生成简单的CRUD脚本(Create, Read, Update, Delete)。
除此之外,Rails还能让你编写'代码生成器'-自动地写其他的简单脚本代码。Rails社区中有许
多这样的例子,因此你可以做很多智能化的东西。
CI不这样做。(有基本的 '脚手架'功能-在CI中,脚手架只给开发者使用。就象在线手册描述的
一样: "脚手架安全性不够...如要使用脚手架的话要确保在使用后立即关闭这个功能。在实际
运行的网站上不要让脚手架处在工作状态。" 说得够明确了吧?)
相反地CI专注于使基本的东西更容易。它处理的一些事物是:
. session管理和cookie管理 (见第 6 章)
. 数据库访问和查询 (见第 4 章)
. 创建HTML相关内容,如页面和表单,并检验输入内容。(见第 5 章)
. 测试 (第 8 章)
. 英特网通信, 使用FTP或 XMLRPC(第 9 章)
很熟悉吧? 这些全部是基本的处理, 如果你正在创建一个动态的网站,你一定会做这些工
作。 CI使这些工作更容易, 而且使你的代码尽可能更好地工作。
许可证
参见CI下载文件包
摘要
如果你已经掌握PHP的基本知识并且想“聪明”地编写动态网站脚本, CodeIgniter框架会使你
的工作更容易,它帮助你:
. 节约时间
. 使你的网站更强健
. 帮助你编写更复杂的系统
它使你更好地享受编程乐趣, 而不是一个干苦活的体力工。
有相当多的框架, 还有很多是为其它语言开发的。 他们都能减少编码的重复工作,使编写
复杂程序变得更容易, 而且建立一个合理的系统架构。
这篇文章不制造框架大战。文章中已经解释了选择CI理由,让它为你节约更多的时间用在学
习工作和生活中吧,请享用它!
下一章:
"二分钟: 建立一个CI网站”
二分钟: 建立一个 CodeIgniter 网站
用CI建一个网站很容易。 这一章很短,解释了用CI制作网站时发生了些什么,哪些文件被
创建,让我们来瞧一瞧:
. 创建网站需要什么软件?
. 安装 CI 文件: 一个简单的下载和解压缩操作
. CI 的基本设置: 有哪些文件夹及它们是如何组织的
. CI 安装时默认的控制器和视图
. 一些简单的修改来演示CI如何运作
准备知识
CodeIgniter 有较好的版本兼容性。 它工作在PHP 4.3.2 及以上版本, 或 PHP 5。由于大多
数ISP还不支持 PHP 5, 支持PHP 4 版本是有用的。
你还需要一个数据库。 CI 的在线手册说: " 被支持的数据库是 MySQL 、 MySQLi 、 MS
SQL 、 Postgre 、Oracle、 SQLite 和ODBC。 "
为了要开发并测试一个动态的网站,你需要一个Web服务器。通常,你会在本地服务器上开
发并测试你的网站,也就是, 这些软件运行在你自己的机器上 (127.0.0.1 或 localhost), 一般
来讲, 开发环境不会建立在远程服务器上。
如果你不熟悉如何分别建立本地开发环境, 可以选择一个套装软件,像是 Xampplite, 一次
过安装APACHE、 PHP 和 MySQL,几乎不需要修改设置文件。 Xampplite 是免费的,有简
单易懂的安装指南。
你还需要一个称心的 PHP 编辑器。 所有的编码工作都可以在文本编辑器中完成。提供语
法高亮功能和命令自动补齐功能的编辑器会更理想一些,因为它可以帮助一般水平的程序员
节约时间。
一旦你做好了这些准备工作,我担保你在两分钟内就可以搞定CI安装工作
安装 CodeIgniter
再次声明,CI是完全免费的!
建立好开发环境后, 去 CodeIgniter 网站:
http://www.codeigniter.com/
和下载最新版的框架。 1.5.4 版是最新版, 是一个只有 737KB 的压缩文件, 几秒种就可以
下载完成。
解 压缩这个文件,把它释放到网站根目录中。 如果你正在使用 Xampplite ,通常在
Xampplite 文件夹里面的 htdocs 文件夹。
CodeIgniter index.php 文件应该在根目录中。这时,如果你在浏览器上打开 http://127.0.0.1.
你也就实际打开了此文件。 我们用 1-2 分钟的时间来建立一个可运行的网站!
和 CI 包含在一起是一个简单易懂的用户手册.(在 user_guide 文件夹中) 你将会经常用到
它。它的内容很详细,细过这篇文章,所以,需要时,请经常查阅它。
当这些文件保存在你的机器上的时候,有二个方法来访问他们:
. 通过URL,http://127.0.0.1
. 经过正常的目录路径: 举例来说, C:/xampplite/htdocs/index.php
你应该通过浏览器访问 CI 的默认首页。 真是简单! 默认首页传递给你一个信息:它是由
两个你正在见到的被二个文件组成的:视图文件和控制器。
分析文件结构
安装 CI 文件后,我们来看一下目录结构。
|
―-htdocs
|
--system
||
| --application
|||
||--config
|||
||--controllers
|||
||--errors
|||
||--hooks
|||
||--libraries
|||
||--models
|||
||--views
|--cache
||
|--codeigniter
||
|+-database
||
|--fonts
||
|--helpers
||
| +-language
||
| --libraires
||
| --logs
||
| --plugins
||
| +-scaffolding
||
+-user_guide
你的根文件夹现在应该看起来有点像上面的图表。 如果你曾经看Rails,这结构将会看起来
非常熟悉。
你能把这些文件夹分为三个小组:
. application是你自己的项目存放文件的目录 (举例来说, 控制器、模型和视野: 全部在应用
文件夹中). 除了你才见到的默认的视图和控制器,这些文件夹是空的。
. 在系统文件夹的一部分文件夹是 CI 本身的代码。(system/libraries、system/codeigniter 、
system/drivers, 等等。). 如果你愿意,你能研读他们, 或者改变他们-不过要等到你了解 CI
是如何工作才这样做。而且如果你改变框架内的代码,记住当你下载 CodeIgniter更新版本的
时候,备份它们。否则新的版本会覆盖它们。 当然, 你也可能不需要自己修改代码而直接
使用CI本身的代码,Rick写的代码应该是很不错的。
. 还有一些文件夹中已包含文件,但是可能需要增加或修改(如:language、 config, errors.) 这
些文件夹被设定成默认值,但是你可以修改它们。
配置文件
还记得我们要花二分钟建立我们的网站吗? 第二分钟要用来做一些基本的设置。
config 文件夹包含了为你的网站设定基本结构的一些文件。 打开 config/config.php 文件.
告诉网站应该在哪里找到它自己的结构和配置信息. 文件的第一行一般是这样的(不包含注
释):
/* |------------------------------------------------ | Base Site URL |------------------------------------------------ | | URL to your codeIgniter root. Typically this | will be your base URL, WITH a trailing slash: | |http://www.your-site.com/ | */ $config['base_url']=" http://127.0.0.1/"; /*
注意 CI 的注释多详尽!
修改引号中的数据以匹配你自己的网址。 如果你有疑问,请查询在线手册以得到详细指导。
作为一项基本的原则,使用 config.php 文件储存关于你的网站的信息好过散布在你项目的
不同文件中。这样做有几个好处,第一,更新比较容易; 第二,当你把项目从开发服务器
转移到实际存放的服务器时,修改配置较容易;最后, 许多 CI 函数会首先在配置文件中寻
找需要的信息。
还有其他的 config 文件存放在 config 文件夹中,但是目前你可以放心地使用它们而不用
修改它们的默认值。
在二分钟中,我们需要建立第二个网站。 在这一章的余下部分,我们将会上我们刚做好的
网站去逛逛。
它能工作吗?
假定你正在本地服务器的根文验证网站能否正常工作的一个简单方法就是打开你的浏览器。
件夹中运行它, 在地址栏输入http://127.0.0.1 ,你能看到网站的默认页面.
看到默认页面意味着你的网站正常工作了。不需要二分钟,对吗?
摘要
在这一个章节中,我们已经见到,安装 CI 是多么容易。一旦建立好你的开发环境, 你所需
要做的是下载 CI 框架文件,解压, 复制到一个目录而已。
随后, 我们快速浏览了CI的目录结构。
这一章节非常短,因为 CI 容易安装,不需要太长的篇幅。 其实其它章节也不长,因为CI
的确很简单易懂,节约时间。
第三章介绍:
分析网站结构
第三章介绍:
分析网站结构
第3章
分析网站结构
既然我们已经安装 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 结构的所有好处。
当你编程的�r候,试着始终用 MVC 来思考问题。尽可能确保你的 '视图' 聚焦于显示, '控
制器'纯粹地用来控制数据流。 把应用逻辑保留在数据模型和数据库中。
这样,如果你决定开发新的视图,你不必在任何一个控制器或模型中修改代码。 如果你需
要更新 '商业规则' ,你只需要在模型中修改代码。
另一方面,你必须认识到,MVC只是用来帮助你的一种设计方式,而不是用来约束你的。
MVC可以有不同的实现方式。 论坛包含许多如何 '正确合理'地实现 MVC 的方式。 ( 我CI
应该在控制器部分实现数据库查询功能吗?我能直接从视图发送数据到模型层吗?或者我
必须通过控制器来访问?)
与其寻找理论上的正确方式,不如遵循二项有用的原则。这些在 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。
代码:
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> <head> <title>Welcome to Code Igniter</title> <style type=" text/css"> body { background-color: #ffffff; margin: 40 px; font-family: Lucida Grande, Verdana, Sans-serif; font-size:14 px; color: #4F5155; } .....more style information here </style> </head> <body> <h1> Welcome to Code Igniter!</h1> <p>The page you are looking at is being generated dynamically by Code Igniter.</p> <p>If you would like to edit this page you'll find it located at:</p> <code>system/application/views/welcome_message.php</code> <p>If you are exploring Code Igniter for the very first time, you should start by reading the :<a href="user_guide/">User Guide</a>.</p> </body> </html>
正如你见到的,它完全由 HTML 组成,内置CSS定义。在这个简单的例子中,控制器还没有
传送任何的变量到视图中。
默认的控制器
前面提到,如果在request中没有指明具体的控制器和action, CI 将会把页面重定向到一个系
统默认的页面。这个默认页面可以自己设定,它存放在如下地址:
/system/application/config/routes
该文件中包含下列设置:
$route['default_controller']="welcome";
如果你不在此设定默认值, 没有明确URL的request会转到 '404not found'页面。
上述config文件,默认值是重定向到welcome controller。
如果没有指定函数,/index会被默认选中。因此确定你包括一个index()函数, 如果只是要避
免显示 '404' 页面,请确保包括index()函数。
你可以根据需要修改此设置,你还可以修改一个函数叫做_remap($function),其中$function
是你要重定向的控制器。_remap总是先被调用,不管URL是什么内容。
CodeIgniter 语法规则
在我们开始学习之前,让我们简单地规纳一下 CI 的语法规则。 框架希望文件和目录按一定
的规则设置,否则它可能无法准确地定位和使用它们。
控制器
这是一个类(也就是OO代码) 它由URL直接调用,例如:
'www.example.com/index.php/start/hello'
控制器使用函数名称来调用函数,如:
mainpage();
不过,你不能够在一个控制器内调用其它控制器内的函数。
定义:
控制器开始用如下格式定义:
class Start extends controller
控制器的名称的首字母必须大写, 而且被保存为.php文件,位于如下路径:
/system/application/controllers
文件名称的首字母不需要大写,应该是start.php而不是Start.php. 还有,在构造函数中至少要
有如下构造方式:
function display() {parent::Controller();}
。所有的其他代码一定要写在不同的函数当中(这不是CI的规定,而是PHP的规定)
视图
视图是包含 HTML 代码的,带有.php后缀的文件。 使用如下命令装载: $this->load->view('testview',$data);
这条命令载入视图。使用时还要使用别外的方法。
语 法: 视图用HTML编写,PHP 代码包含在 <?ph p?>标记中,在view目录中保存为后缀
为.php的文件。
在 CI 框架开发的网站上的文件或类的类型介绍
application目录中有一些不同的子目录。 我们已经看过controller、 config 和views目录。
但是什么是libraries, models和scripts? 这是 CI 目录中似乎让人相当困惑的一个区域。 (如
果你已经用过 1.5 版前的 CI 的版本, 你将会了解为什么。 Rick Ellis对较早的版本感到不
满意, 并且已经大幅度修改了结构。 因此,为了向前兼容,一些目录结构必须保留。)
这些文件夹被平等地对待。你为什么要把代码放在这个目录而不是那个目录从技术角度看,
是没有什么理由好讲,这就是一种约定。
这样讲吧,假定你已经写了一段代码并命名为display, 里面包含一个函数叫做mainpage。有
四种方法你可以实现: 一个model, 一个library,一个助手类或一个插件。下列的表格列举了
你如何装载和使用每一种方法:
文件类型
model
如何使用
是一个类(面向对象代码)
装载方法:$this->load->model('display');
使用方法:$this->display->mainpage();
如何定义:
必须以如下格式开始:class Display extends Model
必须包含构造函数和构造语句:
function display() { parent::Model(); }
必须包含一个mainpage()函数
概念性总结:用户手册这样描述:“Models是设计用来表示数据库中信息的PHP类。”
library
存放在application和system目录中。
也是一个类(注意:你自己的类库不会自动地包含在CI超类中,因此你必须用
不同的方法来词用,详见第七章)
装载方法:$this->load->library('display');
使用方法:$this->display->mainpage();
如何中定义:
不需要从父类继承,不一定需要构造函数。
这样足够了:
chass Display() {
function mainpage() {
// code here
}
}
概念性总结:如果你想扩充CI的功能,或者创建特别的功能可以使用library。
是一段脚helper可以保存在system/helpers或application/helpers目录中
本(过程式代码,不是类)
装载方法:$this->load->helper('display');
使用方法:直接调用,如:mainpage();
如何定义:
文件必须被保存为,如:display_helper.php
(文件名必须加上_helper)
mainpage()必须作为一个函数包含在这个文件中,整个文件就是一过程式函数的集
合。因此你不可以在这个文件的函数中调用CI的其它资源。
概念性总结:helper是用来适度帮助你实现特定目的的低级函数。
保存在system/plugins目录中,也可以保存在
application/plugins目录中
是一段脚本(不是类)
装载方法:$this->plugin('display');
使用方法:直接调用,如:mainpage();
如何定义:
保存在如下格式的文件中:display_pi.php
文件名中必须加上_pi
mainpage()必须作为一个函数包含在这个文件中,整个文件就是一过程式函数的集
合。因此你不可以在这个文件的函数中调用CI的其它资源。
概念性总结:用户手册如此写道:“...plug-in和helper的最大不同就是plug-in通常用来
提供一个单一的函数,helper是一个函数的集合...plug-in一般用于社区内互相分享代码。”。
(详见第十五章:一个插件的例子)
plug-in
你可以自由地选择使用这四种方式中的任一种或几种,当然,如果你选择model和library的
话必须使用OO编程方式。helper和plug-in必须使用过程编程方式。后者不能够直接引用其他
的 CI 类。 另外,不同目录的区别主要是由CI框架设定的。
你 应该注意到 CI 有二组helpers,plug-in和libraries,而models只有一组,前三种一组放在
application目录中,另一组放在system目录中,这两组的区别主要也是CI框架设定的。
。 那些在system目录中代码是CI的核心代码,所有的项目都会使用。如果你升级到一个新
的CI版本,这些文件会被修改。
。 当你装载一个helper, plug-in或library, CI会在两个目录中查找,比如你要装载一个类叫做
display, CI会先杳找system/application/libraries目录。如果这个目录中不存在,CI会寻找
system/libraries目录。
。这意味着可以通过把同名的文件放入applications目录来取代CI核心库的libries, helpers, 和
plug-ins。不要轻易尝试这样做。因为这种高度的灵活性需要你使用CI的经验足够多。如果
你想扩充CI基本类和脚本的功能,请参考第十三章。
文件夹的含义?
在对系统各目录进行了一番介绍后,我们通过下表来总结一下各目录的作用。
application config
存放配置文件:包含网站的基本配置信息
controllers 控制器
errors
hooks
包含出错信息页,你不必修改这个目录
首次安装时为空,用来存放你创建的钩子。钩子是
用来装载其它文件的控制方法
代码库,针对本项目的专用代码
代码库,本项目的模型层文件
存放视图的模板目录
libraries
models
views
cache
放
第一次安装时为空,如果你打开缓存设置(详见第十章) 这个目录存,
缓存数据
codeigniter 组成CI框架的文件
database
fonts
helpers
language
libraries
CI框架的数据库类的类库文件
没有在用户手册中介绍,存放水印图像使用的字体
"系统级"助手类
你可以存放你本国语言的键名列表-详见 11 章
“系统级”类库
logs
plugins
如果你打开系统错误日志,日志文件默认保存在这个目录
更多的系统级代码文件
scaffolding "系统级"类库,实现简单的“脚手架”功能
设计良好的视图
在现阶段,你可能问我们为什么要这么努力去为一个简单的HTML页面服务?为什么不把所
有的东西放在一个文件里?对一个简单的网站来说,这个观点是对的,但是现在谁还听得到
简单的网站?CI框架中最酷的一点就是它能够始终保持内部结构一致,展开良好,易于维护。
一开始,我们需要三个相同的步骤:
。 写一个视图view
。 写一个stylesheet
。 更新我们的 config 文件指定 stylesheet 在哪里
在这三点做完之后,我们需要更新我们的控制器接受从URL传来的叁数,把变量传给视图。
首先,让我们重新设计我们的视野并把它保存至如下路径:
system/application/views/testview.php
<html> <head> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'http:\/\/ www.w3.org/TR/xhtml 1/DTD/xhtml-strict.dtd'> <html xmlns='http:\/\/ www.w 3.org/1999/xhtml'> <title>Web test Site</title> <base href=<?php echo "$base"; ?>> <link rel="stylesheet" type=" text/css" href="<?php echo "$base/$css";?>"> </head> <body> <h1><?php echo $mytitle; ?></h1> <p class='test'><?php echo $mytext; ?></p> </body> </html>
它基本上仍然是 HTML, 但是注意<?php ?>标记中间的PHP代码。
你将会注意到有一个PHP代码片断存放在stylesheet中,它指定一个系统的CSS文件存放在网
站的根文件夹中,让我们保存一个简单的 stylesheet 文件,名为 mystyles.css 。 它很简单:
h1{ margin: 5 px; padding-left: 10 px; padding-right: 10 px; background: #ffffff; color: blue; width: 100%; font-size: 36 px; } .test{ margin: 5 px; padding-left: 10 px; padding-right: 10 px; background: #ffffff; color: red; width: 100%; font-size: 36 px; }
这给了我们二种风格可以选择, 而且你将会在视图中会用到它们。
首先,让我们在config 文件加入:
$config['css']=" mystyles.css";
这只是将告诉网站我们刚才编写的 CSS 文件的文件名称和位置
但是注意 stylesheet 的实际位置是 $base/$css-从哪里获取变量 $base和 $css的内容呢?你
还可以联想到,变量 $mytitle 和 $mytext 的内容呢? 答案是我们需要一个新的控制器!
设计一个工作良好的控制器
现在,我们需要一个新的控制器。 我们将其命名为Start并且保存在
/system/application/controllers/start.php
这一个控制器必须做几件事情:
。调用视图
。将基本URL信息和刚编写的css文件的名称传递给视图
。把另一些数据传递给视图: 它正在期待名称 ($mytitle) 和一些本文 ($mytext)
。最后, 我们想要控制器接受来自使用者的一个叁数 (经由URL request)
换句话说,我们必须在先对视图中的变量赋值。 因此让我们从我们的Start控制器开始。 这
是一个 OO 类:
<?php class Start extends Controller { var $base; var $css;
在这里请注意,我们已经声明了变量(或叫做类属性) $base (网站的根地址), 和 $css(css 文
件名)。 如果我们在每个类中要编写超过一个函数,这样做会很方便。你也可以把它们定义
为一个函数内的变量,如果你硬要这么做也可以。
构造函数现在可以通过查找config文件来定义我们刚声明的变量了。要实现这个功能,我们
可以做如下定义:
$this->config->item('name_of_config_variable');
当做在:
function Start() { parent::Controller(); $this->base = $this->config->item('base_url'); $this->css = $this->config->item('css'); }
CI 会 config 文件中读取相关的设置内容。
使用这一机制、不管我们编写多少个控制器和函数,如果我们的网站访问量很大,我们需要
搬迁服务器的话,也只要一次就可以改变这些参数。
把叁数传给一个函数
现在,在Start控制器类里面,让我们定义将会实际上做工作的函数。
function hello($name) { $data['css']=$this->css; $data['base']=$this->base; $data['mytitle']='Welcome to this site'; $data['mytext']="Hello, $name, now we're getting dynamic!"; $this->load->view('testview',$data); }
这函数期待一个叁数, $name,(但是你能设定一个默认值-myfunction($myvariable=0)), 通常会
把一个字符串赋给$mytext变量。好吧, 我们现在要问一个问题,$name变量来自哪里?
在这个例子中,它需要来自URL request的第三个参数。因此, 它由 HTTP request提供:
GET /index.php/start/hello/fred HTTP/1.0
或换句话说, 当你在地址栏输入:
http://www.mysite.com/index.php/start/hello/fred
注意这一个例子中代码不 '干净地' 传递了变量fred, 没有用任何方式检查它。 你需要在编
程时对它进行检查。 我们将会在第 7 章学习到如何检查输入。 通常,参数必须在检查后
确保没有问题再传递给控制器。 如果不检查的话,一个不怀好意的用户可以容易地侵入系
统, 他可以发送这样一个URL如: http://www.mysite.com/index.php/ ... malicious_variable. 所
以, 你应该检查接收的变量,确保它们符合要求再进行处理。
网址的最后一个片段作为一个参数被传给函数。事实上,你能增加更多的参数,但不能超过
你所使用的浏览器的设置。
让我们总结下CI处理URL具体细节:
URL片段
用途
http://www.mysite.com 定位你网站的基本URL
/index.php定 位 CI 路 由 器 并 读 取 URL 的 其 它 部 分 , 分 析 后 定 们 到 相 关
网页
/Start
将
/hello
不
CI 将 调 用 的 控 制 器 的 名 称 ( 如 果 没 有 设 置 控 制 器 名 称 , CI
调用你在config文件中设置的默认控制器)
CI 将 调 用 的 函 数 的 名 称 , 位 于 所 调 用 的 控 制 器 内 。 如 果(
存在该函数,默认调用的是index函数,除非你使用
_remap)
CI把这个作为传递给函数的变量
CI把更多的参数作为变量传递给函数
/fred
如果还有/...
传递数据到视图
让我们回去再看一下hello函数:
function hello($name) { $data['css']=$this->css; $data['base']=$this->base; $data['mytitle']='Welcome to this site'; $data['mytext']="Hello, $name, now we're getting dynamic!"; $this->load->view('testview',$data); }
注意hello() 函数如何首先设置一个名为 $data的数组, 并把一些对象的属性及文本读入数
组。
然后它通过名称装载视图, 并把刚生成的$data数组作为第二个参数。
在幕后, CI 很好地利用了另外一个 PHP 函数: extract(),这个函数的作用是把数组中元素
取出放入变量表,其中每个键值对中的键名即为变量名,对应该键名的值为变量的值。因此
我们刚才定义的 $data 数组在视图中转换成一个一个单一的变量:$text (包含 " Hello,
$name, now we're getting dynamic ") , $css(包含来自 config 文件的设置值), 等等。
换句话说,当它被建立时的时候, $data数组看起来像这样:
Array ( [css]=> mystyles.css [base]=> http://127.0.0.1/packt [mytitle]=> Welcome to this site [mytext]=> Hello, fred, we're getting dynamic! )
但是当它被传递给视图的途中,它被解开,而且下列的变量在视图对象中被生成,与$data
的每个键/值相对应:
$css = 'mystyles.css'; $base = 'http://127.0.0.1/packt'; $mytitle = 'Welcome to this Site'; $mytext = 'Hello, fred, we're getting dynamic!'; )
虽然你只传送一个变量到视图中, 但是,你能把许多数据装进那一个变量。$data数组的每个
值还可是数组,这被称为多维数组,因此,用一个数组变量可以把大量的变量传递给视图,
这是一个很好的编程技巧。
现在对
http://127.0.0.1/packt/index.php/index/start/fred
(注意:这个网址跟以前的不同-它要求在index控制器中寻找start函数,并把参数“fred”传递
给该函数),你可以看到如何使用 MVC 框架构建动态网站。 (当然, 到目前至少是 VC,
因为我们还没有介绍 M 。)
键入上述网址,你可以在济览器中出来了对应的页面。
你可以看到参数fred是URL的最后一个部分,并被传递给函数,再经由函数传给了视图。
请记住你的视图一定要与你的控制器相对应。 如果视图中并未为一个变量安排显示的位置,
它将不被显示。如果视图正在期待一个变量,而这个变量并没有在控制器中被声明并赋值,
你可能收到一个错误信息。(当然,如果变量被声明,则不会有错误信息,但它不会正常显
示。)
CI 框架中的类彼此之间如何操控
当你编写你的控制器、模型时,你将会需要在他们之间进行互操作并传递数据。 让我们看
看如何实现这些功能。
调用视图
我们已经见到控制器如何调用视图并传递数据给它:
首先它产生数组 ($data) 传给视图; 然后它装载而且调用视图:
$this->load->view('testview',$data);
直接地调用函数
如果你想要使用来自libraries、models、plug-ins或helpers的代码, 你必须首先装载他们, 然后
而且我想要按先前我们制作的列表里的方法调用它们。 因此, 如果 'display' 是一个model,
使用它的 mainpage 功能,我的控制器可能这样调用:
$this->display->mainpage();
如果函数需要叁数,我们能通过如下方式传递:
$this->display->mainpage('parameter1',$parameter2);
与控制器互动
你能调用同一控制器内部的libraries、models、plug-ins或helpers,而且models和libraries也能
彼此调用,同plug-ins和helpers一样。
然而, 你不能从一个控制器调用另外一个控制器, 或从一个model或library调用一个控制器。
只有二个方法可以让一个model或者library与一个控制器关联:
首先,它能返回数据。 如果控制器作如下赋值:
$fred=$this->mymodel->myfunction();
而且函数中有return语句返回变量,那么控制器将得到赋给 $fred的值。
其次,你的model或library能产生(而且传递给视图)一个URL。控制器调用相关视图与使用者
产生交互。
你不能把URL直接传递给一个model或library。 用户总是与控制器交互, 从不直接面对其它
对象-但是你能在控制器里写一个调用函数。 换句话说, 你的视野可能包含一个URL指向一
个控制器函数:
echo anchor(start/callmodel, Do something with a model);
通过callmodel函数,调用一个model中的一个函数:
function callmodel() {
$this->load->model(mymodel);
$this->mymodel->myfunction;()
}
其中的原理如下图:
+--------------+
|用户|<----------------+
+--------------+|
||
v|
+--------------++-------------+
| controllers|--------->| views |
+--------------++-------------+
|^^
v||
+----------------------+|
| models and libraries |-------------+
+----------------------+
^^
||
||
+--------------+
这个图显示了控件间信息流的走向。
有的是直接的函数调用,如:
$this->mymodel->myfunction;()
models和libraries内部,或者从控制器到视图, 从控制器到libraries或models。 (models也能调
用视图, 理论上这样做不是很合适.) 相反方向就不能调用,如:视图等等不能调用控制器。
然而,libraries和models能互相调用。
有的是返回值给调用它的对象,如:
model和libraries能在内部互相传递数据,也能返回值给控制器。 视野不返回值给调用它的
控件。
用户可以通过地址栏发出URL request, 也可以通过点击视图上的URL发出request。
一个CI helper的例子: URL helper
下面介绍一个如何使用helper的例子,使用helper能使你的代码更整洁, 更有针对性。
CI的URL helper包含一组帮助你操作URL的函数。你可以像这样装载它:
this->load->helper('url');
然后, 你能用它寻找并返回URL或URL的base部分:
echo site_url;()
echo base_url;()
你也能使用它产生超链接。我们在上一节看到过在start控制器中存取hello函数, 而且把叁数
fred 传递给该函数, 这些都是通过一个网址实现的:
http://www.mysite.com/index.php/start/hello/fred
如果你想要你自己的代码生成一个像这样的URL,你可以使用URL helper实现。 语法是:
echo anchor(start/hello/fred, Say hello to Fred);
这生成一个同样的URL, 而且显示:“Say hello to Fred"。 换句话说,它是等同于:
<a href="http://www.mysite.com/index.php/start/hello/fred">Say hello to Fred</a>
请记住,使用 CI helper有二个好处:
第一, 录入字符较少
第二,URL helper自动在 config 文件中查找网站URL(和index文件名) 这意谓如果你改变你
的网站URL,你只需要改变 config 文件一次,你不需要查遍代码修改变化。
URL helper还有其他的有用功能。比如:它能创建'mailto' 超链接。
echo mailto('[email protected]', 'Click Here to Email Me');
和下面的HTML代码等效:
<a href=" mailto:[email protected]">click here to email me</a>
如 果你担心机器人从你的网站搜集电子邮件并使用它们发垃圾邮件,用safe_mailto 代替
mailto。屏幕内容相同,并且工作也正常。但是如果检查你的HTML代码,现在变成了复杂
的JS代码,机器人也许什么也抓不到。