聚會時間公告: 3月份聚會為3月27號星期六下午兩點在
MocaMona / 講者: ->

十二月 30, 2009
» [PHP Framework] How to implement Plurk API in CodeIgniter

ci_logo2 (by appleboy46)
很開心在12月看到 Plurk Release API 出來,而自己也跟網路上一些朋友合作開發 PHP implementation of Plurk API,Plurk (簡稱噗浪)在台灣這一兩年紅了起來,網路高手分別針對噗浪研究產生非官方的 API,現在官網 Release 出來,提供了 JavaPython 的 Example,我想因為 Plurk 是用 Python 寫出來的,所以提供了範例,但是 API 出來沒多久,roga 就集合了網路一些強者,一起開發了 PHP Plurk API,我也拿了此 API 在實作到 CodeIgniter Framework,讓在使用此套 open source 的使用者可以享用 Plurk API。不過從2009.12.29日之後,Plurk 官網有限制每天只能 call 50.000 次,已經蠻多了,不要操掛 Plurk 的機器阿。

1. 首先下載 CodeIgniter 1.7.2 版本:下載
2. 新增檔案 plurk_config.php 和 plurk_constant.php 到 application/config/ 目錄底下
plurk_config.php 檔案內容如下:

<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

$config['api_key'] = "xxxxx";
$config['username'] = "xxxxx";
$config['password'] = "xxxxx";

?>

api_key 請到 Plurk API 網站申請,申請過後會寄信到您的信箱,username 是 Plurk 帳號,password 是 Plurk 密碼。
plurk_constant.php
http://github.com/appleboy/CodeIgniter-Plurk-API/blob/master/config/plurk_constant.php

這檔案不需要修改什麼,唯一要注意的是,可以設定 Plurk 的 log 跟 Cookie 檔案位置,目前是存放到 application/logs/ 目錄,如果沒有此目錄,請麻煩建立此資料夾,之後設定 755 讓 Web 可以存取。

define('PLURK_COOKIE_PATH', APPPATH . 'logs/cookie');
define('PLURK_LOG_PATH', APPPATH . 'logs/plurk_log');

3. 新增 Common.php 跟 Plurk.php 檔案到 application/libraries/ 資料夾裡面
Common.php 檔案如下:
http://github.com/appleboy/CodeIgniter-Plurk-API/blob/master/libraries/Common.php
Plurk.php 主程式:
http://github.com/appleboy/CodeIgniter-Plurk-API/blob/master/libraries/Plurk.php

4. 接下來就可以新增 Controller 來測試看看,直接些改 CodeIgniter 所預設的 Welcome Controller

<?php
class Welcome extends Controller {
    function __construct()
    {
        parent::Controller();
        $this->config->load('plurk_config');
        $this->load->library('plurk');

    }
   
    function index()
    {
        $api_key = $this->config->item('api_key');
        $username = $this->config->item('username');
        $password = $this->config->item('password');
        $this->plurk->login($api_key, $username, $password);  
       
        /**
         ******************************************
         * @Get plurks
         *
         * set plurk id = {123, 456, 789}
         ******************************************/

       
        echo "<h1>----- get plurks -----</h1>";
        echo "<pre>";
        print_r($this->plurk->get_plurks());
        echo "</pre>";
       
        /*
        echo "<h1> ----- get someone's plurk ----- </h1>";
        print_r($plurk->get_plurk(123));
       
        echo "<h1> ----- get unread plurks ----- </h1>";
        print_r($plurk->get_unread_plurks());
       
        echo "<h1> ----- mark plurk as read ----- </h1>";
        $plurk->mark_plurk_as_read(array(123,456,789));
       
        echo "<h1> ----- add plurk ----- </h1>";
        $plurk->add_plurk('en', 'says', 'Hello World');
       
        echo "<h1> ----- edit plurk ----- </h1>";
        $plurk->edit_plurk(123, 'be edited');
       
        echo "<h1> ----- delete plurk ----- </h1>";
        $plurk->delete_plurk(123);
       
        echo "<h1> ----- mute plurks ----- </h1>";
        print_r($plurk->mute_plurks(123));
       
        echo "<h1> ----- unmute plurks ----- </h1>";
        print_r($plurk->unmute_plurks(123));
        */

       
        /**
         ******************************************
         * @Get alerts
         *
         ******************************************/

       
        /*
        echo "<h1> ----- get active alerts ----- </h1>";
        print_r($plurk->get_active());
       
        echo "<h1> ----- get a list of past 30 alerts ----- </h1>";
        print_r($plurk->get_history());
       
        echo "<h1> ----- remove notification ----- </h1>";
        $plurk->remove_notification(123);
        */

       
        /**
         ******************************************
         * @Get plurk's responses
         *
         ******************************************/

       
        /*
        echo "<h1> ----- get responses ----- </h1>";
        echo "set plurk id = 123</h1>";
        print_r($plurk->get_responses(123));
       
        echo "<h1> ----- add response ----- </h1>";
        echo "set plurk id = 123</h1>";
        print_r($plurk->add_response(123, 'test response', 'says'));
       
        echo "<h1> ----- delete response ----- </h1>";
        echo "set plurk id = 123, response id = 456</h1>";
        $plurk->delete_response(123, 456);
        */

       
        /**
         ******************************************
         * @Control user
         *
         ******************************************/

       
        /*
        echo "<h1> ----- get own profile ----- </h1>";
        print_r($plurk->get_own_profile());
       
        echo "<h1> ----- get user public profile ----- </h1>";
        echo "set user id = 123</h1>";
        print_r($plurk->get_public_profile(123));
       
        echo "<h1> ----- get user info ----- </h1>";
        print_r($plurk->get_user_info());
       
        echo "<h1> ------ get users friends (nick name and full name)</h1>";
        print_r($plurk->get_completion());
       
        echo "<h1> ----- get block user's list ----- </h1>";
        print_r($plurk->get_blocks());
       
        echo "<h1> ----- block user ----- </h1>";
        $plurk->block_user(5366984);
       
        echo "<h1> ----- unblock user ----- </h1>";
        $plurk->unblock_user(5366984);
        */

       
        /**
         ******************************************
         * @Control friends
         *
         * set user id = 123
         * set friend id = 789
         ******************************************/

       
        /*
        echo "<h1> ----- get someone's friends ----- </h1>";
        print_r($plurk->get_friends(123));
       
        echo "<h1> ----- become someone's friend ----- </h1>";
        $plurk->become_friend(789);
       
        echo "<h1> ----- remove friend ----- </h1>";
        $plurk->remove_friend(789);
       
        echo "<h1> ----- accept friendship request as friend ----- </h1>";
        $plurk->add_as_friend(789);
       
        echo "<h1> ----- accept all friendship requests as friends ----- </h1>";
        $plurk->add_all_as_friends();
       
        echo "<h1> ----- deny friendship ----- </h1>";
        $plurk->deny_friendship(789);
        */

       
        /*
         ******************************************
         * @Control fans
         *
         * set user id = 123
         * set fan id = 789
         ******************************************/

         
        /*
        echo "<h1> ----- get following ----- </h1>";
        print_r($plurk->get_following());
       
        echo "<h1> ----- get someone's fans ----- </h1>";
        print_r($plurk->get_fans(123));
       
        echo "<h1> ----- become someone's fan ----- </h1>";
        $plurk->become_fan(5366983);
       
        echo "<h1> ----- accept a friendship request as fan ----- </h1>";
        plurk->add_as_fan(789);
       
        echo "<h1> ----- accept all friendship requests as fans ----- </h1>";
        $plurk->add_all_as_fan();
        */

       
        /* can't use */
        //echo "<h1> ----- set user following ----- </h1>";
        //echo "user id = 789</h1>";
        //echo ($plurk->set_following(3440147, $follow = FALSE)) ? 'success' : 'disable';
       
       
        /*
         ******************************************
         * @Search
         *
         ******************************************/

       
        /*
        echo "<h1> ----- search plurk ----- </h1>";
        print_r($plurk->search_plurk('php-plurk-api'));
       
        echo "<h1> ----- search user ----- </h1>";
        print_r($plurk->search_user('roga lin'));
       
        echo "<h1> ----- get emoticons ----- </h1>";
        print_r($plurk->get_emoticons());
        */

       
       
        /*
         ******************************************
         * @Clique
         *
         ******************************************/

       
        /*
        echo "<h1> ----- get clique list ----- </h1>";
        print_r($plurk->get_cliques());
       
        echo "<h1> ----- create a clique ----- </h1>";
        print_r($plurk->create_clique("test"));
       
        echo "<h1> ----- rename clique ----- </h1>";
        print_r($plurk->rename_clique("test","test1"));
       
        echo "<h1> ----- get clique ----- </h1>";
        print_r($plurk->get_clique('test1'));
       
        echo "<h1> ----- add a user to a clique ----- </h1>";
        print_r($plurk->add_to_clique("test1", 3440147));
       
        echo "<h1> ----- remove a user from a clique ----- </h1>";
        print_r($plurk->remove_from_clique("test1", 3440147));
       
        echo "<h1> ----- delete a clique ----- </h1>";
        print_r($plurk->delete_clique("test1"));  
        */
     
    }
}
/* End of file welcome.php */
/* Location: ./system/application/controllers/welcome.php */

底下載入相關設定以及 Plurk Library,當然也可以設定在 application/config/autoload.php 裡面喔

$this->config->load('plurk_config');
$this->load->library('plurk');

這樣就算是安裝成功了,大家可以試試看,如果需要程式碼,可以到 CodeIgniter-Plurk-API 下載完整的程式碼

INSTALLATION

Download all file from this site.

$ http://github.com/appleboy/CodeIgniter-Plurk-API/archives/master
$ git clone git://github.com/appleboy/CodeIgniter-Plurk-API.git

Copy some files into directory.

$ copy config/plurk_config.php your_application/config/
$ copy config/plurk_constant.php your_application/config/
$ copy libraries/Common.php your_application/libraries/
$ copy libraries/Plurk.php your_application/libraries/

Create logs directory, and chmod 755 directory

$ mkdir your_application/logs
$ chmod 755 your_application/logs
$ chown www:www your_application/logs

Edit config/plurk_config.php, and configure your api key, plurk username, and plurk password

$config['api_key'] = "xxxxx";
$config['username'] = "xxxxx";
$config['password'] = "xxxxx";

Test your controller file: welcome.php

http://localhost/welcome

Related View

十月 26, 2009
» [CodeIgniter] 解決 CI 下載函數 force_download 在 IE 底下檔案標題亂碼

CodeIgniter
CodeIgniter 底下提供了 force_download 函數,讓使用者可以直接下載檔案,但是會遇到中文的問題,IE 底下開起來檔名會是亂碼,force_download(’filename’, ‘data’) 如果 filename 使用中文,測試 FireFoxChrome 都是沒問題的,唯獨 IE 開起來就是有問題,所以麻煩請修改 helpers/download_helper.php 這隻程式。

if ( ! function_exists('force_download'))
{
    function force_download($filename = '', $data = '')
    {
        if ($filename == '' OR $data == '')
        {
            return FALSE;
        }

        // Try to determine if the filename includes a file extension.
        // We need it in order to set the MIME type
        if (FALSE === strpos($filename, '.'))
        {
            return FALSE;
        }
   
        // Grab the file extension
        $x = explode('.', $filename);
        $extension = end($x);

        // Load the mime types
        @include(APPPATH.'config/mimes'.EXT);
   
        // Set a default mime if we can't find it
        if ( ! isset($mimes[$extension]))
        {
            $mime = 'application/octet-stream';
        }
        else
        {
            $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
        }
   
        // Generate the server headers
        if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
        {
            header('Content-Type: "'.$mime.'"');
            header('Content-Disposition: attachment; filename="'.iconv('utf-8', 'big5', $filename).'"');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header("Content-Transfer-Encoding: binary");
            header('Pragma: public');
            header("Content-Length: ".strlen($data));
        }
        else
        {
            header('Content-Type: "'.$mime.'"');
            header('Content-Disposition: attachment; filename="'.$filename.'"');
            header("Content-Transfer-Encoding: binary");
            header('Expires: 0');
            header('Pragma: no-cache');
            header("Content-Length: ".strlen($data));
        }
   
        exit($data);
    }
}

裡面利用了 iconv 把 utf-8 編碼,改成 big5,這樣在 IE 底下就不會出現問題了

header('Content-Disposition: attachment; filename="'.iconv('utf-8', 'big5', $filename).'"');

Related View

九月 16, 2009
» [新聞] CodeIgniter v1.7.2 Released

CodeIgniter 終於 Release V1.7.2 版本了,官方網站也公佈了此消息,那這次跟 v1.7.2 版本有哪些不一樣呢,我想最主要應該是支援 PHP 5.3.0 了

  • 相容於 PHP 5.3.0
  • 新增 Cart Class 類別
  • 改善 Form helper 函數
  • 新增 is_php() 到 Common functions 來更有善的比較 PHP 版本
  • 無數個 bug 修正
  • 修改 show_error() 函數功能

更多的 bug 修正,可以觀看 change log,我也順便了 send-pr 給 FreeBSD ports maintainer 請他 update 到 1.7.2:ports/138848,台灣的官網也需要來修正了,已經更新了 v1.7.2 上去,至於繁體中文文件方面還沒更新,有時間會把它更新,如果有任何問題,可以先到論壇留言找我。

Related View

八月 18, 2009
» [CodeIgniter] 分享中文官方網站範例程式碼

之前在高雄開了一堂:[CodeIgniter] Open Source PHP Web Framework 系列講座,在上課過程,我很強調大家可以多多參考網路上的範例來學習,所以找了官方網站的程式碼想分享給大家,希望大家看完程式碼,可以針對 CodeIgniter 的 Model Views Controller 有比較深入的瞭解,如果有不懂的地方,可以來論壇這邊提出問題,我會儘快回答大家,底下是程式碼的下載網址,包含論壇程式 PHPBB3,以及所有影片程式碼,大家可以參考看看:

檔案下載

裡面有需要注意的,就是 .htaccess 檔案:

RewriteEngine on
RewriteBase /
RewriteCond $1 !^(videos|download_files|user_guide|forum|index\.php|admin|css|flash|images|img|includes|js|language|captcha|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

裡面會附上 db.sql 檔案,這是資料庫檔案,請麻煩匯入到您的資料庫,然後修改 system/application/config/database.php 內容的資料庫相關資訊,這樣就可以了。

Related View

七月 26, 2009
» [教學] 加入 Sphinx 繁體中文全文檢索 on CodeIgniter

sphinx
在寫這篇之前,有介紹過了 Sphinx 一篇針對繁體中文檢索的教學,大家可以先去參考看看,把 Sphinx 服務架設起來,在搭配 CodeIgniter MVC Framework 使用,把 Sphinx 提供的 PHP API 放到 CI 的 Library 裡面就可以運作了,首先去官網下載套件,然後參考官方的安裝文件,大致上就差不多了,下載的檔案裡面會有 api 資料夾,裡面提供了 python, ruby, java, php 的 client 端檔案,讓您去自由呼叫,PHP 部份可以看 sphinxapi.php 這個檔案,我們也只需要把這個檔案放入 CI 的 Library 裡面,不過寫法有些改變,請看底下

1. 非常簡單,開啟 sphinxapi.php 然後前面加上:

這是 Library 的擴充寫法,可以參考中文文件。存檔之後放入 application/libraries 檔名取 Sphinxapi.php 就可以了
2. 如何使用:預先載入到建構子

function __construct()
{
parent::Controller();
$this-&gt;load-&gt;library("sphinxapi");
}

或者是加入到 config/autoload.php 裡面也是可以的

3. 使用 sphinxapi,請先設定 sphinxapi 裡面的 host 跟 port,設定完之後,就可以正常連接了

$index = 'test2'; // 您要索引的名稱
$start = 0; // 抓取起始筆數
$limit = 100;   // 一次抓取 100 筆
$this-&gt;sphinxclient-&gt;SetWeights(array(100,1));
$this-&gt;sphinxclient-&gt;SetMatchMode(SPH_MATCH_ALL);
$this-&gt;sphinxclient-&gt;SetLimits($start,$limit);
$this-&gt;sphinxclient-&gt;SetArrayResult(true);
// $keyword 你要查詢的字串
$res = $this-&gt;sphinxclient-&gt;Query($keyword,$index);

$res 會回傳我們想要的資料,拿到之後,利用 $total = $res['total_found']; 取得查到的筆數,然後利用底下程式碼取得資料 auto increment ID

foreach($res['matches'] as $row)
{
$vedio[] = $row['id'];
}

在丟到 model 找到自己想要的資料,這樣就可以了,其實還有很多進階作法,這裡就不多說了,可以參考官方文件,都是設定 sphinx.conf 檔案。最後附上 sphinxapi.php 檔案程式碼:檔案下載

Related View

七月 20, 2009
» [CodeIgniter] Open Source PHP Web Framework 系列講座

update 2009.07.23: 有影音檔可以看了,請點選這裡

7月18日受到 OSSF::自由軟體鑄造場(Open Source Software Foundry)的邀請,在高雄講一場 Open Source PHP Web Framework系列講座 - CodeIgniter (高雄場次) ,我準備了 87 張投影片,包含介紹了 CodeIgniter 目前台灣官方網站的狀況,以及流行 PHP MVC Framework 的比較,大部分時間花在 Controller, Views 身上,還有 helper function, Library Class 教學使用,沒有把 Model 精華部份教完有點可惜,內容可能有點多,一整天六小時的課程把教學消化,好像有點困難了,這也是給我一點警惕,下次教學這部份內容要在改變一下,這樣對於來上課的學員,才不會感到排斥,最後非常感謝酷學園的阿民來幫忙錄影,以及飛亨現場支援,以及讓我有這次機會可以上台分享這幾個月在 CI 上面的使用心得,底下是我這次的上課投影片,如果大家有問題可以到論壇討論,或者是看看繁體中文教學文件,如果對於翻譯教學文件有興趣,可以再跟我聯絡喔。

Related View

七月 9, 2009
» [CodeIgniter] lighttpd rewrite rule && apache mod_rewrite

CodeIgniter 要移除網址列存在的 index.php,apache 必須使用 mod_rewrite 寫入 .htaccess 的方式來達成,lighttpd 也是有支援 rewrite,可以參考官方文件:Module: mod_rewrite,設定方法很容易。

$HTTP["host"] == "mimi.twgg.org" {
  server.document-root = "/var/www/html/MLB/"
  url.rewrite = (
        "^/images/.*$" => "$0",
        "^/includes/.*$" => "$0",
        "^/(.*)$" => "index.php/$1"

  )
  accesslog.filename = "/var/log/lighttpd/mimi.twgg.org-access_log"
}


images 跟 include 是您放圖片或者是 css js 的地方,您也可以開一個資料夾把全部靜態檔案放進去,就可以了,這樣不用設定太多的 rule,apache 的 .htaccess 設定方法如下:

RewriteEngine on
RewriteBase /
RewriteCond $1 !^(index\.php|images|includes)
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

兩種作法很類似,都不難,筆記一下,將來會用到。

可以參考 CodeIgniter 官方文件:CodeIgniter URLs

Related View

六月 26, 2009
» [PHP] Gallery 3.0 Beta 1 使用 Kohana MVC Framework

Gallery
Gallery 3.0 Beta 1 出來了,在 roga’s blog,看到這篇訊息,gallery 3 捨去 php smaty template engine,而改用 Kohana MVC Framework 這套 base on CodeIgniter 的 Framework,在 Gallery3:FAQ 裡面有提到為什麼會使用 Kohana 這套 MVC,gallery 團隊找尋了許多 MVC 的架構來幫助開發整個相簿系統,包含了 CakePHPZend FrameworkPradoSymfonyCodeIgniter,最後經過許多人的討論,選用了 Kohana 這套 MVC,原本打算考慮 CI 的,雖然 CI 支援 PHP4 跟 PHP5,以及它非常的小,對於效能方面也非常的好,但是並不支援 PHP5 的 exception,畢且有些少數的 Structure 只有支援 PHP4,所以就不被他們採納了,再來 Zend Framework 因為包含了 1705 個檔案,相當龐大,效能比 CI 少了 200-300%,雖然 ZF 文件相當豐富,不過沒有良好的 example 範例,所以導致 gallery 團隊遇到很多挫折,XDD。

最後選擇了 Kohana,雖然 Kohana 效能輸給 CI,不過這之間的差異極小,Kohana 也有 support PHP5 的 exception,Kohana 文件比 CI 還要少了些,不過對 gallery 團隊已經相當足夠了。底下有一篇各大 Framework 的效能比較:PHP framework comparison benchmarks,還有另一篇:Kohana vs CodeIgniter: Speed and Memory Usage Performance Benchmark

Related View

六月 11, 2009
» [網站] 好站連結 (三)


jQuery

Linux

FreeBSD

javascript

CSS

Wordpress

PHP

C/C++

Ruby

html

CodeIgniter

Related View

六月 9, 2009
» [CodeIgniter] 使用者註冊 auth code 亂數認證碼圖片

我想這已經是網站最基本的技術,防止機器人大量註冊,或者是灌爆留言板,之前寫了兩篇製作認證碼的教學:[PHP]製作類似 google 網頁認證碼[PHP] 好用的留言板 驗證碼 功能,這篇是要寫如何實做把第一篇教學整合到 CodeIgniter 系統裡面,來筆記一下,以後用到就相當方便了,CodeIgniter 在 path 路徑上面有小 bug,查了國外討論區發現了這篇 Path to CSS doesn’t work a second time,不過這並沒有解決我的問題,主機的網址是 http://xxxxx.xxx/path/,所有的 CI 檔案都是放在 path 目錄底下,包含圖片是 http://xxxxx.xxx/path/images/,在 View 裡面基本上只要寫 <img src=’/images/xx.gif’> 這樣就可以顯示圖片了,但是要改成 <img src=’/path/images/xx.gif’> 才能,但是我的 index.php 是放在 /path/ 裡面,以絕對路徑跟相對路徑來想,都是不太合理的,所以後來用 <img src=”<?=base_url();?>public/images/find.png” alt=”" /> 來解決,不過這是暫時的問題,我比較龜毛,喜歡寫短一點的 code。

如何裝上類似 google 的認證碼呢,首先打開 index.php 檔案

/* 算出 index.php 根目錄 */
define('Document_root',dirname(__FILE__));


建立 Controller:vcode.php 檔案,程式碼如下:

<?php
class Vcode extends Controller {

  var $mode;          // 1.文字模式, 2.字母模式, 3.文字字母混合模式, 4.其他文字字母優化模式
  var $v_num;         // 驗證碼個數
  var $img_w;         // 圖像寬度
  var $img_h;         // 圖像高度
  var $int_pixel_num; // 干擾像數個數
  var $int_line_num;  // 干擾線條數量
  var $font_dir;      // 字型文件路徑
  var $border;        // 圖像邊框
  var $borderColor;   // 圖像邊框顏色
 
  function __construct()
  {
    parent::Controller();
        //session_start();
       
  }
  function index()
  {
    $this->getCode('');
  }
  function getCode($time)
  {
    $this->SetImage(4,5,100,50,60,0);
  }
  function SetImage($mode, $v_num, $img_w, $img_h, $int_pixel_num, $int_line_num, $font_dir = '/tool/font', $border=false, $borderColor='0,0,0')
  {
      $this -> mode = $mode;
      $this -> v_num = $v_num;
      $this -> img_w = $img_w;
      $this -> img_h = $img_h;
      $this -> int_pixel_num = $int_pixel_num;
      $this -> int_line_num = $int_line_num;
      $this -> font_dir = Document_root . $font_dir;
      $this -> border = $border;
      $this -> borderColor = $borderColor;
      $this -> GenerateImage();
  }

  function GetChar($mode)
  {
      if($mode == "1"){
          $ychar = "0,1,2,3,4,5,6,7,8,9";
      }else if($mode == "2"){
          $ychar = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
      }else if($mode == "3"){
          $ychar = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
      }else{
          $ychar = "3,4,5,6,7,8,9,a,b,c,d,h,k,p,r,s,t,w,x,y";
      }
      return $ychar;
  }

  function RandColor($rs, $re, $gs, $ge, $bs, $be)
  {
      $r = mt_rand($rs, $re);
      $g = mt_rand($gs, $ge);
      $b = mt_rand($bs, $be);
      return array($r, $g, $b);
  }

  function GenerateImage()
  {
      $fonts = scandir($this -> font_dir);
      $ychar = $this -> GetChar($this -> mode);
      $list = explode(",", $ychar);
      $cmax = count($list) - 1;
      $fmax = count($fonts) - 2;
      $fontrand = mt_rand(2, $fmax);
      $font = $this -> font_dir."/".$fonts[$fontrand];

      // 驗證碼
      $v_code = "";
      for($i = 0; $i < $this-> v_num; $i++){  
          $randnum = mt_rand(0, $cmax);
          $this_char = $list[$randnum];
          $v_code .= $this_char;
      }

      // 扭曲圖形
      $im = imagecreatetruecolor ($this -> img_w + 50, $this -> img_h);
      $color = imagecolorallocate($im, 32, 81, 183);
      $ranum = mt_rand(0, 2);
      if($ranum == 0){
          $color = imagecolorallocate($im, 32, 81, 183);
      }else if($ranum == 1){
          $color = imagecolorallocate($im, 17, 158, 20);
      }else{
          $color = imagecolorallocate($im, 196, 31, 11);
      }
      imagefill($im, 0, 0, imagecolorallocate($im, 255, 255, 255) );
      //imagettftext ($im, 24, mt_rand(-6, 6), 10, $this -> img_h * 0.6, $color, $font, $v_code);
      imagettftext ($im, 24, 0, 10, $this -> img_h * 0.6, $color, $font, $v_code);
      // 干擾線條
      for($i = 0; $i < $this -> int_line_num; $i++){
          $rand_color_line = $color;
          imageline($im, mt_rand(2,intval($this -> img_w/3)), mt_rand(10,$this -> img_h - 10), mt_rand(intval($this -> img_w - ($this -> img_w/3) + 50),$this -> img_w), mt_rand(0,$this -> img_h), $rand_color_line);
      }

      $ranum = mt_rand(0, 1);
      $dis_range = mt_rand(8, 12);
      $distortion_im = imagecreatetruecolor ($this -> img_w * 1.5 ,$this -> img_h);        
      imagefill($distortion_im, 0, 0, imagecolorallocate($distortion_im, 255, 255, 255));
      for ($i = 0; $i < $this -> img_w + 50; $i++) {
          for ($j = 0; $j < $this -> img_h; $j++) {
              $rgb = imagecolorat($im, $i, $j);
              if($ranum == 0){
                  if( (int)($i+40+cos($j/$this -> img_h * 2 * M_PI) * 10) <= imagesx($distortion_im) && (int)($i+20+cos($j/$this -> img_h * 2 * M_PI) * 10) >=0 ) {
                      imagesetpixel ($distortion_im, (int)($i+10+cos($j/$this -> img_h * 2 * M_PI - M_PI * 0.4) * $dis_range), $j, $rgb);
                  }
              }else{
                  if( (int)($i+40+sin($j/$this -> img_h * 2 * M_PI) * 10) <= imagesx($distortion_im) && (int)($i+20+sin($j/$this -> img_h * 2 * M_PI) * 10) >=0 ) {
                      imagesetpixel ($distortion_im, (int)($i+10+sin($j/$this -> img_h * 2 * M_PI - M_PI * 0.4) * $dis_range), $j, $rgb);
                  }
              }
          }
      }

      // 干擾像素
      for($i = 0; $i < $this -> int_pixel_num; $i++){
          $rand_color_pixel = $color;
          imagesetpixel($distortion_im, mt_rand() % $this -> img_w + 20, mt_rand() % $this -> img_h, $rand_color_pixel);
      }

      // 繪製邊框
      if($this -> border){
          $border_color_line = $color;
          imageline($distortion_im, 0, 0, $this -> img_w, 0, $border_color_line); // 上橫
          imageline($distortion_im, 0, 0, 0, $this -> img_h, $border_color_line); // 左豎
          imageline($distortion_im, 0, $this -> img_h-1, $this -> img_w, $this -> img_h-1, $border_color_line); // 下橫
          imageline($distortion_im, $this -> img_w-1, 0, $this -> img_w-1, $this -> img_h, $border_color_line); // 右豎
      }

      imageantialias($distortion_im, true); // 消除鋸齒

      $time = time();
      $this->session->set_userdata('vCode', $v_code."|".$time);
      //$_SESSION['vCode'] = $v_code."|".$time; // 把驗證碼與時間賦與給 $_SESSION[vCode], 時間欄位可以驗證是否超時

      // 生成圖像給瀏覽器
      if (function_exists("imagegif")) {
          header ("Content-type: image/gif");
          imagegif($distortion_im);
      }else if (function_exists("imagepng")) {
          header ("Content-type: image/png");
          imagepng($distortion_im);
      }else if (function_exists("imagejpeg")) {
          header ("Content-type: image/jpeg");
          imagejpeg($distortion_im, "", 80);
      }else if (function_exists("imagewbmp")) {
          header ("Content-type: image/vnd.wap.wbmp");
          imagewbmp($distortion_im);
      }else{
        die("No Image Support On This Server !");
      }

      imagedestroy($im);
      imagedestroy($distortion_im);
  }  
}

顯示認證碼:在您想要的 Controller 裡面加入:

#
# 加入 image
$data['image'] = '<img id="auth_code" src="'.base_url().'vcode">';
#
# 放入 Viewer 裡面
$this->load->view('profile/register',$data);

打開 views/profile/register.php 加入 jQuery javascript,可以自動刷新圖片

$("#auth_code").click(function(){
    genCode();
});
function genCode(){
  vNum = Math.random()
  vNum = Math.round(vNum*10)
    $("#auth_code").attr("src", "<?=base_url()?>vcode/getCode/"+ vNum);
}

在 html 寫入您要顯示的地方

<?=$image?>

大致上完成了,不難,因為稍微改一下 vcode.php 的部份,記得調整 font 的目錄,並且放上要顯示的字型就可以了。

Related View

五月 29, 2009
» [CodeIgniter] Text 補助函數 character_limiter 不適用於中文字

CodeIgniter 裡面的 Text 補助函數,目前只適用於英文字體,不支援 utf-8 或者是簡體字體,bite 數超過2的都會出問題,當然是因為這是國外的 mvc 所以也沒有考慮到這麼週到就是了,也不是沒有辦法解決,之前就用了PHP官方網站所提供的一個函式來正確切割中文字串,就是要利用 ord 判斷 ASCII 編碼範圍,或者是可以使用 mb_substr 函式正確切割,之前寫一篇可以參考看看:[PHP] 如何切割中文標題

底下是原本 CodeIgniter 所提供的 Text 函數

if ( ! function_exists('character_limiter'))
{
    function character_limiter($str, $n = 500, $end_char = '&#8230;')
    {
        if (strlen($str) < $n)
        {
            return $str;
        }
       
        $str = preg_replace("/\s+/", ' ', str_replace(array("\r\n", "\r", "\n"), ' ', $str));
   
        if (strlen($str) <= $n)
        {
            return $str;
        }
   
        $out = "";
        foreach (explode(' ', trim($str)) as $val)
        {
            $out .= $val.' ';
           
            if (strlen($out) >= $n)
            {
                $out = trim($out);
                return (strlen($out) == strlen($str)) ? $out : $out.$end_char;
            }      
        }
    }
}


character_limiter 不能用在中文切割字串,只能用於英文切割,所以自己就要加上切割的函數才可以正確使用喔,利用簡單的 mb_substr 就可以做到了,這算是 CodeIgniter 的 bug 嗎?好像也不是,不過自己有找到函數來使用,那就沒差了,自己可以定義函數在 libraries/ 底下:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class System
{

  function bite_str($string, $start, $len, $byte=3)
  {
    $str     = "";
    $count   = 0;
    $str_len = strlen($string);
    for ($i=0; $i<$str_len; $i++) {
      if (($count+1-$start)>$len) {
          $str  .= "...";
          break;
      } elseif ((ord(substr($string,$i,1)) <= 128) && ($count < $start)) {
          $count++;
      } elseif ((ord(substr($string,$i,1)) > 128) && ($count < $start)) {
          $count = $count+2;
          $i     = $i+$byte-1;
      } elseif ((ord(substr($string,$i,1)) <= 128) && ($count >= $start)) {
          $str  .= substr($string,$i,1);
          $count++;
      } elseif ((ord(substr($string,$i,1)) > 128) && ($count >= $start)) {
          $str  .= substr($string,$i,$byte);
          $count = $count+2;
          $i     = $i+$byte-1;
      }
    }
    return $str;
  }
}
?>

utf-8:$byte=3 | gb2312:$byte=2 | big5:$byte=2

現在都是用 utf-8,所以先把預設值 $byte 設定為 3,就可以正常使用了,使用方法是 $this->system->bite_str($string, $start, $len) 寫這樣就可以成功切割中文字串了。

Related View

五月 23, 2009
» [CodeIgniter] 多國語言網站製作,重複 load 相同 language?

目前正在研究網站的多國語系寫法,研究了 CodeIgniter 的 Language class 用法,可以看線上中文文件:Language 類別,目前遇到一個疑問,在單一 PHP 檔案讀取,不可以同時讀取相同的 Language file 檔案,這樣是完全沒有作用的,以底下的例子來說,我在 application/language 目錄底下放了三個語系資料夾,English、zh-TW、zh-CN 這三個資料夾,裡面分別放路 vbs_lang.php 檔案,為了要區別各國的語系檔案,要分別開資料夾放入,在 CI 文件裡面都寫的很清楚,架構如下

  • application/language/English
  • application/language/zh-TW
  • application/language/zh-CN


在每個 Controller 開始讀取資料,可以利用 建構子(Constructor) 方式 將語系檔案載入,就在這時候,問題如下,我希望可以讀取相同 vbs_lang.php 檔案,但是不同語系目錄,本來以為這樣會把原先載入的檔案蓋掉,可是結果並非是您想要的,例如底下:

#
# 原來先載入繁體中文語系
$this->lang->load('vbs', 'zh-TW');
#
# 後來跑簡體中文語系
$this->lang->load('vbs', 'zh-CN');

當你同時跑這兩個的同時,後面的語系是不會被載入的,這是為甚麼呢?可以從 CodeIgniter 的 Core 裡面找到 libraries/Language.php 檔案,裡面的程式碼寫的很清楚:

<?php
function load($langfile = '', $idiom = '', $return = FALSE)
{
  $langfile = str_replace(EXT, '', str_replace('_lang.', '', $langfile)).'_lang'.EXT;
    if (in_array($langfile, $this->is_loaded, TRUE))
    {
        return;
    }

    if ($idiom == '')
    {
        $CI =& get_instance();
        $deft_lang = $CI->config->item('language');
        $idiom = ($deft_lang == '') ? 'english' : $deft_lang;
    }

    // Determine where the language file is and load it
    if (file_exists(APPPATH.'language/'.$idiom.'/'.$langfile))
    {
        include(APPPATH.'language/'.$idiom.'/'.$langfile);
    }
    else
    {
        if (file_exists(BASEPATH.'language/'.$idiom.'/'.$langfile))
        {
            include(BASEPATH.'language/'.$idiom.'/'.$langfile);
        }
        else
        {
            show_error('Unable to load the requested language file: language/'.$langfile);
        }
    }

    if ( ! isset($lang))
    {
        log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
        return;
    }

    if ($return == TRUE)
    {
        return $lang;
    }

    $this->is_loaded[] = $langfile;
    $this->language = array_merge($this->language, $lang);
  unset($lang);

    log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile);
    return TRUE;
}
?>

CI 會先比對您要載入的語系資料,那就是 $langfile 這個變數資料,當在 $this->is_loaded 這陣列裡面存在了 vbs 這個語系,系統就會 return 空值給您,並不會接下去跑程式,這麼做是為了避免重複的變數名稱 merge 到 array 裡面,當然這也可以解,解法就是比對陣列裡面的 key,如果找到相同的就把陣列 key 值 unset 刪除,不過這樣降低系統效能,結論是單一語系檔案就載入一次就好,有一點要注意,請不要在 application/config/autoload.php 裡面把 language 載入進來,因為這樣系統就預設載入了您要的國家語系,當您要改變的時候,就沒辦法了載入相同語系,這算是 bug 吧。^^

Related View

五月 17, 2009
» [PHP] CodeIgniter 繁體中文翻譯計畫

CideIgniter 官方中文網站

本人目前正在推廣 CodeIgniter 官方中文網站,這套 MVC 在我使用起來還蠻適合新手學習的,也非常容易上手的一套 MVC Web development 架構 ,希望推廣給台灣繁體 php web 開發人員,即使您之前沒有用過 MVC 架構,只要懂的一點 PHP 語法,基本 function 會使用,基本上就可以直接來使用 CodeIgniter,在這裡徵求對 php 或者 CodeIgniter 翻譯繁體中文有興趣的網友或者是使用者們,可以加入繁體中文的翻譯計畫,我在 github 開了CodeIgniter translation 的 repository,網址是:

http://github.com/appleboy/PHP-CodeIgniter-Framework-Taiwan/tree/master

目前翻譯文件不多,只有三個人,徵求更多使用者可以加入翻譯計畫,希望可以造福台灣的使用者,也當然是推廣這套 MVC,如果想加入可以主動跟我聯絡,另外 jiz 使用者也針對程式中文化部份開了一個 repository,在底下網址

http://github.com/jiz/CodeIgniter/tree/master

目前可以接受三種方式:

  • 如果你有 github 帳號,請把帳號給我,我會加入共同作者,這樣就可以直接 commit merge checkout pull push 進去 repository
  • 把 patch 檔案寄給我,diff -u 原檔名 翻譯後檔名  > 檔名.patch
  • 或者是將片段翻譯,寄給我,並告知識翻譯哪個部份這樣就可以了

我的聯絡方式:http://blog.wu-boy.com/contact-subscribe/
或者是上 irc : irc.freenode.net codeigniter.tw 頻道

底下是整理的 git 教學網站:

http://github.com/guides/home
providing your ssh key
http://github.com/guides/providing-your-ssh-key
Git Guides: Pull Requests
Git 原始碼管理
Git 版本控制系統(2) 開 branch 分支和操作遠端 repo
Git 基礎設定 (帳號的環境參數設定)

Related View

四月 30, 2009
» [CodeIgniter] Web Framework 非官方繁體中文討論區成立

CodeIgniter 是我最近正在研究的一套 Web MVC Framework,為什麼會選擇這一套來推廣呢,目前在網路上大家所推的 MVC Framework,無非是 Zend FrameworkCakePHPKohanaYii PHP Framework…等,這些都算是國內常用的 MVC 架構,那效能方面可以參考:PHP framework comparison benchmarks,這篇寫到利用 httperf 測試 Web Performance,跑了很多效能方面的數據出來,這些數據也看看就好,大家還是都會選擇自己上手的 Framework 來使用,那今天我就是來推廣 CodeIgniter 這套 Web Framwork。

CodeIgniter 在效能數據方面表現的很不錯,重點在於它非常輕便,沒有載入過多的 module 跟 Library,線上文件也寫的非常清楚容易,在台灣也成立了非官方網站:CodeIgniter 繁體中文!,最近也把非官方討論區架設完畢,希望大家能夠共同推廣 CodeIgniter,目前只有我以及另一位 ptt 網友 awelkije 共同推廣以及維護網站討論區,當然很希望更多朋友可以一起來翻譯教學文件,或者是寫教學文件放到討論區上面,造福台灣使用 CodeIgniter 的朋友以及給入門新手觀看學習,如果需要加入翻譯行列,或者是維護官方網站,都可以找我,自己也是剛學 CodeIgniter 不到兩個禮拜,大家一起推廣 CodeIgniter 吧。

聯絡我的方式:http://blog.wu-boy.com/contact-subscribe/

Related View

四月 20, 2009
» [PHP] Web Framework : CodeIgniter MySQL Database 使用教學

繼上一篇 [PHP] 好用 Web Framework : CodeIgniter 安裝教學 之後,這次來紀錄一下 Database Class 的用法,我想官方網站都已經寫的很詳細了,就大概快速講一下我的一些用法跟心得,其實最主要講的是內建的 Active Record Class,它可以快速撰寫 SQL 語法,不必打 where 或者是 From 這些字眼,insert update select 都可以利用 Active Record Class 很簡單的撰寫出來喔,它也幫忙簡單的檢查 escape SQL Injection,舉的簡單例子大概就知道了:

假設底下這個簡單的 join 一個表格的 select 語法

$query = $this->db->query("SELECT a.news_id, a.news_name, a.add_time FROM project_news a
 left join project_news_categories b on a.categories_id = b.categories_id
where news_id = '"
.$id."' order by news_top DESC, a.add_time DESC
"
);

利用 Active Record Class 可以改寫成:

$this->db->select('a.news_id, a.news_name, a.add_time');
$this->db->from('project_news a');
$this->db->join('project_news_categories b', 'a.categories_id = b.categories_id', 'left');
$this->db->order_by("news_top DESC, a.add_time DESC");
$this->db->where('news_id', $id);


是不是覺得在閱讀方面很容易瞭解呢,那之後要改 sql 語法,也可以快速找到要改的地方,交接給其他程式組員,在學習或者是除錯方面都相當容易的喔。

首先介紹設定 database 的 config 檔案 Database Configuration

$active_group = "default";
$active_record = TRUE;

$db['default']['hostname'] = "localhost";
$db['default']['username'