星期一, 8月 22, 2011

PHP轉影音檔

[轉]使用PHP進行影片轉檔及擷取縮圖

要在 Linux 主機上使用 PHP 進行影片轉檔,須安裝 LAME、ffmpeg、Ruby、FLVTool2。

  1. 安裝 LAME
    LAME 是用來將聲音壓成 MP3 格式,並加入 --enable-shared 以供 ffmpeg 使用
    網址:http://lame.sourceforge.net/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -zxvf lame-3.98.4.tar.gz
    [root@localhost ~]# cd lame-3.98.4
    [root@localhost ~]# ./configure --enable-shared -prefix=/usr
    [root@localhost ~]# make
    [root@localhost ~]# make install
  2. ffmpeg Install With Libx264
    1. Download libx264
      Get the libx264 package from here: http://www.videolan.org/developers/x264.html
    2. Install libx264
      cd /path/to/x264-dir
      ./configure --enable-shared
      make
      make install
      ldconfig
      如果遇到yasm not found,就用無敵的yum install yasm
      如果遇到yum找不到yasm,就先裝epel
      //32bit 
      sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
      
      //CentOS 5 64bit
      sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
      
      //CentOS 6
      rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
  3. 安裝 ffmpeg
    ffmpeg 影片轉檔系統,其 libavcodec 涵蓋大部分影片格式,不過仍有轉換 FLV 上的問題,須另外安裝 FLVTools 來修正。
    網址:http://www.ffmpeg.org/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -zxvf ffmpeg-0.5.1.tar.gz
    [root@localhost ~]# cd ffmpeg-0.5.1
    [root@localhost ~]# ./configure --enable-gpl --enable-libmp3lame --enable-shared --enable-libx264 --prefix=/usr

    [root@localhost ~]# make clean && make
    [root@localhost ~]# make install
  4. 安裝 Ruby
    FLVTool2 可以修正 ffmpeg 不正確儲存 FLV metadata 的問題,不過它是用 Ruby 寫的,須先安裝 Ruby。
    網址:http://www.ruby-lang.org/en/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -zxvf ruby-1.9.1-p376.tar.gz
    [root@localhost ~]# cd ruby-1.9.1-p376
    [root@localhost ~]# ./configure
    [root@localhost ~]# make
    [root@localhost ~]# make install
  5. 安裝 FLVTool2
    FLVTool2 是一個用來編輯FLV檔的套件,透過它來儲存FLV檔,確保 FLV 檔裡有正確的 metadata。
    網址:http://rubyforge.org/projects/flvtool2/

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -xvf flvtool2-1.0.6.tar
    [root@localhost ~]# cd flvtool2-1.0.6
    [root@localhost ~]# ruby setup.rb config
    [root@localhost ~]# ruby setup.rb setup
    [root@localhost ~]# ruby setup.rb install
  6. 安裝 ffmpeg-php
    為了讓 PHP 取得影片的資料,要安裝 ffmpeg-php 插件。
    網址:http://ffmpeg-php.sourceforge.net/
    下載:http://sourceforge.net/projects/ffmpeg-php/files/ffmpeg-php/0.6.0/ffmpeg-php-0.6.0.tbz2/download

    下載完成後,輸入下列命令:
    [root@localhost ~]# tar -xvf ffmpeg-php-0.6.0.tbz2
    [root@localhost ~]# cd ffmpeg-php-0.6.0
    [root@localhost ~]# phpize
    [root@localhost ~]# ./configure && make
    [root@localhost ~]# make install

    在configure && make階段遇到CODEC_TYPE_VIDEO undeclared問題
    新增yum的Repository後
    重裝yum install ffmpeg ffmpeg-devel ffmpeg-libpostproc 解決一些問
    Install FFmpeg and ffmpeg-php on CentOS Easily
    之後又遇到‘PIX_FMT_RGBA32′undeclared 看下篇解決
    ffmpeg-php error PIX_FMT_RGBA32

    如果 Apache 是使用 XAMPP 請參考這篇:
    [Linux] 在 XAMPP 上安裝 PHP extension (以 ffmpeg-php 為例)

    make後 可以看到產生ffmpeg.so的資料
    再搬到/usr/lib64/php/modules/ffmpeg.so
    即可設定 PHP 載入這個plugin。
  7. 設定 php.ini
    1. #vi /etc/php.ini
      加入以下內容:
      [ffmpeg]
      extension=ffmpeg.so
    2. 重開apache
      #service httpd restart

    最後重啟 Apache
  8. 開始轉檔
    以下是一個簡單的範例:
    PHP程式碼
    //ffmpeg 的執行路徑
    $ffmpegPath = "/usr/bin/ffmpeg";
    //來源影片路徑
    $srcFile = '/var/www/html/ffmpeg/upload/test_in.wmv';
    //輸出影片路徑
    $outFile = '/var/www/html/ffmpeg/upload/test_out.flv';
    //輸出縮圖路徑
    $outImg = '/var/www/html/ffmpeg/upload/test.jpg';

    //取得影片資訊
    $ffmpegObj = new ffmpeg_movie($srcFile);
    //取得音頻比特率
    $srcAB = intval($ffmpegObj->getAudioBitRate()/1000);

    //將影片轉換為FLV檔
    exec("$ffmpegPath -i $srcFile -f flv -s 436x324 -acodec libmp3lame -ar 22050 -ac 2 -ab $srcAB -y $outFile");

    //從影片產生縮圖
    exec("$ffmpegPath -itsoffset -1 -i $srcFile -vcodec mjpeg -vframes 1 -an -f rawvideo -s 436x324 $outImg");
如果沒有錯誤,又沒有轉出的檔案 檢查一下資料夾權限是否限制寫入

Reference

星期五, 8月 19, 2011

書: Clean Code

  1. What is clean code
    • "elegant and efficient" Bjarne Stroustrup, C++之父
      寫的真好...
    • "simple and direct" Grady Booch, OO大師
      幾個字就說出精要,大師就是大師

    為什麼會有bad code
    程式不斷修改,保持clean,混亂的程式碼才不會越滾越大
    導致沒辦法維護,記住童子軍的規則
    The Boy Scout Rule
    Leave the campground cleaner than you found it.

    5S
    • Sort 命名易辯識
    • Systematize 歸類(知道到哪找)
    • Cleaning 潔簡
    • Standardization 一致的coding style
    • Self-discipline 遵守規定
    總而言之就是Keep it clean
    Each function, each class, each module
    exposes a single-minded attitude

  2. Meaningful Names
    • Use Intention-Revealing Names
      透過命名就能知其意圖,如果還需要註解來解釋它,就代表不夠清楚
    • Use Pronounceable Names
      使用可發音的Name幫助溝通
    • Use Searchable Names
      方便search及取代
    • Use Problem Domain Names
      沒有適合使用的term,就使用domain的term,讓接手維護的人至少還可以問domain專家,這代表什麼
  3. Functions
    • Do One Thing(Small)
      只做命名的事細節,包給其他function
    • Function Arguments The Ideal number of arguments is 0 有參數,增加理解困難

  4. Comments
    Don’t comment bad code
    rewrite it 註解沒太多幫助,不如重寫重新整理

程式持續修改演化
不可能一次把程式寫好
First, Make It Work
Then Make It Right


References

星期五, 8月 12, 2011

git push 二三事

  • push origin
    git push可夾很多參數
    還看不太懂,好好研究一下吧
    • git push
          即git push <remote>, 如果<remote>沒設定,便push到origin
    • git push origin
         即git push origin :.
         The default behavior of this command when no is given can be configured by setting the push option of the remote.
         For example, to default to pushing only the current branch to origin use git config remote.origin.push HEAD. Any valid (like the ones in the examples below) can be configured as the default for git push origin.
    • git push origin :
           自動推到相同名稱的分支     
    • git push origin master
          將目前的master推到origin的master
      (most likely, it would find refs/heads/master), and update the same ref (e.g. refs/heads/master) in origin repository with it.      
    • git push origin HEAD
      將目前所在的branch推回origin下,同名稱的branch(
      未建立,會自動建立)
    • git push origin master:satellite/master dev:satellite/dev
           Use the source ref that matches master (e.g. refs/heads/master) to update the ref that matches satellite/master (most probably
          refs/remotes/satellite/master) in the origin repository, then do the same for dev and satellite/dev.   
    • git push origin HEAD:master
          
      HEAD為目前所在branch,也可以直接下名稱;而後面master是push到origin下的branch
    • git push origin master:refs/heads/experimental
             Create the branch experimental in the origin repository by copying the current master branch. This form is only needed to create a new branch or
                    tag in the remote repository when the local name and the remote name are different; otherwise, the ref name on its own will work.      
    • git push origin :experimental
                    Find a ref that matches experimental in the origin repository (e.g. refs/heads/experimental), and delete it.        
    • git push origin +dev:master
                    Update the origin repository’s master branch with the dev branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling
                    in the origin repository. Consider the following situation, where a fast-forward is not possible:
  • push remote
    • 送給某個repo
      $ git push ssh://yourserver.com/~you/proj.git master

git運用流程

目前做法
一台共用的測試機 + n台開發機

雖然每個人可各自pull其他人的東西
不過共同開發還是用1台做merge,其他人pull比較簡單點

  • push時機
    每次commit完
    便push到測試機,而push是push到測試機上自己的branch,這樣方便分辯誰push的
    再到測試機做merge,其他人做pull
  • pull時機
    每次commit完,就做pull

星期三, 8月 10, 2011

MySQL Proxy & Amoeba

做MySQL的效能多會用load balance
目前MySQL的load balance多採用官方的MySQL Proxy及大陸的Amoeba
以下整理網路上收集到的資訊,挺多簡體翻的 要習慣一下
  • MySQL Proxy
    安裝:mysql proxy讀寫分流(一)-mysql proxy的安裝方式
    說明:MySQL Proxy位於 client及MySQL server(s)中間
    MySQL Proxy可以monitor, analyze or transform their communication. 可達到:
    • load balancing
    • failover
    • query analysis
    • query filtering and modification
    • ... and many more. 
  • Amoeba
    安裝:Amoeba For MySQL 實現資料庫負載平衡(讀寫分離)
    說明:Amoeba 也位於Client、Database Server(s)之間
     Amoeba 具有負載均衡、高可用性、 sql過濾
    可承受達到讀寫分離、Query Route(解析sql query語句,並且根據條件與預先設定的規則,請求到指定的目標數據庫。可並發請求多台數據庫合併結果)
    對客戶端透明。主要降低數據切分帶來的複雜多數據庫結構、數據切分規則給應用
    帶來的影響。
  • 比較 in action

    • Load Blance及讀寫分離
      Master:Server1(可讀寫)
      Slaves:Server2, Server3, Server4(3個平等的數據庫。只讀/負載均衡)

      • MySQL Proxy
        #設定db server變數
        Server1=10.1.1.1  #master
        Server2=10.2.1.1  #slave1
        Server3=10.3.1.1  #slave2
        Server4=10.4.1.1  #slave3
        ROOT_DIR=/usr/local

        #指定讀寫server
        LUA_PATH="$ROOT_DIR/mysql-proxy/share/mysql-proxy/?.lua" $ROOT_DIR/mysql-proxy/sbin/mysql-proxy \
        --daemon \
        --proxy-backend-addresses=$Server1:3306 \
        --proxy-read-only-backend-addresses=$Server2:3306 \
        --proxy-read-only-backend-addresses=$Server3:3306 \
        --proxy-read-only-backend-addresses=$Server4:3306 \
        --proxy-lua-script=$ROOT_DIR/mysql-proxy/share/mysql-proxy/rw-splitting.lua

        這個例子中10.1.1.1為可寫
        限制10.2.1.1,10.3.1.1,10.4.1.1只能讀
      • Amoeba
        amoeba提供讀寫分離pool相關配置。並且提供負載均衡配置。
        可配置server2、server3、server4形成一個虛擬的 virtualSlave,該配置提供負載均衡、failOver、故障恢復功能
        <dbServer name=“virtualSlave” virtual=“true”>
        <poolConfig>
        <className>com.meidusa.amoeba.server.MultipleServerPool</className>
        <!-- 負載均衡參數 1=ROUNDROBIN , 2=WEIGHTBASED -->
        <property name="loadbalance">1</property>

        <!-- 參與該pool負載均衡的poolName列表以逗號分割 -->
        <property name="poolNames"> Server2,Server3,Server4</property>
        </poolConfig>
        </dbServer>

        指派讀寫機
        <queryRouter>
        <className>com.meidusa.amoeba.mysql.parser.MysqlQueryRouter</className>
        <property name="LRUMapSize">1500</property>
        <property name="defaultPool">server1</property>

        <property name="writePool">server1</property>
        <property name="readPool">virtualSlave</property>

        <property name="needParse">true</property>
        </queryRouter>
        那麼遇到update/insert/delete將 query語句發送到 wirtePool,將 select發送到 readPool機器中執行。
    • 資料分割
      • MySQL Proxy
      • Amoeba
        SELECT * from user_event where user_id='test' and gmt_create between Sysdate() -1 and Sysdate()

        如果根據gmt_create 時間進行數據切分,比如 6個月進行切分一次
        amoeba提供利用類似sql表達式進行數據切分:
        • 規則1(對應服務器1):
          GMT_CREATE > to_date('2008-01-01','yyyy-mm-dd')
          AND GMT_CREATE < to_date('2008-05-31','yyyy-mm-dd')
        • 規則2(對應服務器2)
          GMT_CREATE > to_date('2008-06-01','yyyy-mm-dd')
          AND GMT_CREATE < to_date('2008-12-31','yyyy-mm-dd')
        上面的sql的條件 gmt_create 與規則裡面的的gmt_create 進行交集判斷,如果存在交集則表示符合規則。 則會將sql轉移到 規則1 的相應的服務器上面執行。
        利用amoeba寫出這種類似規則很容易,但是要想做到數據切分以後可線性擴容,那麼這樣的規則需要自己根據業務實際情況進行設置。
        amoeba可同時將sql 並發分發到多台服務器、然後將結果合併再反饋給客戶端,而且amoeba內部現成採用無阻塞模式,工作線程是不會等待的,並發請求多台 database server情況下,客戶端等待的時間基本上面是性能最差的那台 database server+amoeba內部解析協議的時間

    注意事項

    沒實作過,也不知要注意什麼 還是看別人寫的吧
    • MySQL Proxy
      • 同步延遲問題
        寫入後,其他slaves的同步問題,MySQL Proxy如何解決同步延遲問題
      • 資料是亂碼
        有看到2種解決方法,還沒試過
        • 設定mysql server
          set names "utf8"也沒有效果。
          [mysqld]
          skip-character-set-client-handshake
          init-connect='SET NAMES utf8'
          default-character-set=utf8
        • 修改/etc/my.cnf 設定檔
          加入底下設定,即可解決亂碼問題(當然您要依據您的環境做修改)
          default-character-set = utf8
          skip-character-set-client-handshake
          character-set-server = utf8
          collation-server = utf8_general_ci
          init-connect = SET NAMES utf8
    • Amoeba
        MySQL使用Amoeba作为Proxy时的注意事项 以下是截錄的
      • Amoeba不支持事务
        p.s. 還不知道"事務"是什麼 不過官網似乎提到有支援了
      • Amoeba不支持跨库join和排序
        跨庫的join和排序非常消耗資源,會導致性能嚴重下降,Amoeba沒有進行支持,只能做到分數據庫實例。
      • Amoeba不支持大數據量的查詢。
        不適合返回大量(超過10萬)數據的查詢,大數據量的查詢非常消耗內存,Amoeba在進行大數據量查詢時性能會非常差。當然,實際業務中需要進行大數據量查詢的情況會非常少或者根本沒必要實現這種情況。這裡所謂的大數據量查詢指的是一次查詢結果超過十萬行。
      • Amoeba需要更嚴格的SQL語句規範
        From 關鍵字後面如果不是子查詢,一律不能帶括號」()」;
        如果的表中字段名與關鍵字或者函數名一樣需要帶上字符` (比如:mytable.`order`)
      • 與直接操作mysql數據庫相比,amoeba性能的損失大概在怎麼一個範圍?
        amoeba是屬於代理層,起碼要消耗2次網絡IO,加上amoeba自身的計算時候的消耗,
        如果數據庫的性能非常高,或者sql的執行並不消耗數據庫的磁盤IO,那麼這時候完全不能體現amoeba的好處,反而會降低整體的性能。具體數據目前沒有算過。

    結論

    • 學習曲線
      由於MySQL Proxy需透過Lua Script
      看起來不難,不過要初學者在linux去碰這東西,還真是有難度

      而Amoeba設定就簡單的多
      只需要進行相關的XML配置就可以滿足需求
      用SQLJEP語法寫規則
      雖然lua也不難,但比起設定檔的學習曲線還是有差
    • 效能方面
      比官方的mysql proxy性能大致低10%~20%左右
      在一次請求數據量比較大的情況下比如好幾千條數據,性能有所下降,這個原因是由於解析了mysql與客戶端之間交互的所有數據包,而mysql proxy在沒有使用lua特定腳本的時候是不會解析mysql數據包
      並發能力來說比mysql proxy會更強勁,還有穩定性方面都比mysql proxy強。從使用的連接數來看,在相同的客戶端並發連接情況下,與mysql數據庫的連接數將比mysql proxy少一半。
      在0.27版本以後,amoeba的性能逐漸超過了MySQL Proxy
    • 文件支援
      維護amoebad的人似乎不多
      在官網查相關文件都有些不清楚
      問題回覆也沒有歸類,有問題不好解決
    • 穩定性
      覺得Amoeba太新了
      官網上也有不少人回應bug的事
      穩定性也是需要考量的地方
    References

星期五, 8月 05, 2011

php比較相似字串

  1. 比對相似的字串 similar_text($str1, $str2)
    //測試性名陣列
    $names = array('Robert Smith','Bobby Smythe','Roberto Thithe', 'Robin Smith');

    //檢查相似程度
    foreach($names as $name){
    similar_text($name, 'Roberto Smythi', $percent);
    echo "{$name} = {$percent}%\n";
    }
    //result
    //Robert Smith = 88%
    //Bobby Smythe = 64%
    //Roberto Thithe = 74.074074074074%
    //Robin Smith' = 66.66666666667%
  2. levenshtei()


See Also

  • soundex() - Calculate the soundex key of a string

星期一, 8月 01, 2011

$_SERVER

url為www.example.com/controllerA/actionB/argC/C
利用$_SERVER的各參數,可得以下

  • Server相關
    參數說明value
    SERVER_NAMEServer位置www.example.com
    SERVER_ADDRserver IP位置192.168.11.1
    SERVER_PORTPort80
    DOCUMENT_ROOTweb的根目錄/var/www/html(看/etc/httpd/conf/httpd.conf的設定)
    SCRIPT_FILENAMEscript位置
    SCRIPT_NAMEscript名稱
  • Client相關
    參數說明value
    REMOTE_ADDRclient的ip192.168.11.1
  • request相關
    參數說明value
    REQUEST_URIrequest的uri/controllerA/actionB/argC/C






星期三, 7月 27, 2011

git

  • 安裝git
    • install git
      $ yum install git-core
      如果發生No package git-core available.
      $rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
    • 環境設定
      git config、git script自動完成
  • git操作
    1. 建立Repository
      兩種方法
      • 以該資料夾當成新的Repository
        $ cd (project-directory)
        $ git init
        $ (add some files)
        $ git add .
        $ git commit -m 'Initial commit'
      • 從遠端複製一份Repository
        git clone http://xxxx
    2. 查看版本
      git log
    3. 暫存
      git stash
    4. 重置及還原
      reset, revert
FAQ

  • commit原則 (from ihover's slide)
    • 適當的粒度/相關性/獨立性
      • 以一個小功能、小改進或一個bug fixed為單位
      • 無相關的修改不在同一個commit
      • 語法錯誤的半成品程式不能commit
  • git push error
    git v1.7後 就不允許覆蓋origin的master
    如果當初始化資料夾下git --bare init時
    沒加上參數--bare 就會發生這個錯誤
    refusing to update checked out branch: refs/heads/master
    如果硬要幹的話....
    git config --bool core.bare true
    這樣就可以push了

    另外較好的解決方法是在local開branch開發,再push到origin的branch後,做merge動作 在要push的branch下 $git push origin HEAD:branch2 #branchX未建會自動建 回到origin,用git branch會看到branch2 $git checkout master #假設是master要merge branch2 $git merge branch2

References

星期五, 7月 22, 2011

提升查詢效率與避免LOCK發生

Sql查詢時 會因之前的操作而做lock
因此會有些delay的等待
加了WITH (nolock)就不會理會transaction lock
而直接回覆查詢資料,因而提升回覆速度

  • MSSQL
    SELECT * FROM TABLE WITH (nolock)
    但會有dirty read,所以較不重要資料才可以這麼用
先在DB打開Snapshot功能,再用command or connection string 控制isolation level。
PHP的mssql server driver 不支援 connection string控制isolation level,因此只能用sql command 或者在DB打開RCSI (READ COMMITTED SNAPSHOT isolation),全部查詢就會在此isolation level
  • MySQL
    1. 利set session
      SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
      SELECT * FROM TABLE_NAME ;
      SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
    2. inside a transaction
      SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
      GO

    3. 設定global variable
      SELECT @@global.tx_isolation; (global isolation level)
      SELECT @@tx_isolation; (session isolation level)

MySQL uses table-level locking for ISAM, MyISAM, and MEMORY (HEAP) tables, page-level locking for BDB tables, and row-level locking for InnoDB tables.

http://dev.mysql.com/doc/refman/4.1/en/internal-locking.html

References

星期四, 7月 21, 2011

vim 環境設定

  • 環境
    • 將vi以vim啟動
      就是下vi等於下vim
      # vi ~/.bashrc
      ---------/root/.bashrc----------
      alias vi='vim'  #加入這一行
    • 支援編碼
      vim /etc/vim/vimrc
      
      -----------/etc/vim/vimrc-------------------
      
      set fileencoding=utf-8,big5,gb18030  //支援中文utf-8,繁體big5及簡體gb
    • Turn on or off color syntax highlighting in vi or vim
      • 從環境變數設定
        # echo 'syntax on' >> /root/.vimrc
      • 使用中設定
        //command mode
        
        :syntax on //or off
    • 取消自動產生的*.ext~, .*.swp檔
      這是vi自動產生的備份檔 在/etc/vimrc下加入
      set nobackup #不產生*.ext~
      set noswapfile #不產生.*swp
      set nowritebackup #不管不產生哪一項,這個都要給
      
    • 關掉吵人的beep聲
      set vb
      vb = visual bell
    • 設定tab長度及自動縮排長度
      為了follow PSR規範... 不用tab,要用4個whitespace
      vi ~/.vimrc
      set tabstop=4
      set shiftwidth=4
  • 縮排 indent

    1. 取得indent檔
      先取得相關的indent檔,例如html縮排,會得到html.vim
      其他相關縮排檔
      • javascript
      • jQuery
      • php
      • php(html enhanced)
        由於php裡,常會夾html,而在原php的縮排對html的支援不是很好,所以有人做了加強版
        p.s. 作者預設縮3個空格,如果要改成縮8個,在第27行,set sw=3 //改成8即可
    2. 放到~/.vim/indent 
      如果沒有就自行建資料夾
    3. 啟動縮排
      在~/.vimrc中(如果沒有就自行建),加入 filetype indent on
  • 編輯
    • 取代斷行符號
      用vi編輯時,有時會遇到^M的斷行符號
      雖然不影響,不過還挺礙眼的
      幾百行下來還挺難改的,又打不出取代的符號,總算在找到取代的方法了
      :%s/^V^M//g

      ^v為CONTROL-V,而^m是CONTROL-M當打完這兩個時,就會出現
      :%s/^M//g
  • 縮排
    1. Html, JavaScript
      JavaScript Indent : Javascript indenter (HTML indent is included) , Preston Koprivica  
      直接下載 
      安裝:
      # tar xvf web-indent.tar  //解壓
      # cd web-indent/indent/     //進到html.vim及javascript.vim的資料夾
      # cp *.vim ~/.vim/indent/  //將*.vim全放到runtime目錄下的vim環境

參考網路的範例,調成自己用的
" encoding
 set encoding=utf-8
 set fileencodings=utf-8,cp950,latin1

"syntax
 syntax on " 語法上色顯示
 set nocompatible " VIM 不使用和 VI 相容的模式
 au BufReadPost *.volt set syntax=php
 au BufReadPost *.zep set syntax=php

"indent
 set shiftwidth=4 " 設定縮排寬度 = 4
 set tabstop=4 " tab 的字元數
 set softtabstop=4
 set expandtab

" setting
 set ruler " 顯示右下角設定值
 set backspace=2 " 在 insert 也可用 backspace
 set ic " 設定搜尋忽略大小寫
 set ru " 第幾行第幾個字
 set hlsearch " 設定高亮度顯示搜尋結果
 set incsearch " 在關鍵字還沒完全輸入完畢前就顯示結果
 set smartindent " 設定 smartindent
 set confirm " 操作過程有衝突時,以明確的文字來詢問
 set history=100 " 保留 100 個使用過的指令
 set cursorline " 顯示目前的游標位置
 set laststatus=2
 set statusline=%4*%<\%m%<[%f\%r%h%w][%{&ff},%{&fileencoding},%Y]%=\[Position=%l,%v,%p%%]
 set nu
 set cursorline

 " Color configuration
 set bg="solarized dark"
 color evening " Same as :colorscheme evening
 hi LineNr cterm=bold ctermfg=DarkGrey ctermbg=NONE
 hi CursorLineNr cterm=bold ctermfg=Green ctermbg=NONE

效果見下圖



References

星期一, 7月 18, 2011

window, document, dom的寬與高

  • document
    整份文件的高 $(document).height()
  • window
    視窗(browser)的高 $(window).height()
  • dom物件
    絕對高 $(xxx).position().top; //不是method哦


$(window).scroll(function(){
    console.log('document:%d, window:%d scroll:%d',
        $(document).height(),  //整份文件的高
        $(window).height(),      //視窗(browser)的高
        $(window).scrollTop()); //目前捲的位置
});

星期日, 7月 17, 2011

MySQL - select最佳化分析

利用EXPLAIN幫助索引和查出最佳化的查詢語法
EXPLAIN SELECT * FROM website WHERE url='http://homeserver.com.tw';

欄位資訊,完整版看官網EXPLAIN的欄位說明
Column Meaning
id The SELECT identifier
select_type The SELECT type
沒有union為simple, 其他看官網
table The table for the output row
type The join type
最優至最差的類型為system,const, eq_reg, ref, range, ..., ALL 
possible_keys The possible indexes to choose
key The index actually chosen
如果為NULL,則是沒有使用索引。
key_len The length of the chosen key
長度越短 準確性越高。
ref The columns compared to the index
顯示那一列的索引被使用。一般是一個常數(const)。
rows Estimate of rows to be examined
Extra Additional information
MySQL用來解析額外的查詢訊息。如果此欄位的值為:Using temporary和Using filesort,表示MySQL無法使用索引。

  • Extra
    Extra為MySQL用來解析額外的查詢訊息,其中欄位值所代表的意義如下:
    • Distinct:當MySQL找到相關連的資料時,就不再搜尋。
    • Not exists:MySQL優化 LEFT JOIN,一旦找到符合的LEFT JOIN資料後,就不再搜尋。
    • Range checked for each Record(index map:#):無法找到理想的索引。此為最慢的使用索引。
    • Using filesort:當出現這個值時,表示此SELECT語法需要優化。因為MySQL必須進行額外的步驟來進行查詢。
    • Using index:返回的資料是從索引中資料,而不是從實際的資料中返回,當返回的資料都出現在索引中的資料時就會發生此情況。
    • Using temporary:同Using filesort,表示此SELECT語法需要進行優化。此為MySQL必須建立一個暫時的資料表(Table)來儲存結果,此情況會發生在針對不同的資料進行ORDER BY,而不是GROUP BY。
    • Using where:使用WHERE語法中的欄位來返回結果。
    • System:system資料表,此為const連接類型的特殊情況。
    • Const:資料表中的一個記錄的最大值能夠符合這個查詢。因為只有一行,這個值就是常數,因為MySQL會先讀這個值然後把它當做常數。
    • eq_ref:MySQL在連接查詢時,會從最前面的資料表,對每一個記錄的聯合,從資料表中讀取一個記錄,在查詢時會使用索引為主鍵或唯一鍵的全部。
    • ref:只有在查詢使用了非唯一鍵或主鍵時才會發生。
    • range:使用索引返回一個範圍的結果。例如:使用大於>或小於<查詢時發生。 index:此為針對索引中的資料進行查詢。 ALL:針對每一筆記錄進行完全掃瞄,此為最壞的情況,應該儘量避免。

Reference

星期六, 7月 16, 2011

PHP 效能 - 快取篇

  1. APC
  2. Memcache

何時用APC (獨立在一台server)
  • Application Settings
  • Configuration
  • Data is the same for each user
  • request都由同一台server responses(i.e sticky session)
  • file upload process & sessions (if using sticky session)
何時用Memcache (分散在不同的servers)
  • 當request不保證指向同server時
  • Data is specific or targeted to a user
  • User sessions

References

Apach效能

  1. 確保足夠的RAM
    在無法購買更快的硬體情形下,硬體方面已經沒有方法讓伺服器更快,因此重點要確定有足夠的RAM
    • 利用top或ps檢視apache的process佔用的記憶體
    • 或限制最大的process數,利用MaxClients指令限制
  2. 以ab評校Apache的效能
    解答:apache/bin/ab -n 1000 -c 10 htp://www.example.com/test.html
    ab: 請求url的資源
    -n: request 1000次
    -c: 一次送出10個請求(同步的意思)
    適合用於輕微組態改變,並測試改變前後伺服器的效能
    note:,不要在欲測試的server試ab,因為ab會耗資源,所以效能會低於別台機器發出的ab,且同一台不會有網路delay
  3. 調校保持連線的設定
    解答:啟用KeepAlive指令,並將相關指令設定成合理值
    KeepAlive On
    MaxKeepAliveRequests 0
    KeepAliveTimeout 15

    KeepAlive可讓單一連線上多個請求,減少建立socket連線所需的時間
    MaxKeepAliveRequest即每個連線上允許多少請求
    KeepAliveTimeout 超過閒置時間即斷線,大多數15即可順利運作


Reference
Apache Cookbook, O'Reilly

星期六, 7月 02, 2011

vm指向host為gateway

最近把vm用在自己的nb上跑
利用bridge mode向dhcp取ip

有次到了沒網路的地方 才發覺沒辦法連到vm
才想說用自己的nb當gateway來連,這樣不用怕沒網路,也不用改ip了

想法是把vm的gateway設為自己的nb
不過試了好久,一直沒成功
請教仰哥後,果然成功了
再次感謝仰哥


  1. 選擇Nat模式
    在vm的Network Mode選擇Nat模式
  2. 抄下nat網卡的ip
    vm安裝好後,會建立2張網卡,抄下ip(右鍵/內容... 應該不用教吧)
  3. 設定gateway
    將vm裡的os的gateway設成步驟2的ip即可
  4. 就這麼簡單


星期四, 6月 30, 2011

json parse error with double quotes

搞了半天
原來要用3個斜線
var tmp = {'name' : "kev///'s blog"};


Reference
json parse error with double quotes

星期二, 6月 28, 2011

建立index的準則

  • 具有特定鍵值足以識別特定資料
    如Primary key, Alternative key或user視為key拿來查詢的欄位
  • table資料少
    不到50筆或不到一個Data block,則建立的價值不大
  • join過程在where中會出現的欄位
    join過程大都以Primary key及Foreign key為條件,因此最好針對 Foreign key建立Index
  • 如果update或Delete程度超過20%,index價值不大
    因為系統必需同時I/O索引與實體資料
  • 不要太多索引
    太多的索引會造成資料異動過程要花很多時間調整索引
  • 查尋條件不明確
    考慮建立複合索引

Reference
Oracle 10g 資料庫管理實務, 林存德

星期六, 6月 18, 2011

JavaScript debug工具、技巧

寫入快顯視窗
  • 測試視窗
    var debug = window.open('','newWin',[arguments]);
    function addDebugginMessage(msg){
    debug.document.write(msg + '<br>');
    }

無侵入腳本程式設計 unobtrusive scripting

意思即將html中的view(css),結構(html),行為(js)分開
不要把3者都摻在html裡
css就很明確的利用class name從html分離了
js見下例
//html夾了javascript
<a href="#" onclick="showPopuup('niceimage.jpg')">Nice image!</a>


將html與js分開
<a href="niceimage.jpg" id="nice">Nice image!</a>
document.getElementById('nice').onclick = function(){
showPopup(this.href)
};

利用JavaScript跳過中間轉頁處理

html中,利用href的效果,如同click連結,會開啟新頁面
如果js中,判斷條件後轉頁
利用href轉頁,將會在history多一個歷史記錄
將造成使用者click上一頁會回到判斷頁,
而判斷頁又馬上轉到下一頁

解決方法,利用replace
//javascript
var isSupported = [check JavaScript support];
if (isSupported){
  locaiton.href = 'scriptpage.html';       //如果使用者按上一頁,就會再回到此判斷頁
  locaiton.replace('scriptpage.html');  //將回到真的上一頁
}




Reference:
pp]{ on JavaScript

星期一, 6月 13, 2011

CentOS 5.5升級PHP至最新版


PHP 5.3 on CentOS 5.5


#To install, first you must tell rpm to accept rpm’s signed by me, then add the yum repository information to yum:
rpm -Uvh http://repo.webtatic.com/yum/centos/5/latest.rpm

#Now you can install php by doing:
yum --enablerepo=webtatic install php

#update an existing installation of php
yum --enablerepo=webtatic update php

後記
好像失敗,原因還沒查出來
似乎是升級php後,部份套件沒升到相同版本
例如php 5.3,但php-common停在5.1
先remove重灌試試
而yum install php-common 會停在5.1
所以要用上面的方法 改變安裝的來源
yum --enablerepo=webtatic install php-common 安裝php-pear 因為centos的pear版本為1.4.9 需與php-devel 5.1搭
所以如果更新php後,就會裝不了
簡單點的方法就 ...
  1. 先降回5.1
    yum remove php php-*
  2. 再安裝pear
    yum install php-pear
  3. 最後升級php最新版

星期五, 6月 03, 2011

軟體開發書單

初階
  1. 態度
    心態最重要... 一切從心開始...
    • 自慢 1
    • 自慢 4
    • 打不破的人生 30 個定律
    • 學徒模式 優秀軟體開發者的養成之路
  1. Programming 
    • 編程創藝:編寫出卓越的程式碼 Code Craft: The Practive of Writing Excellent Code
    • 重構:改善現有程式碼的設計 Refactoring: Improving the Design of Existing Code, Martin Fowler
    • 程式碼大全 Code Complete
    • 程式開發心理學 The Psychology of Computer Programming 
    • 程式師修煉之道 The Pragmatic Programmer
    • 程式設計實踐 The Practice of Programming
    • Woking Efficiency with Legacy Code
  2. Design Pattern
    • 設計模式:可重複用的物導向軟體的基礎 Design Patters: Elements of Reusable Object-Oriented Software 
    • Design Pattern於java語言上的實習應用, 結城浩
  3. Coding Sytle
進階
  1. 物件觀念
    • Streamlined Object Modeling
    • Object Modes: Strategies, Patterns, and Applications (2/e) - by Peter Coad
    • Java Modeling in Color with UML: Enterprise Components and Process - by Peter Coad, Eric Lefebvre, Jeff De Luca
  2. Software Architecture
    1. Expert One-on-One J2EE Design and Development
      Spring Framework的創始人Rod Johnson對於J2EE 2.x的反思
    2. Expert One-on-One J2EE Development without EJB
  3. Software Development
  4. 專案管理
    • 人月神話 (The Mythical Ma0Month)
    • 溫伯格的軟體管理學, 溫伯格
    • 與熊共舞:軟體專案的風險管理
    • UML Distilled, Martin Fowler
    • 讓事情發生--專案管理之美學
    • 人件 (Peopleware:Productive Projects and Teams)
    • 深入淺出軟體開發 
    • Ship it
References

軟體開發時間估計

怎麼估計軟體開發的時間
我向來不猜想。猜想是很不好的習慣,它有害邏輯的推理 ~ 夏洛克.福爾摩斯
實用的估計方法
  1. 將任務盡可能地分解成最小的單位,高效地通過首次系統設計
  2. 當得到一個不錯的解決方案,並且它的各個組成部份都可以得到正確理解的時候,為每一個小任務塊提供一個時間範圍估計,「人時」或「人天」為單位
  3. 當你完成所有時間範圍估計之後,將這些時間放在一起,加總即得到一個整體的時間範圍估計
關鍵概念:徵求別人的意見來幫助你進行估計
交付軟體所需的所有活動
  • 執行考慮充分的設計
  • 所有必要的試驗性工作和原型設計
  • 實際的程式碼實作工作
  • 除錯
  • 編寫單元測試
  • 整合測試
  • 編寫文件
  • 期間需要開展的任何研究或培訓

懶惰的人只有靠運氣才能做出成功的估計

References
Code Craft: The Practice of Writing Excellent Code

星期五, 5月 20, 2011

[書]JavaScript: 優良部份

擷取
  • 企圖擷取不存在的屬性,會產生undefined
    stooge['middle-name'] //undefined
    flight.status //undefined

    較好的做法 - 給予預設值
    var middle = stooge['middle-name'] || "(none)";
    var status = flight.status || "unknown";
  • 企圖從undefined取值,將丟出TypeError
    可利用&&防衛此狀況
    flight.equipment //undefined
    flight.equipment.model //丟出"TypeError"
    flight.equipment && flight.equipment.model //undefined
減少全域變數
全域變教會削弱程式的彈性,利用物件包裝
var MYAPP = { };
//利用這個變數保存全域變數
MYAPP.flight = {
airline: "Oceanic",
number:815
};




Reference

JavaScript: The Good Parts - 中譯:JavaScript: 優良部份

星期四, 3月 31, 2011

mysql datetime format

  • 常用格式
    • 2011-03-28
      DATE_FORMAT(NOW(), '%Y-%m-%d');
  • DATE_FORMAT(date,format)

%M 月名字(January……December)
%W 星期名字(Sunday……Saturday)
%D 有英語前綴的月份的日期(1st, 2nd, 3rd, 等等。)
%Y 年, 數字, 4 位
%y 年, 數字, 2 位
%a 縮寫的星期名字(Sun……Sat)
%d 月份中的天數, 數字(00……31)
%e 月份中的天數, 數字(0……31)
%m 月, 數字(01……12)
%c 月, 數字(1……12)
%b 縮寫的月份名字(Jan……Dec)
%j 一年中的天數(001……366)
%H 小時(00……23)
%k 小時(0……23)
%h 小時(01……12)
%I 小時(01……12)
%l 小時(1……12)
%i 分鐘, 數字(00……59)
%r 時間,12 小時(hh:mm:ss [AP]M)
%T 時間,24 小時(hh:mm:ss)
%S 秒(00……59)
%s 秒(00……59)
%p AM或PM
%w 一個星期中的天數(0=Sunday ……6=Saturday )
%U 星期(0……52), 這裡星期天是星期的第一天
%u 星期(0……52), 這裡星期一是星期的第一天
%% 一個文字「%」。

Reference
Mysql日期和时间函数不求人

星期四, 3月 24, 2011

省下網路費 (連接2台無線AP)

由於跟老婆娘家住同社區 直線距離也只差7,8公尺而已
一直礙於沒辦法拉條網路線,只得各自付筆網路費

直到幾天前 同事才說用2台無線AP連接起來就好啦
才一語驚醒夢中人,且開心的是2台無線AP(Buffalo WHR-G54S)是同款且支援Bridge模式
這幾天試了好久,都一度想要放棄了
但想到每個月可以省600塊網路費 還是仍力嘗試
總於在昨天連續試了近5個小時下成功了 嗚 ...

我還是快記下來,免得將來又來一次...
而且Buffalo WHR-G54S已經停產了,將來現在產品網頁在官網已經搜尋不到了
還是用google才找到,不過看官網出了幾台都挺不錯的無線基地台,至少號稱不用太多設定了

設定說明
官方文件:WHR-G54S WDS設定教學,WHR系列WDS無線中繼功能設定方式

以下截錄官方教學文的內容
  • 成功要件
    要成功的將兩部AP 設定無線橋接/中繼/漫遊的要件如下:
    1. 兩部AP 的LAN IP Address 設定為同網段之不同IP (例如:192..168.11.×)。
    2. 第二部AP 的DHCP Server 功能均需關畢。
    3. 兩部AP 的WDS 功能均需 」Enable」。
    4. 兩部AP 的Wireless MAC Address 應互相抄寫。
    5. 兩部AP 的WEP Key 必須相同 (請參閱說明書設定)。
    6. 不可使用AOSS 功能
    7. 兩部AP 的Channel 必須相同 (請參閱說明書設定)。
    8. 兩部AP 的ESSID 必須相同方可達成漫遊功能(請參閱說明書設定)。
    9. 兩部AP 之間的距離必須要在可互相收到對方訊號的範圍內。
  • 步驟
    注意事項
    • 第一台IP:192.168.11.1,但第二台切到BRI時,要連192.168.11.100
    • 第二台將dhcp關掉時,會透過第一台要ip,因此當2台未連接成功而要連第二台AP時,會抓不到ip,要自行設定ip
    1. 第二台AP 底座的開關要接到BRI 的位置上 , 先使用網路線串接到第一台AP
      注意: 以下之步驟兩台AP 皆需設定
    2. 兩台AP 的橋接設定皆在"Advanced"-->"Wireless Config"內做設定
    3. 兩台AP 的"Wireless Config"-->"Basic"內的設定調整
      • Wireless Channel-->預設是"Auto Channel",要選擇一成個固定的"Channel" , 兩台要設成一樣
      • FrameBursting-->預設是"125*High Speed Mode",要改選成" FrameBursting"
      • 按"Apply"儲存設定
      p.s. 官方是建議SSID最後設定,因為改SSID要重連線,隨意啦
    4. 兩台AP 的"Wireless Config"-->"Security"內的設定
      • Wireless Encryption-->預設是"No Encryption",要選擇"WEP"
      • WEP Encryption Key-->預設是"Character Input:13 Characters(WEP128)",選擇要設定的位元數
      • 在1:的空白格上輸入要設定的密碼
      • 按"Apply"儲存設定
    5. 兩台AP 的"Wireless Config"-->"Repeater"內的設定
      • Repeater/Bridge (WDS)-->預設是"Disable",要改選成"Enable"後按"Apply"
      • Registered Access Points-->點選"Edit Registered WDS Partners"
      • Wireless MAC Address of an Access Point-->的空格中填入另一台的MAC Address,
      後按下"New Partner"
    6. 確定已經設定成功後,將"Wireless Config"-->"Basic"-->"SSID"設定成相同的名字
    7. 以上部驟完成後即完成 WDS 之設定

星期三, 3月 23, 2011

MySQL 資料庫備份與還原

  • 備份
    //將DB1輸出到DB1.sql
    #mysqldump -u root -p DB1 > DB1.sql

  • 還原
    • 還原整個資料庫
      #mysql -u root -p DB1 < DB1.sql
    • 還原資料表 (其實一樣)
      #mysql -u root -p DB1 < DB1_Table1.sql

Reference
MySQL 資料庫的備份與還原

星期五, 3月 18, 2011

MySQL效能 - 欄位

varchar + utf-8 長度設超過 170 的話, 就無法存在 memory 裡。別以為用 varchar 就可以亂設最長長度啊。 ...截至 fcamel MySQL varchar 長度和效能問題

Zend validator

  • validator
    $validator = new Zend_Validate_NotEmpty();
    if($validator->isValid($username))
    ...
  • chain
    $validatorChain = new Zend_Validate();
    $validatorChain->addValidator(new Zend_Validate_NotEmpty())
    ->addValidator(new Zend_Validate_Alnum()));

  • 自訂訊息
    $alnum = new Zend_Validate_Alnum();
    $alnum->setMessage('非數字');

    Zend_Validate_EmailAddress的setMessage沒反應,v1.11前都還沒修好

Zend View Helper

利用View Helper,在網頁中呈現使用者登入的資訊
<html>
//header ...
$this->LoggedInUser->loggedInUser()();
//content ...
</html>

class Zend_View_Helper_LoggedInUser
{
    protected $_view;
    function setView($view){
        $this->_view = $view;
    }
    function loggedInUser(){
        $auth = Zend_Auth::getInstance();
        if($auth->hasIdentity()) #2{
            $logoutUrl = $this->_view->linkTo('auth/logout');
            $user = $auth->getIdentity(); #3
            $username = $this->_view->escape(ucfirst($user->name));
            $string = 'Logged in as ' . $username . ' | Log out';
        } else {
            $loginUrl = $this->_view->linkTo('auth/identify'); #4
            $string = 'Log in'; #5
        }
        return $string;
    }
}

Zend View Render

View Render
$view = new Zend_View();
$view->setScriptPath(dirname(__FILE__) . “/templates”); //template的位置
$view->name = $name; //參數
$view->email = $email;
$view->render(‘form.phtml’); //render


template(login.phtml)
<html>
<body>
Login e-mail:email; ?>
Login password:password; ?>
</body>
</html>

星期四, 3月 17, 2011

ie css min-height問題

網上查只有ie6有不支援min-height問題
不過我也不知那機車美工怎麼做的
我的ie8不會自動延展div

最後用javascript自己給它"動"一下
做法是
function onload(){
var tmp = $('#content').css('position'); //content是破板的div
$("#content").css('position','absolute');
$("#content").css('position',tmp);
}


Reference
解決IE6不支援css min-width與min-height

星期三, 3月 16, 2011

nl2br問題

本來用mysql_real_escape_string用的好好的 不過最近處理textarea有斷行的文字 原本想用nl2br轉,卻一直轉失敗,一直沒有辦法判斷出\n
$value = mysql_real_escape_string($value); //先escape也會失敗<
$value = nl2br($value);

----result----
11/n22


調一下順序
$value = ereg_replace( "\n", "", $value); //不知為何用nl2br會失敗
$value = mysql_real_escape_string($value); //先escape也會失敗

----result----
11    <----有斷行,不過還是不對 
\n22


改掉nl2br的方法
$value = mysql_real_escape_string($value); //先escape也會失敗
$value = ereg_replace( "\n", "", $value); 
----result----
11    <-- 總算是成功了 
22

星期二, 3月 15, 2011

js取得置中位置

  1. 左右皆置中
    var $dialog = $("<div>hello</div>");
    var left = ($(window).width() - $dialog.outerWidth()) / 2 + $(window).scrollLeft() + "px";
    var top = ($(window).height() - $dialog.outerHeight() ) / 2 + $(window).scrollTop() + "px";
  2. click button後,置於button正下方
    onclick = "showDialog(this)
    function showDialog(obj)
    var margin_top = 30; //自行預設設margin top距離

    var pos = $(obj).offset();
    var eWidth = $(obj).outerWidth();
    var mWidth = $confirmBox.outerWidth();
    var left = (pos.left - mWidth/2) + "px";
    var top = margin_top + pos.top + "px";

星期二, 3月 08, 2011

國家代碼、中文名稱、英文名稱

直接複製,貼到excel組成sql字串

代碼 英文 中文
'AD' , 'Andorra' , '安道爾'
'AE' , 'United Arab Emirates' , '阿拉伯聯合酋長國'
'AF' , 'Afghanistan' , '阿富汗'
'AG' , 'Antigua & Barbuda' , '安提瓜和巴布達'
'AI' , 'Anguilla' , '安圭拉'
'AL' , 'Albania' , '阿爾巴尼亞'
'AM' , 'Armenia' , '亞美尼亞'
'AN' , 'Netherlands Antilles' , '荷屬安的列斯'
'AO' , 'Angola' , '安哥拉'
'AQ' , 'Antarctica' , '南極洲'
'AR' , 'Argentina' , '阿根廷'
'AS' , 'American Samoa' , '美屬薩摩亞'
'AT' , 'Austria' , '奧地利'
'AU' , 'Australia' , '澳大利亞'
'AW' , 'Aruba' , '阿魯巴'
'AZ' , 'Azerbaijan' , '阿塞拜疆'
'BA' , 'Bosnia and Herzegovina' , '波斯尼亞和黑塞哥維那'
'BB' , 'Barbados' , '巴巴多斯'
'BD' , 'Bangladesh' , '孟加拉'
'BE' , 'Belgium' , '比利時'
'BF' , 'Burkina Faso' , '布其納法索'
'BG' , 'Bulgaria' , '保加利亞'
'BH' , 'Bahrain' , '巴林'
'BI' , 'Burundi' , '布隆迪'
'BJ' , 'Benin' , '貝寧'
'BM' , 'Bermuda' , '百慕達'
'BN' , 'Brunei Darussalam' , '汶萊'
'BO' , 'Bolivia' , '玻利維亞'
'BR' , 'Brazil' , '巴西'
'BS' , 'Bahama' , '巴哈馬'
'BT' , 'Bhutan' , '不丹'
'BV' , 'Bouvet Island' , '布維島'
'BW' , 'Botswana' , '博茨瓦納'
'BY' , 'Belarus' , '白俄羅斯'
'BZ' , 'Belize' , '伯利茲'
'CA' , 'Canada' , '加拿大'
'CC' , 'Cocos (Keeling) Islands' , '可可島'
'CF' , 'Central African Republic' , '中非共和國'
'CG' , 'Congo' , '剛果'
'CH' , 'Switzerland' , '瑞士'
'CI' , 'Côte D\'ivoire (Ivory Coast)' , '象牙海岸'
'CK' , 'Cook Iislands' , '庫克群島'
'CL' , 'Chile' , '智利'
'CM' , 'Cameroon' , '喀麥隆'
'CN' , 'China' , '中國'
'CO' , 'Colombia' , '哥倫比亞'
'CR' , 'Costa Rica' , '哥斯達黎加'
'CU' , 'Cuba' , '古巴'
'CV' , 'Cape Verde' , '佛得角'
'CX' , 'Christmas Island' , '聖誕島'
'CY' , 'Cyprus' , '塞浦路斯'
'CZ' , 'Czech Republic' , '捷克共和國'
'DE' , 'Germany' , '德國'
'DJ' , 'Djibouti' , '吉布提'
'DK' , 'Denmark' , '丹麥'
'DM' , 'Dominica' , '多米尼加'
'DO' , 'Dominican Republic' , '多米尼加共和國'
'DZ' , 'Algeria' , '阿爾及利亞'
'EC' , 'Ecuador' , '厄瓜多爾'
'EE' , 'Estonia' , '愛沙尼亞'
'EG' , 'Egypt' , '埃及'
'EH' , 'Western Sahara' , '西撒哈拉'
'ER' , 'Eritrea' , '厄立特里亞'
'ES' , 'Spain' , '西班牙'
'ET' , 'Ethiopia' , '埃塞俄比亞'
'FI' , 'Finland' , '芬蘭'
'FJ' , 'Fiji' , '斐濟'
'FK' , 'Falkland Islands (Malvinas)' , '福克蘭群島(馬爾維納斯)'
'FM' , 'Micronesia' , '密克羅尼西亞'
'FO' , 'Faroe Islands' , '法羅群島'
'FR' , 'France' , '法國'
'FX' , 'France, Metropolitan' , '法國本土'
'GA' , 'Gabon' , '加蓬'
'GB' , 'United Kingdom' , '英國'
'GD' , 'Grenada' , '格林納達'
'GE' , 'Georgia' , '格魯吉亞'
'GF' , 'French Guiana' , '法屬圭亞那'
'GH' , 'Ghana' , '加納'
'GI' , 'Gibraltar' , '直布羅陀'
'GL' , 'Greenland' , '格陵蘭'
'GM' , 'Gambia' , '岡比亞'
'GN' , 'Guinea' , '幾內亞'
'GP' , 'Guadeloupe' , '瓜德羅普島'
'GQ' , 'Equatorial Guinea' , '赤道幾內亞'
'GR' , 'Greece' , '希臘'
'GS' , 'South Georgia and the South Sandwich Islands' , '南喬治亞島和南桑威奇群島'
'GT' , 'Guatemala' , '危地馬拉'
'GU' , 'Guam' , '關島'
'GW' , 'Guinea-Bissau' , '幾內亞比紹'
'GY' , 'Guyana' , '圭亞那'
'HK' , 'Hong Kong' , '香港'
'HM' , 'Heard & McDonald Islands' , '赫德和麥克唐納群島'
'HN' , 'Honduras' , '洪都拉斯'
'HR' , 'Croatia' , '克羅地亞'
'HT' , 'Haiti' , '海地'
'HU' , 'Hungary' , '匈牙利'
'ID' , 'Indonesia' , '印度尼西亞'
'IE' , 'Ireland' , '愛爾蘭'
'IL' , 'Israel' , '以色列'
'IN' , 'India' , '印度'
'IO' , 'British Indian Ocean Territory' , '英屬印度洋領地'
'IQ' , 'Iraq' , '伊拉克'
'IR' , 'Islamic Republic of Iran' , '伊朗伊斯蘭共和國'
'IS' , 'Iceland' , '冰島'
'IT' , 'Italy' , '義大利'
'JM' , 'Jamaica' , '牙買加'
'JO' , 'Jordan' , '約旦'
'JP' , 'Japan' , '日本'
'KE' , 'Kenya' , '肯亞'
'KG' , 'Kyrgyzstan' , '吉爾吉斯斯坦'
'KH' , 'Cambodia' , '柬埔寨'
'KI' , 'Kiribati' , '基里巴斯'
'KM' , 'Comoros' , '科摩羅'
'KN' , 'St. Kitts and Nevis' , '聖基茨和尼維斯'
'KP' , 'North Korea' , '朝鮮'
'KR' , 'Korea' , '韓國'
'KW' , 'Kuwait' , '科威特'
'KY' , 'Cayman Islands' , '開曼群島'
'KZ' , 'Kazakhstan' , '哈薩克斯坦'
'LA' , 'Lao People\'s Democratic Republic' , '寮國'
'LB' , 'Lebanon' , '黎巴嫩'
'LC' , 'Saint Lucia' , '聖盧西亞'
'LI' , 'Liechtenstein' , '列支敦士登'
'LK' , 'Sri Lanka' , '斯里蘭卡'
'LR' , 'Liberia' , '利比里亞'
'LS' , 'Lesotho' , '萊索托'
'LT' , 'Lithuania' , '立陶宛'
'LU' , 'Luxembourg' , '盧森堡'
'LV' , 'Latvia' , '拉托維亞'
'LY' , 'Libyan Arab Jamahiriya' , '利比亞'
'MA' , 'Morocco' , '摩洛哥'
'MC' , 'Monaco' , '摩納哥'
'MD' , 'Moldova' , '摩爾多瓦'
'MG' , 'Madagascar' , '馬達加斯加'
'MH' , 'Marshall Islands' , '馬紹爾群島'
'ML' , 'Mali' , '馬里'
'MN' , 'Mongolia' , '蒙古'
'MM' , 'Myanmar' , '緬甸'
'MO' , 'Macau' , '澳門'
'MP' , 'Northern Mariana Islands' , '北馬里亞納群島'
'MQ' , 'Martinique' , '馬提尼克'
'MR' , 'Mauritania' , '毛里塔尼亞'
'MS' , 'Monserrat' , '蒙特塞拉特'
'MT' , 'Malta' , '馬爾他'
'MU' , 'Mauritius' , '毛里求斯'
'MV' , 'Maldives' , '馬爾地夫'
'MW' , 'Malawi' , '馬拉威'
'MX' , 'Mexico' , '墨西哥'
'MY' , 'Malaysia' , '馬來西亞'
'MZ' , 'Mozambique' , '莫桑比克'
'NA' , 'Namibia' , '納米比亞'
'NC' , 'New Caledonia' , '新喀裡多尼亞'
'NE' , 'Niger' , '尼日爾'
'NF' , 'Norfolk Island' , '諾福克島'
'NG' , 'Nigeria' , '尼日利亞'
'NI' , 'Nicaragua' , '尼加拉瓜'
'NL' , 'Netherlands' , '荷蘭'
'NO' , 'Norway' , '挪威'
'NP' , 'Nepal' , '尼泊爾'
'NR' , 'Nauru' , '瑙魯'
'NU' , 'Niue' , '紐埃'
'NZ' , 'New Zealand' , '紐西蘭'
'OM' , 'Oman' , '阿曼'
'PA' , 'Panama' , '巴拿馬'
'PE' , 'Peru' , '秘魯'
'PF' , 'French Polynesia' , '法屬波利尼西亞'
'PG' , 'Papua New Guinea' , '巴布亞新幾內亞'
'PH' , 'Philippines' , '菲律賓'
'PK' , 'Pakistan' , '巴基斯坦'
'PL' , 'Poland' , '波蘭'
'PM' , 'St. Pierre & Miquelon' , '聖皮埃爾和密克隆群島'
'PN' , 'Pitcairn' , '皮特凱恩'
'PR' , 'Puerto Rico' , '波多黎各'
'PT' , 'Portugal' , '葡萄牙'
'PW' , 'Palau' , '帕勞'
'PY' , 'Paraguay' , '巴拉圭'
'QA' , 'Qatar' , '卡塔爾'
'RE' , 'Réunion' , '留尼汪'
'RO' , 'Romania' , '羅馬尼亞'
'RU' , 'Russian Federation' , '俄羅斯聯邦'
'RW' , 'Rwanda' , '盧旺達'
'SA' , 'Saudi Arabia' , '沙特阿拉伯'
'SB' , 'Solomon Islands' , '所羅門群島'
'SC' , 'Seychelles' , '塞舌爾'
'SD' , 'Sudan' , '蘇丹'
'SE' , 'Sweden' , '瑞典'
'SG' , 'Singapore' , '新加坡'
'SH' , 'St. Helena' , '聖赫勒拿'
'SI' , 'Slovenia' , '斯洛文尼亞'
'SJ' , 'Svalbard & Jan Mayen Islands' , '斯瓦爾巴群島和揚馬延島'
'SK' , 'Slovakia' , '斯洛伐克'
'SL' , 'Sierra Leone' , '塞拉利昂'
'SM' , 'San Marino' , '聖馬力諾'
'SN' , 'Senegal' , '塞內加爾'
'SO' , 'Somalia' , '索馬里'
'SR' , 'Suriname' , '蘇里南'
'ST' , 'Sao Tome & Principe' , '聖多美和普林西比'
'SV' , 'El Salvador' , '薩爾瓦多'
'SY' , 'Syrian Arab Republic' , '敘利亞'
'SZ' , 'Swaziland' , '史瓦濟蘭'
'TC' , 'Turks & Caicos Islands' , '特克斯和凱科斯群島'
'TD' , 'Chad' , '查德'
'TF' , 'French Southern Territories' , '法國南部領土'
'TG' , 'Togo' , '多哥'
'TH' , 'Thailand' , '泰國'
'TJ' , 'Tajikistan' , '塔吉克斯坦'
'TK' , 'Tokelau' , '托克勞'
'TM' , 'Turkmenistan' , '土庫曼斯坦'
'TN' , 'Tunisia' , '突尼斯'
'TO' , 'Tonga' , '東加'
'TP' , 'East Timor' , '東帝'
'TR' , 'Turkey' , '土耳其'
'TT' , 'Trinidad & Tobago' , '特立尼達和多巴哥'
'TV' , 'Tuvalu' , '圖瓦盧'
'TW' , 'Taiwan' , '台灣'
'TZ' , 'Tanzania' , '坦桑尼亞聯合共和國'
'UA' , 'Ukraine' , '烏克蘭'
'UG' , 'Uganda' , '烏干達'
'UM' , 'United States Minor Outlying Islands' , '美國本土外小島嶼'
'US' , 'United States of America' , '美國'
'UY' , 'Uruguay' , '烏拉圭'
'UZ' , 'Uzbekistan' , '烏茲別克斯坦'
'VA' , 'Vatican' , '梵蒂岡'
'VC' , 'St. Vincent & the Grenadines' , '聖文森特和格林納丁斯'
'VE' , 'Venezuela' , '委內瑞拉'
'VG' , 'British Virgin Islands' , '英屬維爾京群島'
'VI' , 'United States Virgin Islands' , '美屬維爾京群島'
'VN' , 'Viet Nam' , '越南'
'VU' , 'Vanuatu' , '瓦努阿圖'
'WF' , 'Wallis & Futuna Islands' , '瓦利斯群島和富圖納群島'
'WS' , 'Samoa' , '薩摩亞'
'YE' , 'Yemen' , '葉門'
'YT' , 'Mayotte' , '馬約特'
'YU' , 'Yugoslavia' , '南斯拉夫'
'ZA' , 'South Africa' , '南非'
'ZM' , 'Zambia' , '贊比亞'
'ZR' , 'Zaire' , '扎伊爾'
'ZW' , 'Zimbabwe' , '津巴布韋'
'ZZ' , 'Unknown or unspecified country' , '未知'

星期五, 3月 04, 2011

補齊固定字串長度

string str_pad( string $input , int $pad_length [, string $pad_string = " " [, int $pad_type = STR_PAD_RIGHT ]] )

$input = "Alien";
echo 
str_pad($input, 10);                      // produces "Alien     " 

echo 
str_pad($input, 10, "-=", STR_PAD_LEFT);  // produces "-=-=-Alien"
echo str_pad($input, 10, "_", STR_PAD_BOTH);   // produces "__Alien___" 
echo 
str_pad($input, 6 , "___");               // produces "Alien_"



UTF8問題
function mb_str_pad($input, $pad_length, $pad_string=' ', $pad_type=STR_PAD_RIGHT) {
   $diff = strlen($input) - mb_strlen($input, 'UTF-8');
   return str_pad($input, $pad_length+$diff, $pad_string, $pad_type);
}