[PHP] 實作例外處理

  在很久以前(也沒多久,我學PHP不到兩年)我就知道 PHP5 有例外處理,但是當時覺得PHP Exception 很腦殘,因為 PHP 函數庫不會拋出 Exception ....Orz,或許有人會想 PHP 函數又不像 JAVA 都是類別,但是也別忘了 PHP 是弱型別的。

以下先來看一下我覺得腦殘的範例....

try{
    $handle = fopen("/tmp/inputfile.txt", "r");   //<-找不倒檔案!
    fclose($handle);
    mysql_connect('nobody','nodoby','nodoby');   //<-連線失敗!
    mysql_query('select * from notablae;')        //<-沒有資料表!
}
catch(Exception $e){
    echo $e->getMessage();
}

  注意到了嗎,上面的例子是不會拋出任何例外的,尤其是最近看到一篇文章 腦殘 PHP: Codeigniter是萬靈丹? 才發覺這其實是 PHP 根本性的問題了。為什麼事根本性問題?翻開坊間上 PHP 的書,不外乎會像下面這樣寫,就連官方 PHP 也是。

if(isset($_REQUEST['age'])){
    $age = $_REQUEST['age'];
    $link = mysql_connect('localhost', 'mysql_user', 'mysql_password') or die('Could not connect: ' . mysql_error());
    $result = mysql_query("SELECT * from table where age<{$age};");
    if ($result) {
        while ($row = mysql_fetch_assoc($result)) {
            echo $row['firstname'];
            echo $row['lastname'];
            echo $row['address'];
            echo $row['age'];
        }
    }
}

  就算官方一直推 PDO 有推好像沒推一樣,另外 PDO 已經包含例外處理,非常好用,是值得大家去學習的。 最後實做把上面例子改寫一下。

//先建一個公用函數,來檢查 $_REQUEST 值。
function __GET($key=''){
    if($key!='' && isset($_GET[$key])){
        return $_GET[$key];
    }
    throw new Exception("Input 錯誤");
    return null;
}

//接下來我還需要建立一個例外處理
class MysqlException extends Exception {}

try{
    if(!$link = @mysql_connect('localhost', 'mysql_user', 'mysql_password')){
        //用PHP的錯誤控制運算式不是一個很好的方法
        //推薦方式用set_error_handler把所有錯誤訊息給隱藏掉
        throw new MysqlException(mysql_error());
    }

    $age = (int)__GET("age");
    
    if (!$result = @mysql_query("SELECT * from table where age<{$age};")){
        throw new MysqlException(mysql_error());
    }
    //我記得某些情形直接用while會發生錯誤,比較保守的方法是取得資源的長度在用 for 列出來。
    while ($row = mysql_fetch_assoc($result)) {
            echo $row['firstname'];
            echo $row['lastname'];
            echo $row['address'];
            echo $row['age'];
    }
}
catch(MysqlException $e){
 //在這邊決定要不要列出資料庫錯誤訊息!!
 echo $e->getMessage();
}
catch(Exception $e){
 echo "你玩壞我的主機了!!";
 echo $e->getMessage();
}

我的結論:
  看起來異常處理好像寫了很多行,但是也不全然沒好處,如果今天在加上 html 樣式,用 die 寫的話自己可能也跟這死一半。然後另一方面最好能用 PDO 寫就用PDO 寫,然後像我現在沒辦法用 PDO 寫就把 Mysql 和 pgsql 包成類別在包含異常處理就可以減掉好幾行程式,然後異常處理可以分層級就像 MysqlException。   最近才在 Android 上學玩一輪 JAVA 再回來寫 PHP ,所以也發覺異常處理上的某些好處,反正 PHP 鳥也不是一天兩天的是,從鳥 PHP 上我也學不少東西,特別是 PHP 的鳥問題,讓我學完一輪非常基礎的程式設計,只是目前在 PHP 類別上還是很難找到突破點。或許明天計畫可以考慮把 Ruby on Rails 和 zend framework 加進來學習了。

Share this

Related Posts

Previous
Next Post »