Codeigniter的一些優秀實踐

使用規范總結
服務器君一共花費了109.433 ms進行了4次數據庫查詢,努力地為您提供了這個頁面。
試試閱讀模式?希望聽取您的建議

最近準備接手改進一個別人用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 數組中的數據,我們都推薦你實踐下面的三個步驟:

  1. 過濾不良數據.
  2. 驗證數據以確保符合正確的類型, 長度, 大小等. (有時這一步驟也可取代第一步驟)
  3. 在提交數據到你的數據庫之前將其轉換.

關于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里是否存在這樣的控制器和方法,如果沒有,則報錯;如果有,則開始判斷。

小結

先總結這么多,以后有再補充。

本文地址:http://www.snpmgr.live/librarys/veda/detail/2679,歡迎訪問原出處。

不打個分嗎?

轉載隨意,但請帶上本文地址:

http://www.snpmgr.live/librarys/veda/detail/2679

如果你認為這篇文章值得更多人閱讀,歡迎使用下面的分享功能。
小提示:您可以按快捷鍵 Ctrl + D,或點此 加入收藏

大家都在看

閱讀一百本計算機著作吧,少年

很多人覺得自己技術進步很慢,學習效率低,我覺得一個重要原因是看的書少了。多少是多呢?起碼得看3、4、5、6米吧。給個具體的數量,那就100本書吧。很多人知識結構不好而且不系統,因為在特定領域有一個足夠量的知識量+足夠良好的知識結構,系統化以后就足以應對大量未曾遇到過的問題。

奉勸自學者:構建特定領域的知識結構體系的路徑中再也沒有比學習該專業的專業課程更好的了。如果我的知識結構體系足以囊括面試官的大部分甚至吞并他的知識結構體系的話,讀到他言語中的一個詞我們就已經知道他要表達什么,我們可以讓他坐“上位”畢竟他是面試官,但是在知識結構體系以及心理上我們就居高臨下。

所以,閱讀一百本計算機著作吧,少年!

《編程之美:微軟技術面試心得》 《編程之美》小組 (作者)

《編程之美:微軟技術面試心得》是一本讓人著迷的書!閱讀起來。有些題目的內容會引起強烈的共鳴,尤其是那些自己非常熟悉并且又深知解答的題目;也有一些題目讓我異常驚詫,原來除了我所知道的解答思路之外,還有更好的解答以及更深層次的原因。還有一些題目是從來沒想到過的。閱讀過程是一次愉快的享受,也是腦細胞持續活躍的過程。

更多計算機寶庫...

燃烧吧足球登陆