首頁 >後端開發 >php教程 >php框架 Codeigniter 的一些優秀實踐

php框架 Codeigniter 的一些優秀實踐

伊谢尔伦
伊谢尔伦原創
2016-11-26 14:23:57920瀏覽

最近準備接手改進一個別人用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);

4reee

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 库,不过也有一些其他很好的选择。

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_Cont roller 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一樣都是在systemlibraries下,這個類別庫的作用是在程式開始編譯之前給您一個執行其他事情的機會,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位址,取得控制器和方法的名字,接著看applicationcontrollers裡是否有這樣的控制器和方法,如果沒有,則報錯;如果有,則開始判斷。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn