Codeigniter的一些优秀特性总结

最近准备接手改进一个别人用Codeigniter写的项目,虽然之前也有用过CI,但是是完全按着自己的意思写的,没按CI的一些套路。用在公众的项目,最好还是按框架规范来,所以还是总结一下,免得以后别人再接手的时候贻笑大方。

1. 首先是 MVC

如果你还不知道 MVC ,应该尽快的学习,你会很快的体会到在 Model 中数据访问,在 Controller 中进行业务逻辑,在 Views 中编写 HTML 代码的价值。如果你之前没有使用过这种模式写过程序,你也许会皱起额头,不过你应该给自己尝试这样做的机会。

一条实践准则是把更少的东西放进 Controller ,记住 DRY 准则:不要重复造轮子。当在超过一个地方编写相同的代码时,应该根据它的类型来尝试编写一个 library, helper,或 model。比如数据库连接类,用得很频繁,就把它做成 model(系统已提供)。

一旦领悟了 MVC 的精髓,这将会成为一种习惯,你会从 MVC 简洁的代码中受益良多。

一个原则就是:复杂的操作都交给Model。Controller更像个建筑师。 Model是苦工。 View 是粉刷工。Controller 只需要把东西丢进Model里就可以了,不需要在意数据是否异常,然后返回一个标志位以及相应的数据。这样MVC 的 架构就体现出来了。

Model其实就像一个电器如:微波炉一样,使用方法越简单越让人喜欢,(把食物放进去 -按启动 -ok,饭熟了。)接口少的好处是,Model升级代码优化的时候,对外界的耦合度不高。即使你内部写得很烂,接口也很干净,用起来也简单。

2. Application 和 System 路径

最好是把 system 和 application 文件夹放在 webroot 以外的地方,如果 index.php 放在 FTP 服务器的 /public_html/ 路径下,应该尝试把 System 放在根目录下 /system ,这样的话,只能通过 index.php 访问你的PHP文件。

不要忘记在index.php文件中修改 $system_folder 和 $application_folder 的值,$system_folder 的值应该是相对于 index.php 文件,而 $application_folder 的值是相对于 system 目录。

3. 错误报告和调试

常常犯的一个错误是忘记关闭 PHP 错误和数据库错误报告,这样做是有风险的。在任何一个公开的站点,error_reporting 应该设置为0 ,最多只能设置为 E_ERROR,数据库设置 db_debug 应该设置为 false,基于其他安全考虑,设置不显示出错信息 ini_set('display_errors', 'Off');

在你编码和调试时,应该把 error_reporting 设置为 E_ALL ,并且在把应用程序发布前解决每一个注意和警告。

一种简易的方法是在 application/config/database.php 文件设置 db_debug 的值为一个常量 MP_DB_DEBUG,当网站在运行中,如下设置:

代码如下:

ini_set('display_errors', 'Off');
error_reporting(0);
define('MP_DB_DEBUG', false);

在编码和调试中设置为:

代码如下:

ini_set('display_errors', 'On');
error_reporting(E_ALL);
define('MP_DB_DEBUG', true);

4. 安全问题很重要

在接收任何数据到你的程序之前,不管是表单提交的 POST 数据、COOKIE 数据、URI 数据、XML-RPC 数据、还是 SERVER 数组中的数据,我们都推荐你实践下面的三个步骤:

过滤不良数据.
验证数据以确保符合正确的类型, 长度, 大小等. (有时这一步骤也可取代第一步骤)
在提交数据到你的数据库之前将其转换.
关于SQL注入,XSS,以及 CSRF ,你应该先了解它们,再决定是否采用方法来防止它们。可以参考CI手册上的安全指南 以及 输入和安全类。也许最重要的原则是在把数据提交到数据库或文件系统之前检查所有用户的输入。

SQL注入。使用 CI 自带的 Active Record 可以解决这个问题。
XSS (跨站脚本)。通过设置 $config['global_xss_filtering'] = TRUE; 开启自动过滤POST和COOKIE中的跨站脚本攻击,但需要消耗一些资源。也可以在每次处理POST和COOKIE的时候单独使用,把第二个参数设为TRUE,如 $this->input->post('some_data', TRUE); 表单验证类也提供了 XSS 过滤选项,如 $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');
CSRF (跨站请求伪造)。CI 2.0 将内置 CSRF 检查,在 Google 上搜索 "CSRF tokens" 学习更多关于在保护表单提交和 URL 链接的知识,在 Ajax 应用方面可以搜索 "double cookie submission" 或 "双提交 cookie"。
SPAM (垃圾留言和恶意注册)。通过保护你的邮件表单,评论表单,以及其他各种免费用户提交的数据来防止垃圾信息,一个简单的方法是只允许一个IP/User客户端在一分钟之内只能提交一次,一个比较好的方式是使用 Captcha ,CI2中内置了一个CAPTCHA的辅助函数。

5. 数据库 和 ORM

CodeIgniter 有一个自带的库 Active Record 能够帮助你在不使用 SQL 语句的情况下写查询语句。这在你不太精通 SQL 语句或不知道怎样防止SQL注入的情况下是一个很好的方法。

当你需要更强大的工具时,你可以考虑使用 Object Relational Mapper ,就是鼎鼎大名的 ORM 了,遗憾的是,CodeIgniter 没有自带 ORM 库,不过也有一些其他很好的选择。

最流行的或许是 DataMapper OverZealous Edition (DMZ),还可以使用 Doctrine (这里有一个教程),另一个选择 RapidDataMapper 是作者自己的作品。

6. 代码实践

编写简洁的代码,并且理解你的代码,不要只是复制粘贴别人的代码,并且不断提高编码能力。手册上的开发规范是一个能学习怎样更好编写代码的地方。

1. DRY。不要总是重复造轮子,把能重用的代码放在它应该在的地方,比如libraries, helpers 或者是 models,而不是controllers,一个经验准则:当你复制代码的时候,也许你已经第二次把它放在了错误的地方。

2. Caching (缓存)。缓存是一个提高性能的很好的方式,尤其是减少数据库的访问。可以参考网页缓存和数据库缓存,或者在论坛上搜索其他的可选方案,比如 MP_Cache 是作者自己的作品。

3. HTTP headers (HTTP头部)。在客户端你能够通过单独发送HTTP头部使浏览器缓存页面来提高性能,当你使用 AJAX 的时候你也需要了解它来禁止浏览器缓存。

一个禁止缓存的例子:

代码如下:

$this->output->set_header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
$this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate");
$this->output->set_header("Cache-Control: post-check=0, pre-check=0", false);
$this->output->set_header("Pragma: no-cache");

一个长时间保持缓存的例子(比如 css, javascript):

代码如下:

$this->output->set_header('Cache-Control: private, pre-check=0, post-check=0, max-age=2592000');
$this->output->set_header('Expires: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() + 2592000));
$this->output->set_header('Last-Modified: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() - 20));

7. 模板渲染不必每次都调用 header 与 footer

在 MY_Controller 头部和 __construct 函数中添加以下内容,用于设定默认的模版信息,其中 SITE_NAME 需要自己在 application/config/constants.php 里面自己定义:

代码如下:

class MY_Controller extends CI_Controller {
  protected $_data;    // 模版传值数组
  protected $_tplext;  // 默认模版后缀
  protected $_header;  // 默认头部模版
  protected $_footer;  // 默认底部模版
  public function __construct () {
      parent::__construct();
      $this->_data['title'] = SITE_NAME;
      $this->_tplext = '.php';
      $this->_header = 'templates/header';
      $this->_footer = 'templates/footer';
      // 开发模式下开启性能分析
      if (ENVIRONMENT === 'development') {
          $this->output->enable_profiler(TRUE);
      }
  }
}

8. 不必所有的类都继承 CI_Controller

新增的控制器不再继承 CI_Controller,而改继承 MY_Controller:

代码如下:

class Index extends MY_Controller {
  public function __construct () {
      parent::__construct();
  }
  /**
   * 前台首页
   */
  public function index () {
      $this->_data['title'] = '首页';  // 不指定则使用默认标题 SITE_NAME
      $this->_view('index/index');
  }
}

末了,再补充两个:

9. CodeIgniter的文件结构

cache用以存储缓存文件,codeigniter文件夹包含了CI的基类CI_Base,为了兼容php4和php5,CI_Base有两个版本,其中php4版本的CI_Base继承于CI_Loader。libraries里存放了大部分常用的类库,最主要的三个类:Model,View和Cotronller,自己写的任何mvc都要继承于已有的mvc类;helpers里是一些函数(方法)集合,用以辅助其他模块的方便工作。language是一个语言包,用以支持多语言。

application文件夹用以存储您的应用程序,CI已经在内部为您增加了一些子文件,包括models、views、controllers、config、errors、hooks和libraries。其中前三个文件夹是用以创建模型、视图和控制器的。您的大部分工作都应该是创建属于自己的MVC,并可在config里加入配置文件,libraries里加入一些对象和方法,用来辅助您的模型和控制器工作。而hooks也是对CI_Hooks的扩展,具体内容见下面的章节。

10. CodeIgniter的工作过程

当有一个http请求时,如http://www.google.com/blog/,首先进入CI的引导文件index.php。接下来我们看看index.php里做了哪些事情。

index首先设置了应用程序的文件夹名称为application,系统的文件夹名称为system,然后做了一系列严格的判断并转换为unix风格的服务器绝对文件路径,具体说来定义了两个比较重要的常量,APPPATH,应用程序的文件夹路径,根据分析可知,该路径可以和system同级:htdocs/application/,也可以放到system文件夹里面,作为其子文件夹:htdocs/system/application/,但推荐采用第二种方式,这样显得比较整齐;BASEPATH,网站文档的基本文件路径,写出来大概是htdoc/system/;到最后,index引导文件引入了codeigniter/codeigniter.php里。接下来我们看看codeigniter里做了什么事情。

codeigniter.php一上来就引入了三个文件:Common.php,Compat.php和config/constants.php,其中Common里包含了一些函数,用于载入类库的load_class,记录日志的log_message,和引入错误页面的show_404是几个重要的函数;Compat主要解决了php4和php5中的函数不兼容问题,而constants则定义了一些读写文件权限的常量。

紧接着codeigniter载入了第一个类库,Benchmark,这个类库最简单的一个应用就是计算网页从开始到编译结束所花掉的时间,所以您在编译开始的地方打上一个标记,渲染结束后再打上一个标记,就可以算出其中花费的时间了。

接着载入了第二个类库,Hooks,这个类库和Benchmark一样都是在system\libraries下,这个类库的作用是在程序开始编译之前给您提供一个执行其他事情的机会,Hooks会您执行其他任务提供了大约8个机会,具体参见用户指南。在这里,它导入了第一个钩子。

然后分别载入了Config,URI,Router,Output等类库,接着,检查是否有cache_override的钩子,这个钩子可以允许您调度自己的函数来替代Output类的_display_cache方法,如果没有,直接调用Output的_display_cache,检查是否有缓存内容,如果有,则直接输出缓存,退出;如果没有,则接着往下执行。

此后,继续载入Input,Language,注意此前载入的类库都是一个引用;然后又一个重要的载入,那就是CI_Base对象的载入,首先会判断php的版本,如果是php4版本的,则会首先载入Loader,然后载入Base4,因为Base4中CI_Base继承于CI_Loader,而Base5中,CI_Base与CI_Loader没有继承关系。

下一步,也是真正关键的一步了,这一步开始载入了一个Controller类,这个是个实例,而不是引用;然后通过Router来解析http地址,获得控制器和方法的名字,接着看application\controllers里是否存在这样的控制器和方法,如果没有,则报错;如果有,则开始判断。

小结

先总结这么多,以后有再补充。希望大家能投喜欢。

(0)

相关推荐

  • codeigniter实现get分页的方法

    本文实例讲述了codeigniter实现get分页的方法.分享给大家供大家参考.具体实现方法如下: public function project_search(){ $this->load->library('pagination'); $this->load->model('depart_mdl'); //获取搜索需要的信息 $data = $this->get_project_data(); $get_data = $this->input->get();

  • Codeigniter检测表单post数据的方法

    本文实例讲述了Codeigniter检测表单post数据的方法.分享给大家供大家参考.具体如下: $name = $this->input->post(' name' ) ; $email = $this- >input->post( ' email' ) ; $subj ect = $this->input->post( ' subject' ) ; $message = $this->input->post( ' message' ) ; if(empt

  • Codeigniter(CI)框架分页函数及相关知识

    一般在数据分页的时候需要获取当前页的数据和总条数,一般人是在model中封装两个函数分别获取当前页的数据和数据总条数,业务逻辑类似,感觉有点冗余,可以封装在一起: 复制代码 代码如下: /**      * 获取分页数据及总条数      * @param string @tablename 表名      * @param mixed $where 条件      * @param int $limit 每页条数      * @param int $offset 当前页      */   

  • Codeigniter框架实现获取分页数据和总条数的方法

    本文实例讲述了Codeigniter框架实现获取分页数据和总条数的方法.分享给大家供大家参考.具体实现方法如下: 一般在数据分页的时候需要获取当前页的数据和总条数,一般人是在model中封装两个函数分别获取当前页的数据和数据总条数,业务逻辑类似,感觉有点冗余,可以封装在一起 复制代码 代码如下: /** * 获取分页数据及总条数 * @param string @tablename 表名 * @param mixed $where 条件 * @param int $limit 每页条数 * @p

  • CodeIgniter框架URL路由总结

    URI 路由 一般来说,URI字符串有着和它唯一对应的控制器(controller)类/方法.URI的各个部分是如下模式(pattern): 复制代码 代码如下: example.com/class/function/id/ 然而在一些例子中,你也许想重定向这种关系来调用一个不同的类/方法(class/function),而不是与URL一一对应(的调用). 例如,你可能想使你的URL采用这种原型(prototype): 复制代码 代码如下: example.com/product/1/ exam

  • codeigniter中测试通过的分页类示例

    通用分页类(以Codeigniter测试) page_list.php 复制代码 代码如下: <?php if( ! defined('BASEPATH')) die('No Access'); /** * 分页类 */class Page_list { /**     * 总数据     * @var int     */    private $total;    /**     * 每页显示数据     * @var int     */    private $size;    /** 

  • Codeigniter的一些优秀特性总结

    最近准备接手改进一个别人用Codeigniter写的项目,虽然之前也有用过CI,但是是完全按着自己的意思写的,没按CI的一些套路.用在公众的项目,最好还是按框架规范来,所以还是总结一下,免得以后别人再接手的时候贻笑大方. 1. 首先是 MVC 如果你还不知道 MVC ,应该尽快的学习,你会很快的体会到在 Model 中数据访问,在 Controller 中进行业务逻辑,在 Views 中编写 HTML 代码的价值.如果你之前没有使用过这种模式写过程序,你也许会皱起额头,不过你应该给自己尝试这样做

  • 我放弃Python转Go语言的9大理由(附优秀书籍推荐)

    前言 Go大概2009年面世以来,已经8年了,也算是8年抗战.在这8年中,已经有很多公司开始使用Go语言开发自己的服务,甚至完全转向Go开发,也诞生了很多基于Go的服务和应用,比如Dokcer.k8s等,很多的大公司也在用,比如google(作为开发Go语言的公司,当仁不让).Facebook.腾讯.百度.阿里.京东.小米以及360,当然除了以上提到的,还有很多公司也都开始尝试Golang,这其中是什么原因呢?让我们来一起分析分析. 原因 1:性能 Go 极其地快.其性能与 Java 或 C++

  • CodeIgniter框架数据库事务处理的设计缺陷和解决方案

    起因: 在我们线上的某个业务中,使用较老版本的CodeIgniter框架,其中的DB类中,对DB事物处理部分存在着一个设计上的缺陷,或许也算不上缺陷吧.但他却影响了我们生产环境,导致连锁反应.对业务产生较大影响,且不容易排查.这个问题,我在今年的3月中旬,曾向codeigniter中国的站长Hex 报告过,之后,我也忘记这件事情了.直到今天,我们线上业务又一次以为这个问题,害的我又排查一次.具体原因,各位且先听我慢慢说完.(这个问题同样存在于最新版本Version 2.1.0中) 分析: 以Co

  • 总结AngularJS开发者最常犯的十个错误

    前言 AngularJS易于开发.较多的特征及较好的效果导致了较多的应用,伴随而来的是一些陷阱.本文列举了AngularJS的一些共同的易于出问题的地方,下面来一起看看吧. 一.MVC目录结构 AngularJS,直白地说,就是一个MVC框架.它的模型并没有像backbone.js框架那样定义的如此明确,但它的体系结构却恰如其分.当你工作于一个MVC框架时,普遍的做法是根据文件类型对其进行归类: templates/ _login.html _feed.html app/ app.js cont

  • FreeBSD 7.0 图文安装教程第1/4页

    FreeBSD 是一种优秀的 Unix 类操作系统,它以卓越的稳定性.安全性和性能著称,是目前主流服务器操作系统之一.就在不久前,FreeBSD 发布了一个新的重大版本 FreeBSD 7.0,新版本增加了许多优秀特性.现在我们以标准PC机为例,开始介绍 FreeBSD 7.0 的安装过程. 首先,你需要拥有 FreeBSD 7.0 的安装光盘,你可以在官方网站 http://www.freebsd.org/ 中下载到安装镜像,刻录成 CD 后使用.如果你是在虚拟机中安装,直接下载镜像即可.Fr

  • Objective-C的MKNetworkKit开发框架解析

    什么是MKNetworkKit? MKNetworkKit是一个 O-C 编写的网络框架,支持块,ARC 且用法简单. MKNetworkKit 集 ASIHTTPRequest 和 AFNetworking 两个框架于一体.在集成二者的优秀特性之外,还增加了一堆新的功能.尤其是,相比起其它框架,它能让你更轻松地编写代码.它让你彻底远离那些恶心的网络代码. 特点 超轻量级框架 整个框架只有 2 个类和一些类别方法.因此,它的使用极其简单. 在整个程序中只有一个全局队列. 高度依赖互联网连接的 a

  • Python入门篇之面向对象

    面向对象设计与面向对象编程的关系   面向对象设计(OOD)不会特别要求面向对象编程语言.事实上,OOD 可以由纯结构化语言来实现,比如 C,但如果想要构造具备对象性质和特点的数据类型,就需要在程序上作更多的努力.当一门语言内建 OO 特性,OO 编程开发就会更加方便高效.另一方面,一门面向对象的语言不一定会强制你写 OO 方面的程序.例如 C++可以被认为"更好的C":而 Java,则要求万物皆类,此外还规定,一个源文件对应一个类定义.然而,在 Python 中,类和 OOP 都不是

  • 极力推荐一款小巧玲珑的可视化编辑器bootstrap-wysiwyg

    先来看看官方对这款编辑器的相关功能描述吧. 1.在Mac和Wndows平台上能够自动针对常用操作绑定标准热键 2.可以通过拖拽插入图片:支持图片上传(也可以获取移动设备上的照片) 3.语音识别输入(仅限Chrome浏览器) 4.允许自定义工具条:不生成额外标签:支持网站充分利用Bootstrap.Font Awesome等工具库的优秀特性 5.没有强制规定的样式一切都由你做主 6.依赖浏览器的标准特性,没有非标准代码:工具条和键盘功能均可定制,并且能够执行任何浏览器支持的命令 7.不会自己创建一

  • python自带的http模块详解

    挺久没写博客了,因为博主开始了今年另一段美好的实习经历,学习加做项目,时间已排满:很感谢今年这两段经历,让我接触了golang和python,学习不同语言,可以跳出之前学习c/c++思维的限制,学习golang和python的优秀特性以及了解在不同的场景,适用不同的语言:而之前学习linux和c/c++,也使我很快就上手golang和python; 我学习的习惯,除了学习如何使用,还喜欢研究源码,学习运行机制,这样用起来才会得心应手或者说,使用这些语言或框架,就和平时吃饭睡觉一样,非常自然:因为

  • Prototype框架详解

    这里所说的"Prototype"不是JavaScript编程中的原型("prototype"),而是由"Sam Stephenson"写的一个JavaScript类库.这个构思奇妙,而且兼容标准的类库,能帮助程序员轻松建立有高度互动的"web2.0"特性的富客户端页面. •很多人初次接触Prototype,都是从其"$"系列函数开始的,这些类似于桌面应用程序的快捷方式,是Prototype框架中使用频率最高

随机推荐