使用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写一个数据输入窗口, 你想要一个下拉输入框。下拉框中有三个选项。代码如下:





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格式编写:


Hello World


然后, 你决定改变这个链接地址。这意谓你必须仔细地去查找并修改代码中的每一处地址, 否则它们将无法正常工作。


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理由,让它为你节约更多的时间用在学习工作和生活中吧,请享用它!


二分钟: 建立一个 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 结构的所有好处。


当你编程的時候,试着始终用 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。




代码:
        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代码示例(作了精简处理):


  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 :User Guide.






正如你见到的,它完全由 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是用来适度帮助你实现特定目的的低级函数。


plug-in          保存在system/plugins目录中,也可以保存在       
                 application/plugins目录中
                 是一段脚本(不是类)
         装载方法:$this->plugin('display');
         使用方法:直接调用,如:mainpage();
         如何定义:
         保存在如下格式的文件中:display_pi.php
         文件名中必须加上_pi
         mainpage()必须作为一个函数包含在这个文件中,整个文件就是一过程式函数的集合。因此你不可以在这个文件的函数中调用CI的其它资源。
         概念性总结:用户手册如此写道:“...plug-in和helper的最大不同就是plug-in通常用来提供一个单一的函数,helper是一个函数的集合...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     CI框架的数据库类的类库文件


fonts        没有在用户手册中介绍,存放水印图像使用的字体


helpers      "系统级"助手类


language     你可以存放你本国语言的键名列表-详见11章


libraries    “系统级”类库


logs         如果你打开系统错误日志,日志文件默认保存在这个目录


plugins      更多的系统级代码文件


scaffolding  "系统级"类库,实现简单的“脚手架”功能 




设计良好的视图


在现阶段,你可能问我们为什么要这么努力去为一个简单的HTML页面服务?为什么不把所有的东西放在一个文件里?对一个简单的网站来说,这个观点是对的,但是现在谁还听得到简单的网站?CI框架中最酷的一点就是它能够始终保持内部结构一致,展开良好,易于维护。


一开始,我们需要三个相同的步骤:


。 写一个视图view


。 写一个stylesheet


。 更新我们的 config 文件指定 stylesheet 在哪里


在这三点做完之后,我们需要更新我们的控制器接受从URL传来的叁数,把变量传给视图。


首先,让我们重新设计我们的视野并把它保存至如下路径:


system/application/views/testview.php


  
  
          Strict//EN'http:\/\/ www.w3.org/TR/xhtml 1/DTD/xhtml-strict.dtd'>
    
     Web test Site
     >
     ">
  
  
    

< php echo $mytitle;  >


    

< php echo $mytext;  >


  
  


它基本上仍然是 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                CI将调用的控制器的名称(如果没有设置控制器名称,CI将                       调用你在config文件中设置的默认控制器)


/hello                CI将调用的函数的名称,位于所调用的控制器内。(如果不                       存在该函数,默认调用的是index函数,除非你使用   
                      _remap)


/fred                 CI把这个作为传递给函数的变量


如果还有/...           CI把更多的参数作为变量传递给函数




传递数据到视图


让我们回去再看一下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"。 换句话说,它是等同于:


Say hello to Fred


请记住,使用 CI helper有二个好处:


第一, 录入字符较少


第二,URL helper自动在 config 文件中查找网站URL(和index文件名) 这意谓如果你改变你的网站URL,你只需要改变 config 文件一次,你不需要查遍代码修改变化。


URL helper还有其他的有用功能。比如:它能创建'mailto' 超链接。


  echo mailto('[email protected]', 'Click Here to Email Me');


和下面的HTML代码等效:


click here to email me


如果你担心机器人从你的网站搜集电子邮件并使用它们发垃圾邮件,用safe_mailto 代替 mailto。屏幕内容相同,并且工作也正常。但是如果检查你的HTML代码,现在变成了复杂的JS代码,机器人也许什么也抓不到。





你, 和你的用户,不需要看到这些代码。 它只是用来迷惑机器人的,以确保你的电子邮件地址的安全。而你只需要增加四个字母和一个下划线: 你用 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文件:
1< php
2  class show_menu() {
3   function show_menu() {
4    
5     $obj= & get_instance();    
6     $obj->load->helper('url');
7     $menu = anchor("start/hello/fred","Say hello to Fred   
                |");
8     $menu .= anchor("start/hello/bert","Say hello to Bert|");
9     $menu .= anchor("start/another_function","Do something  
               else |");
10    return $menu;
11  }
12}
13 >


(这时,不要为不寻常的语法担心,如“$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, 还有一个是创建菜单的例子。


使用 CI 简化数据库开发


你学习CI是因为你想要使编程更容易和更有生产力。这一章讲述CI的Active Record类。 如果CI只提供一个Active Record类,它还是物超所值的。当然,CI是免费的,只不过我要强调Active Record(以后简称AR)类的价值是非常高的,它是你提高生产力的主要工具。




AR使你以最小的代价获得最大的回报。 它简单,易于使用和维护。


这一章描述CI如何连接到一个数据库,你如何使用AR操纵数据库。你将会见到:


。 AR类与传统PHP/MySQL接口的比较


。 如何读取数据库并显示结果


。 如何创建,更新, 删除查询


CI保留让你用传统的方法编写数据库查询,但是我不会详细介绍这部分内容。它的知识完全被在线手册覆盖。使用AR类后,你可能不会再用传统的方式来做数据库查询了。


配置config文件


你或许已经注意到在这本书的大多数的章节会谈到system/application/config 文件夹和里面的config文件。这些文件对控制CI按要求工作相当必要。而且你可以让大部分的配置参数等于系统的默认值。数据库config文件在正常使用数据库之前需要进行设置。


基本上,你仅仅必须告诉它你的数据库在哪里、它是什么类型。 文件的默认值为:


$active_group="default";
$db['default']['hostname']="";
$db['default']['username']="";
$db['default']['password']="";
$db['default']['database']="";
$db['default']['dbdriver']="";


其他的选项可以保留为默认值。 必选项是:


hostname: 你的数据库的位置, 举例来说, 'localhost' 或 IP 地址


username和password: 使用者名称和密码必须有充分的权限,允许你的网站存取数据库中的数据。


database: 你的数据库的名字, 举例来说, 'websits'


dbdriver: 你正在使用的数据库的类型 - CI可受的有选项有MySQL、MySQLi、 Postgre SQL、ODBC和MS SQL


以我的经验来看, 最困难的事情之一就是把新的CI网站连接到数据库。你可能需要查询你的ISP-有时他们的数据库运行在与他们的web server IP地址不同的地方。如果你正在使用 MySQL, 他们可能提供 phpMyAdmin, 通常告诉你 hostname-这可能是 'localhost' 或者它可能是一个 IP 住址。


你可能注意到 config 文件的内容实际上是一个多维数组。在 $db数组里包含一个叫做default的数组,你所做的设置就是往里增加键/值对,例如 hostname = 127.0.0.1 。你还可以增加其他的数据库设置, 通过改变$active_group的设置可以容易地更改数据据库。


这为网站连接到数个数据库提供了可能性-举例来说, 一个测试数据库和一个产品数据库-你可以很容易地在他们之间切换。 或者你可以在二个数据库之间交换数据。


为我们的网站设计数据库


我想表达的是 CI 能用来开发正式的网站。 我现在正在维护客户的一些网站,而且我想要监控他们,用我设计的方法测试它们, 用数据库保存我想要的数据, 而且可以得到这些网站的分析报告。 因此让我们试着创建它。 先让我们确定一些目标。 它们是:


1. 用最少的人工干预管理一个或更多的远程网站


2. 对远程网站进行定期的测试


3. 生成符合要求的分析报告, 提供网站的细节和测试结果


因此, 第一件事情是我们将会需要一个网站的数据库。 建立一个名为websites的MySQL数据库,你也可以使用别的数据库产品。


现在,我们需要增加一些表来保存各种数据。让我们为网站增加一张表,字段有URL,他们的名字和密码/用户名, 和他们的类型。 我们也将会为每个网站建立一个ID字段-而且在 MySQL数据库中,至少,需要为实体生成一个唯一标识符,可以使用自动增量类型来达到这一目的。


每个网站必须有一个不同的主机,我们需要另一表来保存主机信息。一般有一个域名与主机相关联,所以我们需要一个域名表来保存有关域名的信息,还需要一个人员表来记录这些人的姓名,密码,邮件地址,备用邮件地址,手机号码,曾至宠物的名字,可能还有其它的一些什么。


因此我们的网站表需要包括这样一些字段:domain ID, host ID, 两个people ID,一个存放网站站长的ID一个存放网站管理人的ID(管理人为网站提供技术支持,保证网站正常运行.)


你能见到,这是一个完整的关系型数据库,让我们来建立它!


完整的建表文档,SQL文件格式:


websites.sql:


DROP TABLE IF EXISTS `ci_sessions`;
CREATE TABLE IF NOT EXISTS `ci_sessions` (
  `session_id` varchar(40) NOT NULL default '0',
  `peopleid` int(11) NOT NULL,
  `ip_address` varchar(16) NOT NULL default '0',
  `user_agent` varchar(50) NOT NULL,
  `last_activity` int(10) unsigned NOT NULL default '0',
  `left` int(11) NOT NULL,
  `name` varchar(25) NOT NULL,
  `status` tinyint(4) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `domains`;
CREATE TABLE IF NOT EXISTS `domains` (
  `id` int(10) NOT NULL auto_increment,
  `url` varchar(100) NOT NULL,
  `name` varchar(100) NOT NULL,
  `registrar` varchar(100) NOT NULL,
  `dateregd` int(11) NOT NULL default '0',
  `cost` float NOT NULL default '0',
  `regdfor` int(11) NOT NULL default '0',
  `notes` blob NOT NULL,
  `pw` varchar(25) NOT NULL,
  `un` varchar(25) NOT NULL,
  `lastupdate` int(11) NOT NULL default '0',
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
DROP TABLE IF EXISTS `events`;
CREATE TABLE IF NOT EXISTS `events` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL default 'not set',
  `type` enum('test','alert','report') NOT NULL,
  `testid` int(10) NOT NULL,
  `siteid` int(10) NOT NULL,
  `userid` int(10) NOT NULL,
  `reported` int(11) NOT NULL,
  `result` blob NOT NULL,
  `time` int(11) NOT NULL,
  `timetaken` float NOT NULL,
  `isalert` varchar(2) NOT NULL,
  `emailid` int(11) NOT NULL,
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=69 ;
DROP TABLE IF EXISTS `frequencies`;
CREATE TABLE IF NOT EXISTS `frequencies` (
  `id` int(10) NOT NULL,
  `name` varchar(16) NOT NULL,
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `hosts`;
CREATE TABLE IF NOT EXISTS `hosts` (
  `id` int(11) NOT NULL auto_increment,
  `cost` float NOT NULL,
  `name` varchar(100) NOT NULL,
  `hosturl` varchar(100) NOT NULL,
  `un` varchar(50) NOT NULL,
  `pw` varchar(50) NOT NULL,
  `ns1url` varchar(36) NOT NULL,
  `ns1ip` varchar(36) NOT NULL,
  `ns2url` varchar(36) NOT NULL,
  `ns2ip` varchar(36) NOT NULL,
  `ftpurl` varchar(100) NOT NULL,
  `ftpserverip` varchar(36) NOT NULL,
  `ftpun` varchar(50) NOT NULL,
  `ftppw` varchar(50) NOT NULL,
  `cpurl` varchar(36) NOT NULL,
  `cpun` varchar(36) NOT NULL,
  `cppw` varchar(36) NOT NULL,
  `pop3server` varchar(36) NOT NULL,
  `servicetel` varchar(50) NOT NULL,
  `servicetel2` varchar(50) NOT NULL,
  `serviceemail` varchar(100) NOT NULL,
  `webroot` varchar(48) NOT NULL,
  `absoluteroot` varchar(48) NOT NULL,
  `cgiroot` varchar(48) NOT NULL,
  `booked` int(11) NOT NULL,
  `duration` int(11) NOT NULL,
  `lastupdate` int(11) NOT NULL default '0',
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
DROP TABLE IF EXISTS `people`;
CREATE TABLE IF NOT EXISTS `people` (
  `id` int(11) NOT NULL auto_increment,
  `uname` varchar(25) NOT NULL,
  `pw` varchar(25) NOT NULL,
  `status` smallint(3) NOT NULL default '1',
  `name` varchar(50) NOT NULL,
  `firstname` varchar(50) NOT NULL,
  `surname` varchar(50) NOT NULL,
  `email` varchar(120) NOT NULL,
  `lastupdate` int(11) NOT NULL default '0',
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
DROP TABLE IF EXISTS `sites`;
CREATE TABLE IF NOT EXISTS `sites` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL,
  `url` varchar(100) NOT NULL,
  `un` varchar(50) NOT NULL,
  `pw` varchar(50) NOT NULL,
  `client1` int(10) NOT NULL default '0',
  `client2` int(10) NOT NULL default '0',
  `admin1` int(10) NOT NULL default '0',
  `admin2` int(10) NOT NULL default '0',
  `domainid` int(10) NOT NULL default '0',
  `hostid` int(10) NOT NULL default '0',
  `webroot` varchar(50) NOT NULL,
  `files` text NOT NULL,
  `filesdate` int(11) NOT NULL default '0',
  `lastupdate` int(11) NOT NULL default '0',
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
DROP TABLE IF EXISTS `tests`;
CREATE TABLE IF NOT EXISTS `tests` (
  `id` int(11) NOT NULL auto_increment,
  `siteid` int(11) NOT NULL default '0',
  `name` varchar(250) NOT NULL,
  `type` varchar(25) NOT NULL,
  `url` varchar(120) NOT NULL,
  `regex` varchar(250) NOT NULL,
  `p1` varchar(250) NOT NULL,
  `p2` varchar(250) NOT NULL,
  `p3` varchar(250) NOT NULL,
  `p4` varchar(250) NOT NULL,
  `p5` varchar(250) NOT NULL,
  `p6` varchar(250) NOT NULL,
  `frequency` int(10) NOT NULL default '0',
  `lastdone` int(10) NOT NULL default '0',
  `isalert` varchar(2) NOT NULL,
  `setup` int(10) NOT NULL default '0',
  `lastupdate` int(10) NOT NULL default '0',
  `notes` varchar(250) NOT NULL,
  `submit` varchar(25) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
DROP TABLE IF EXISTS `types`;
CREATE TABLE IF NOT EXISTS `types` (
  `id` varchar(7) NOT NULL,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


 


我们现在要用一个更简单容易的方法来实现这一切。 所以,让我们看看CI框架为我们提供了什么功能,我们要重点介绍AR类。


Active Record


AR是一个'设计模式'-又一个高度抽象的东西,就象 MVC。 它本身不是代码, 只是一个模式。对于代码。 有一些不同的解释。 它的核心是把你的数据库和PHP对象建立一个对应关系。每次,当你执行一个QUERY语句。每一张数据库里的表是一个类,每一行是一个对象。所有你需要做的只是创建它,修改它或者删除它。例如,“方法”,是从类继承而来。Ruby on Rails 是使用AR模式的,CI也是,尽管这两种框架实现AR的方式有一点不同。


理论的东西够多了-但是这是什么意思呢?好吧, 用代码简单和清楚地描述一下吧。


使用AR类的优点


AR节约你的时间,自动运作,使SQL语句方便易懂。


节约时间


当你在PHP编程时,每写一个数据库查询的时候,你每次一定要与数据库建立连接。 对CI来说,第一次连接数据库时,你在每个控制器或模型的构造函数里放入这样一行语名:


$this->load->database();


一旦你这样做了,你不需要重复连接, 在那个控制器或模型就可以做任意多次的查询。


你已经在 config文件中设置了关于数据库的参数,就象我们在这一章开始时看到的一样。 再一次,这使更新你的网站比较容易,如果你想要改变数据库名字、密码或位置的话。


自动机制


一经你已经连接到数据库, CI 的AR生成隐含的代码。 举例来说, 如果你进行下列的插入操作:


$data = array(
              'title'=> $title,
              'name' => $name,
              'date' => $date
              );


$this->db->insert('mytable',$data);


你正在插入的数据据已经被在幕后转换成这样一行代码:


function escapte($str) {
   switch (gettype($str)) {
   case 'string':
     $str="'".$this->escape_str($str)."'";
     break;
   case 'boolean':
     $str= ($str=== FALSE) 0: 1;
     break;
   default  :   
     $str= ($str=== NULL) 'NULL': $str;
     break;
   }             
return $str;
}


换句话说, CI框架使你的代码变得更强健。 现在,让我们看看它是如何工作的。


第一,连接数据库非常简单。 在传统的PHP编程时,你可能是这样做的:


  $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]}";
      }
  }


 


 






 
 

你可能感兴趣的:(框架,php,null,数据库,url,stylesheet)