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

2011年6月24日

[C#] 資料庫管理系統

C#製作的員工、訂單、客戶管理系統

使用ADO.NET元件存取Access資料庫


主程式畫面(上)
OleDbConnection conn = new OleDbConnection();
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Database2.accdb";
DataSet ds = new DataSet();
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM " + table + " ORDER BY " + ordkey,conn);
da.Fill(ds, table);
dataGridView1.DataSource = ds.Tables[table];
da.Dispose();
ds.Dispose();
conn.Dispose();
程式碼連線的某區段

點我下載專案黨

2011年6月4日

[JAVA] Socket 和 Swing 測試

JAVA使用Socket傳送檔案小測試

實作了伺服器端與客戶端,可傳送可接收

伺服器端的儲存位置並 沒有 寫成為動態選擇,目前為寫死狀態
Server連接port也還沒寫入偵測有無佔用(如果有占用會出錯= =||)

總之還有很多BUG....

主要目的是測試GUI介面和結合multi thread的實作



GUI介面




原始碼下載請點我

2011年5月22日

[VB] 實作HTTP檔案下載(多執行緒)



Imports System.Net
Imports System.IO
Imports System.Threading
Public Class Form1
    '跨執行緒使用的委派
    Public Delegate Sub ChangeUpdate()
    Public Delegate Sub ChangeSet(ByVal max As Integer, ByVal min As Integer)
    private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        '使用new thread產生執行緒
        '使用Parameterized傳遞參數
        Dim thread1 As New Thread(New ParameterizedThreadStart(AddressOf downFile))
        thread1.Start(TextBox1.Text)
    End Sub

    Private Sub downFile(ByVal url As Object)
        Dim url2 As String = url.ToString()

        'HttpWebRequest產生Http的請求並用HttpWebResponse接收
        Dim request As HttpWebRequest = WebRequest.Create(url)
        Dim response As HttpWebResponse = request.GetResponse()

        '找尋Http標頭中的檔案長度
        Dim length As Integer = Convert.ToInt32(response.GetResponseHeader("content-length"))

        '因為下載時不是用UI Thread,所以必須使用Invoke來改變ProgressBar的屬性
        Me.Invoke(New ChangeSet(AddressOf SetBar), New Object() {length, 0})

        '開啟一個檔案空間並命名為"test.jpg"
        '檔名可視下載檔案改變,或是解析下載網址來判斷
        Dim fs As FileStream = New FileStream("test.jpg", FileMode.Create)
        Dim br As BinaryReader = New BinaryReader(response.GetResponseStream())
        Dim bw As BinaryWriter = New BinaryWriter(fs)

       '開始讀取串流,邊讀邊寫入
        For i = 0 To length - 1
            bw.Write(br.ReadByte)
            '同樣因為不是UI Thread所以透過委派改變ProgressBar屬性
            Me.Invoke(New ChangeUpdate(AddressOf UpdateBar))
        Next
        br.Close()
        bw.Close()
        fs.Close()
        response.Close()
    End Sub

    Private Sub SetBar(ByVal max As Integer, ByVal min As Integer)
        ProgressBar1.Maximum = max
        ProgressBar1.Minimum = min
    End Sub

    Private Sub UpdateBar()
        ProgressBar1.Value = ProgressBar1.Value + 1
    End Sub
End Class


使用HttpWebRequest和HttpWebResponse下載Http協定的檔案

為了避免在下載時等待過久而造成主執行緒(UI Thread)死當的情況

所以使用多執行緒下載