PHP專案中CodeIgniter使用的一些建議

2016-03-05    分類:WEB開發、程式設計開發、首頁精華0人評論發表於2016-03-05

本文由碼農網 – 邱康原創,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

最近再給一個APP寫API,同時還要寫相應的後臺管理網站。為了便於開發和程式碼組織與管理,我決定採用一個現有的框架。Codeigniter由於其輕量容易自定製的特點吸引了我,一路開發過來也有大半年時間了,寫下一些自己在開發過程中的一些體會來與大家共勉。

開發工具

開發工具有好多,每個人的習慣也不同。Eclipse一直是我的最愛,那麼怎麼讓Eclipse支援codeigniter呢?

首先這是個PHP專案,所以得讓Eclipse支援PHP。假設你的計算機已經安裝了PHP,那麼最簡單的做法就是在Eclipse的market space中搜尋PDT並安裝。具體操作:Help -> Eclipse Marketplace。在輸入框中輸入PDT,點選find,如圖:

點選右下方的install,等待幾分鐘即可。

現在可以在Eclipse中寫PHP了,不過對於codeigniter來說,經常用到的語句類似如下:

$this->load->model ( 'user_model' );

$this->input->post ('phone');

每次都要手動輸入這麼長的類似的語句對於追求高效的人來說顯然是不可取的,所以得讓Eclipse支援codeigniter特定的程式碼提示,包括Controller和Model。把如下程式碼新增到

system/core/ 目錄下的Controller檔案中CI_Controller類的建構函式之前,這其實就是進行

變數宣告,Model檔案也是同樣操作。

 /**
       * @var CI_Config
       */

       var $config;

       /**
       * @var CI_DB_active_record
       */

       var $db;

       /**
       * @var CI_Email
       */

       var $email;

       /**
       * @var CI_Form_validation
       */

       var $form_validation;

       /**
       * @var CI_Input
       */

       var $input;

       /**
       * @var CI_Loader
       */

       var $load;

       /**
       * @var CI_Router
       */

       var $router;

       /**
       * @var CI_Session
       */

       var $session;

       /**
       * @var CI_Table
       */

       var $table;

       /**
       * @var CI_Unit_test
       */

       var $unit;

       /**
       * @var CI_URI
       */

       var $uri;

       /**
       * @var CI_Pagination
       */

       var $pagination;

現在效果如下:

只需輸入$this 即可產生程式碼提示,效率提高不少。

自定義輔助函式和庫

一般一個專案中會有許多相同的邏輯,會使用到相同的程式碼。如果每次都去複製貼上不僅麻煩而且不利於後續修改,想到需要修改一個邏輯就要到每個檔案裡修改程式碼就覺得可怕(涉及到設計模式這一塊了,值得我們學學)。所以你要善於利用那些自定義輔助函式(helpers)和自定義的庫(libraries)。把相同的邏輯封裝成函式或者類,每次遇到相同的邏輯之時只需呼叫現成的helper或者library即可,修改也只需要在helper或者library中一處修改,不需要到處找程式碼。

舉一個我專案中的例子。API需要給APP傳送的請求返回json格式資料,那麼在PHP中的一種實現方法就是:

echo json_encode ( $data);//$data 是array型別的資料

但是如果$data中包含中文字元的話,輸出的json資料會把中文變成Unicode編碼,為了避免客戶端需要再次處理資料,需要加入一個引數,即:

echo json_encode ( $data , JSON_UNESCAPED_UNICODE);//$data 是array型別的資料

這樣就能輸出原始的中文了。但是問題又來了,每次都要寫這麼長一段程式碼實在是麻煩,所以封裝成一個輔助函式。在application/helpers 資料夾中新建一個檔案render_helper.php。其中程式碼如下:

<?php

defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );

/**

 * 列印不轉義中文的json

 * @param [array] $data

 */

function echo_json($data) {

       echo json_encode ( $data, JSON_UNESCAPED_UNICODE );

}

那麼每次呼叫之時只需先在類中的建構函式載入該輔助函式,如下:

$this->load->helper ( 'render' ); // 載入列印json的自定義輔助函式

就可以在本類的所有成員函式中使用該方法:

echo_json ( $data);

這樣省時省力(加上Eclipse的程式碼提示,你只需要輸入echo,這個函式就可以出來了)。以後需要修改成編碼後中文,或者轉換成英文等等(奇怪的需求~)你都可以只修改一行程式碼,效率提高不少。

善用快取

如果一個APP的活躍使用者不是很多,那麼傳統的LAMP架構就可以應付了。但是隨著使用者的逐漸增多,要想提高併發量,最好還是加一個快取。在memcached和redis中,我選擇了redis,主要因為它資料型別更豐富(不僅支援key-value型的資料,同時還提供list,set,zset,hash等資料結構的儲存),能幫你實現一部分邏輯(避免重複造輪子)。與Eclipse配置同理,首先得讓計算機上的PHP能夠和redis通訊(假設你的計算機已經安裝了redis),那麼首選的是phpredis擴充套件,這裡介紹一下我在Debain伺服器上的配置過程,執行的命令如下:

wget https://github.com/nicolasff/phpredis/archive/master.tar.gz  #下載擴充套件

tar xvf master.tar.gz      #解壓目錄

cd phpredis-master/     #進入解壓後的目錄

phpize

./configure --enable-redis

make && make install    #安裝

#但是報錯-bash: phpize: command not found(在使用apt-get install php5安裝php時,默

#認是沒有安裝phpize的,我們安裝phpredis時,需要用到phpize,因此,需要先安裝#phpize。我們通過安裝php開發者工具來獲取phpize。執行如下命令即可: apt-get install #php5-dev)

ls  /usr/lib/php5/20100525/#根據安裝提示的檔案,結果:curl.so  gd.so  redis.so

vim /etc/php5/apache2/php.ini   #開啟PHP配置檔案

# Dynamic Extensions 後面新增extension=redis.so,因為上面命令結果顯示有redis.so

/etc/init.d/apache2 restart       #重啟Apache伺服器

現在PHP就能和redis通訊了,測試如下:

<?php

 $redis = new Redis();

 $redis->connect('127.0.0.1',6379);

 $redis->auth('你的密碼');//為了安全,要給redis設定密碼

 $redis->set('tom','hanks');

 echo ' tom:'.$redis->get('tom'). '</br>';// tom:hanks

echo 'will:'.$redis->get('will'); //will:

?>

好了,現在來到配置codeigniter使其能夠使用redis的步驟了。Codeigniter3.0.0本身具有redis支援,但是它實現的功能過於單一,不能夠滿足我的業務需求,所以必須要修改。但是最好不要直接在/system/libraries/Cache/drivers/Cache_redis.php 中修改,因為以後codeigniter升級採用直接覆蓋system資料夾的形式,會覆蓋掉你的程式碼。所以最明智的做法還是自己建立一個庫,具體步驟如下:

1、在application/config/redis.php 中加入配置資訊:

<?php

defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );

$config ['socket_type'] = 'tcp';

config ['host'] = '你的伺服器域名或者IP';

$config ['password'] = '你的redis密碼';

$config ['port'] = 6379;

$config ['timeout'] = 0;

2、在application/libraries中建立如下圖的檔案結構

Rediscli.php 程式碼如下:

<?php

defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );

class Rediscli extends CI_Driver_Library {

       public $valid_drivers;

       public $CI;

       function __construct() {

              $this->CI = & get_instance ();

              $this->valid_drivers = array (

                            'default'

              );

       }

}

Rediscli_default.php 程式碼從/system/libraries/Cache/drivers/Cache_redis.php 直接拷貝過來,唯一的不同是把類名從CI_Cache_redis改為Rediscli_default,這樣就能按照官方的使用方法使用我們自己寫的庫。

3、現在可以在Rediscli_default.php中新增或者修改方法,具體操作取決於你自己的應用的需求。比如在我的應用中,需要保持一個一定長度的佇列,所以在Rediscli_default類中新增如下兩個方法:

/**

       * 彈出連結串列頭元素

       * @param unknown $key,連結串列名              

       */

       public function lpop($key) {

              return $this->_redis->lPop ( $key );

       }

       /**

       * 插入元素到表尾

       * @param unknown $key,連結串列名              

       * @param unknown $value,待插入值              

       */

       public function rpush($key, $value) {

              return $this->_redis->rPush ( $key, $value );

       }

某個類需要呼叫該庫時只需在其建構函式中新增如下程式碼:

$this->load->driver ( 'rediscli' ); // 載入redis自定義庫

$this->rediscli->default->is_supported ();//判斷是否支援redis並開啟連線

則該類的每個函式就都可以使用Rediscli_default類中的任一方法,示例如下:

$this->rediscli->default->lpop('delnews');//彈出名為delnews的連結串列頭元素

$this->rediscli->default->rpush('delnews',$nid);//該連結串列加入尾元素$nid

登陸邏輯的實現

對於我們的APP來說,每個請求都要判斷使用者是否已登陸,對於登陸的合法使用者正常顯示請求,對於未登入的使用者提示“請先登入”。一般的web應用採用cookie-session機制,一般的session都是以檔案形式儲存在伺服器上,考慮到檔案訪問慢於記憶體訪問,我們可以配置codeigniter的session儲存於redis中。我這裡模仿這種機制:使用者正常login後返回一個特定的id和特定的token(你可以自定義產生演算法),伺服器以id為key、token為value直接儲存在redis中。以後的每次訪問APP都必須帶上用appsecret(預定義)加密後的引數id和token,伺服器端校驗成功即正常返回資料,否則提示“請先登入”。

那麼是否每個類都需要寫一遍檢查登陸的程式碼呢?當然不能這麼幹,我們可以自定義一個基類,在該基類的建構函式中檢查登陸狀態(還可以在這裡載入常用的輔助函式和庫,比如上面的render_helper 和 rediscli)。然後其他的業務邏輯的類就繼承該基類,並完成其自身邏輯即可。

具體操作就是在 application/core 中新建檔案 MY_Controller.php,該檔案對應MY_Controller類(繼承CI_Controller類)。該類只需要一個建構函式完成上述功能即可。

然後其它邏輯類只需繼承MY_Controller類就不必再次校驗登陸狀態,而只需完成自身邏輯。

總結

Codeigniter是我最喜歡的一個PHP框架(相比於thinkPHP,Zend Framework等等),主要在於其易安裝,輕量,易自定製的優點。把握好這些優點,我們就能寫出不遜於那些重量級框架寫出來的應用,並且省時省力。

作為一個學生,在摸索學習的路上還有很多問題需要解決,本文的目的在於和大家分享,更重要的是大家有什麼建議或者批評請一定不吝賜教哈,我的微博:邱康singasong

本文連結:http://www.codeceo.com/article/php-codeigniter-usage.html
本文作者:碼農網 – 邱康
原創作品,轉載必須在正文中標註並保留原文連結和作者等資訊。]

相關文章