2012年1月22日

[php] Apache+Zend Framework安裝+NetBeans專案

最近研究了Zend Framework,雖然文件方面都是英文居多,不過安裝過程不算太難。

Zend Framework簡單來說就是提供MVC架構的一種php framework,甚麼是MVC呢!!就是這個
而php的MVC並不是只有一種,比較有名的還有CakePHP,那要用哪種比較好呢?對不起,小弟還在磨練中,有請各位自行google了
但我想各有優缺點吧,挑一個自己最能上手的當然最好,像是CakePHP有中文的使用手冊,對於想要快速上手的人也許比較好!

安裝前要準備甚麼呢!!記得要先裝好php,作業系統的話windows、Mac或是Linux都可以,這次的練習是以CentOs 6當作範本,所以以下的路徑等等都是使用Linux來表示,而不同的Linux系統也會有一些些微差異。

1. 取得安裝檔

一開始要先取得需要的安裝檔,可以到這個連結,或是自行到官網尋找

到了下載頁面會看到很多個選項可以點,這裡就牽扯到要怎麼安裝和執行Zend Framework,第一個選項 "Zend Framework + Zend Server Community Edition"
這個下載是包含Zend Framework和Zend自己的伺服器,如果選擇這個選項的話就可以直接使用zend server當作伺服器,而且在Mac OSX、Windows、Ubuntu和Fedora核心等系統會有安裝精靈可以使用,算是安裝比較容易的一種方式

不過目前先不採用這種方式,server的話這次是使用Apache,所以選 "Zend Framework X.X.X Full" 這個選項,這樣就成功取得安裝檔囉!

2. 安裝與設定

下載好檔案先解壓縮,檔案放在哪都可以,目前以/usr/local/zend當作範例

解壓縮完之後修改php.ini,把剛剛zend資料夾內的library路徑新增到include_path當中,例如

include_path=".:/php/includes:/usr/local/zend/library"

冒號是用來分隔多個路徑,詳細的include_path設定可以到php官網查閱

完成此步驟後,恭喜!!Zend Framework安裝完成囉!!

3. 開啟一個新專案

完成安裝之後下一步就是新增專案啦,先到/usr/local/zend/bin目錄中找到 zf.sh 這個shell script,然後用指令的方式執行他

[root@localhost bin]# ./zf.sh create project test

執行完成後如果顯示出 Note:This command created a web project...,就表示成功新增了一個名稱為 test 的專案囉!


如果以上步驟都沒問題表示Zend Framework已經可以正常使用了,但是,在這裡提出幾個比較可能遇到的問題

問題一 : 新增專案時出現Testing Note:PHPUnit was not found in your include_path...的錯誤訊息

其實Zend Framework需要另一個php的Framework,那就是PHPUnit,PHPUnit是用來做單元測試的一個套件,如果出現這個問題就表示PHPUnit尚未安裝或是安裝好了卻還沒設定include_path

而目前PHPUnit是使用pear在管理的,所以要安裝PHPUnit前要先安裝pear,pear的安裝方法可以到這個網頁參考

pear安裝完成後就可以裝PHPUnit囉,安裝步驟可以參考這個網頁

全部都安裝好之後就是修改php.ini,需要把PHPUnit所在的資料夾加入include_path,例如

include_path=".:/usr/share/pear:/php/includes:/usr/local/zend/library:/usr/share/pear/PHPUnit"

設定完成後再新增專案就可以成功囉

問題二 : 新增專案時出現 PHP Fatal error:Class 'DOMDocument' not found in....的錯誤訊息

如果看到這個錯誤訊息表示php-xml這個套件沒有安裝,所以來趕快安裝它吧!

[root@localhost bin]# yum install php-xml

安裝完成後就可以成功新增專案


使用NetBeans新增一個Zend Framework專案

新增之前先確定好Zend Framework都安裝且設定完成,在NetBeans工具列找到Tool->options,然後點選到下面這個畫面

tool

然後在Zend script欄位中輸入zf.sh這個檔案的路徑,設定完成後就可以使用NetBeans來新增一個Zend Framework的專案

新增專案的方式不會太複雜,所以就不另行說明!

以上就是這次的練習!如有任何問題還請多多指教!!

2012年1月17日

[php] jQuery ajax 購物車實作

這次的練習是使用php實作購物車,購物紀錄使用session,資料庫使用mysql,php連線使用PDO
下面的程式碼只是提出某些主要的function,其他使用文字做說明

1. 資料庫連線include檔


//資料庫連線資料
define('user','root');
define('password','XXX');
define('dbname','test');

2. 資料庫連線class(繼承用)

class Mysql {

    private $dbname = dbname;
    //使用prepare執行查詢,並回傳結果
    public function executePrepareSelect($sql, $param) {
        $db = new PDO("mysql:host=localhost;dbname=$this->dbname", user, password);
        try {
            $stmt = $db->prepare($sql);
            if (count($param) > 0) {
                foreach ($param as $key => $val) {
                    $this->bindParameters($stmt, $key, $val);
                }
            }
            $stmt->execute();
            $db = null;
        } catch (PDOException $e) {
            $e->getMessage();
            return false;
        }
        return $stmt->fetchAll();
    }
    //用來bind參數
    private function bindParameters($stmt, $key, $value) {
        if (is_int($value)) {
            $stmt->bindParam(':' . $key, $value, PDO::PARAM_INT);
        } else if (is_bool($value)) {
            $stmt->bindParam(':' . $key, $value, PDO::PARAM_BOOL);
        } else if (is_string($value)) {
            $stmt->bindParam(':' . $key, $value, PDO::PARAM_STR);
        } else {
            $stmt->bindParam(':' . $key, $value);
        }
    }
}

Mysql類別主要用來隔離出資料庫select、insert等等所需要的方法,加速其他功能的開發

3. 商品class

class Product extends Mysql {

     //使用商品編號查詢商品
    function getProductById($pid) {
        $param = array("id" => $pid);
        $sql = $this->createPrepareSelectStatement($param);
        $result = $this->executePrepareSelect($sql, $param);
        if ($result)
            return $result[0];
        else
            return "error";
    }
    //新增商品
    function insertProduct($name, $price, $caption) {
        $param = array("ProductName"=>$name,"Price"=>$price,"Caption"=>$caption);
        $sql = $this->createPrepareInsertStatement($param);
        if($this->executePrepareInsert($sql, $param)){
            return true;
        }else{
            return false;
        }
    }
}

雖然商品類別應該代表一個商品,為了簡便就不把商品單獨做出一個類別,商品類別目的在於提供商品的查詢、新增等方法,直接繼承Mysql類別加速開發,createXXXStatement方法只是給予需求的參數就可以產出sql新增或查詢語法

4. 購物車類別

class ShopCar {
    private $items = array(); //購買的商品
    private $count; //新增商品的旗標
    private $total; //總價
    //加入商品
    public function addItem($pid, $num) {
        try {
            for ($i = 0; $i < $num; $i++) {
                $this->items[$this->count] = $pid;
                $this->count++;
            }
            $this->total = $this->setTotal();
            return true;
        } catch (Exception $e) {
            echo $e->getMessage();
            return false;
        }
    }
    //刪除物品
    public function deleteItem($pid){
        for($i=0;$iitems);$i++){
            if($this->items[$i] == $pid){
                unset($this->items[$i]);
            }
        }
    }
    //產出購買物品列表
    public function getAllItems(){
        $tmp = array();
        foreach($this->items as $item){
            if(empty($tmp[$item])){
                $tmp[$item] = 1;
            }else{
                $tmp[$item]++;
            }
        }
        $pending = "";
        $pending .= "";
        foreach($tmp as $key=>$value){
            $p = new Product();
            $item = $p->getProductById($key);
            $name = $item["ProductName"];
            $price = $item["Price"];
            $sumPrice = intval($value) * intval($item["Price"]);
            $caption = $item["Caption"];
            $pending .= "";
        }
        $pending .= '
編號名稱數量單價總價說明
$key$name$value$price$sumPrice$caption
'; return $pending; } }

代表一輛購物車的類別,使用一個陣列(items)記錄使用者購買的商品ID,需要各種資訊如目前購買總價、商品列表都從陣列中提出ID再做查詢,減少新增或刪除商品時的資料庫讀取次數

5. ajax處理商品頁面

if (!isset($_SESSION['car'])) {
    die("error");
}
$car = $_SESSION['car'];
if (strval($_GET['type']) == "add") {
    //加入商品
    if (empty($_GET['pid'])) {
        print "pid not set";
        exit();
    }
    $success = array();
    if ($car->addItem(intval($_GET['pid']), intval($_GET['num']))) {
        $success[0] = "product " . $_GET['pname'] . " add success";
        $success[1] = strval($car->getTotal());
        print json_encode($success);
    } else {
        $success[0] = "error";
        print json_encode($success);
    }
} else if (strval($_GET['type']) == "reset") {
    //重製購物車
    $success = array();
    if ($car->resetCar()) {
        $success[0] = "reset success";
        $success[1] = strval($car->getTotal());
        print json_encode($success);
    } else {
        $success[0] = "reset fail";
        print json_encode($success);
    }
}

負責處理ajax傳來的指令,使用type區分要求的動作,add是加入商品、reset是重製購物車,結果回傳部分使用json

6. javascript傳送function

function ajaxProduct(targetUrl,GETdata,resultArea,money){
    //targetUrl  -> ajax傳送的頁面
    //GETdata    -> 傳送ajax的參數,使用GET方式傳送
    //resultArea -> 顯示結果狀態的區塊
    //money      -> 顯示目前的總價的區塊
    $.ajax({
        url:targetUrl,
        data:GETdata,
        dataType:"json",
        error:function(xhr,status,thrown){
            $(resultArea).html(status);
        },
        success:function(result,status,xhr){
            $(resultArea).html(result[0]);
            $(money).html(result[1]);
        }
    });
}

最後一個就是負責傳送與接收ajax指令的function,這裡使用到jQuery的ajax功能,比較方便跟快速


以上就是這次的購物車實作內容,如果有不對的地方還請多多指教阿!謝謝!

2012年1月7日

[C#] 小數點以下無條件進位至某位數

最近因為網頁的某些需求中需要小數點以下無條件進位,所以就研究了一下
public static double RoundUp(double input, int num)
{
    double tmpNum = Math.Floor(input);
    if ((input - tmpNum) > 0) //判斷input是否為整數
    {
        if ((input - Math.Round(input, num)) != 0) //判斷所要取的位數是否存在
        {
            //利用四捨五入的方法判斷是否要進位,若取的下一位數大於等於5則不用進位
            if (Convert.ToInt32(input * Math.Pow(10, num + 1) % 10) < 5)
            {
                return Math.Round(input, num, MidpointRounding.AwayFromZero) + Math.Pow(0.1, num);
            }
            else
            {
                return Math.Round(input, num, MidpointRounding.AwayFromZero);
            }
        }
        else
        {
            return input;
        }
    }
    else
    {
        return input;
    }
}

說明:

方法接收的參數第一個是要處理的浮點數,第二個是要取到小數點以下哪個位數並無條件進位。
如果輸入的參數為整數或要取的位數大於輸入的參數則回傳input

Example:

RoundUp(12.432, 2) = 12.44
RoundUp(13.5648, 3) = 13.565