2008/04/25

SugarCRM 的 射、拔、追

今天我的老闆交代我在 Server 上裝一份新的 SugarCRM ,原以為是個很簡單的事情,結果花了一整天~
原因出在 SugarCRM 在安裝過程中,檢查 MySQL 連線設定那部份一直過不了,可是在同一台機器上,另外一份之前安裝過的 SugarCRM 卻跑的好好的~

我以為是 PHP 版本問題,從 PHP4 升級、換成 PHP5 都不行~
後來以為是 MySQL 的問題,重裝、換了 5.1 的版本也不行~
最後只好使出最終奧義:在 Windows 上裝好後再移過去...

這下終於可以動了,不過我還是不曉得 SugarCRM 的安裝程式出了什麼問題。

另外,我在 Windows 下安裝程序最後會發生 500 錯誤,只要把 SugarCRM 目錄下的 .htaccess 這個檔案刪除即可正常執行~

2008/04/15

重構插件類別

算是在實做過程中發現一些問題,然後重構這個強力工具!

我知道我目前碰到一個危險的境界,由於這個插件的類別非常強力,我經常拿他來替代繼承,我知道有點過頭了,但它真的很好用!
~我是說你可以維持一個物件變數,然後把需要功能一直掛入(只要你繼承這個抽象的插件類別,寫出你需要的功能)~

這幾天一直為了unset前後記憶用量沒有改變的問題無法釋懷,後來問了 kiang,他表示那是 Zend 引擎還沒到記憶體回收的週期,所以不會釋放~
這個類別的 __更新() 方法有一個地方我一直無法瞭解為何會有這個效果,知道的網友請開示吧~

另外一提,ADODB Lite 目前仍然是記憶用量最小的 DB Layer ,我自己寫的這個 DB Layer 跟它比較,兩邊都不掛任何多餘的模組,硬是比它大了約 50 K...
我該檢討了~


<?php
abstract class Zyme_Class_Plugin{
    private $_插件 = array();
    private $_方法 = array();
    private $_反映 = array();

    function __construct($宿主 = null){
        static $類別 = __CLASS__;
        if ($宿主 instanceof $類別) {
            $this->__插件($宿主);
        }       
    }
   
    final function __call($方法, $參數){
        return call_user_func_array($this->_方法[$方法], $參數);
    }

//    清除插件方法
    final protected function __清除(){
        $this->_插件 = array();
        $this->_方法 = array();
        $this->_反映 = array();
    }   

//    測試某個插件是否已安裝
    final protected function __已裝($類別){
        return isset($this->_插件[$類別]);
    }
   
//    將插件的方法加入$this的方法中
    final protected function __插件(Zyme_Class_Plugin $插件){
        $類別 = get_class($插件);
        if (false == $this->__已裝($類別)){
            $this->_插件[$類別] = $插件;
            $this->_方法 = $插件->__反映() + $this->_方法;
        }
    }

//    取得插件的可呼叫方法列表
    final function __方法(){
        return $this->_方法;
    }

//    取得插件本身的方法列表(除了方法名稱開頭是'__'的方法,例如一些魔術方法,或是方法本身屬於私有方法)
    final private function __反映(){
        $輸出 = &$this->_反映;
        if (false == empty($輸出)) {
            return $輸出;
        }
        $反映 = new ReflectionObject($this);
        $方法 = $反映->getMethods();
        foreach ($方法 as $項目){
            $名稱 = $項目->getName();
            if (0 !== strpos($名稱, '__') && false == $項目->isPrivate()) {
                $輸出[$名稱] = array($this, $名稱);
            }
        }
        return $輸出; 
    }

//    匯入插件的可呼叫方法表
    final function __匯入(Zyme_Class_Plugin $宿主){
        $this->_方法 = $宿主->__方法() + $this->_方法;
    }

//    更新所有插件的方法,通常在載入所有插件後調用
    final protected function __更新(){
        foreach ($this->_插件 as $插件){           
            $插件->_方法 = $this->_方法 + $插件->_方法;    //    照理說,這行應該會出現錯誤(存取私有成員),但不知為何可以執行
//            $插件->__匯入($this);    //    萬一未來版本上面那行無法執行時,可以改用這行
        }
    }
   
}

?>


2008/04/07

開發平台暫時維持在 PHP 5.2.5

由於名稱空間的諸多限制,以及 PHP 5.3 的 call_user_func_array 傳遞參照參數陣列 與 &new 的 Deprecated 警告問題,個人決定還是先將開發平台維持在 PHP 5.2.5 上面。
名稱空間的限制還好,但後面那兩個會造成許多現有的函式庫噴出一堆警告訊息,我沒時間一個一個去修,所以只好暫時放棄,等年底 PHP 5.3 出來一陣子後再看看。

2008/04/03

名稱空間的注意事項

在使用上有幾個要注意的事情:

  • 使用 use 敘述必須至少有一項用::串接
use test; // 這是錯的
use test::test1; // OK

  • 上述的的敘述中,若用::來分隔,最後一項不可相同,若相同則必須用 as 來設定別名
use test::test1::test;
use test::test2::test; // 這是錯的
use test::test2::test as test0; // OK

  • 命名空間不可使用關鍵字或保留字
use test::class; // 這是錯的
use test::_class; // OK

  • 透過字串變數來 new 一個物件時,字串變數必須為完整的類別
use test::test1;
$class1 = 'test1::_class';
$class2 = 'test::test1::_class';
$obj1 = new $class1();   //   這是錯的
$obj2 = new $class2();   //   OK
這當中我個人覺得最嚴重的問題是,命名空間不可以使用關鍵字或保留字這項限制,如此一來將可用的詞彙縮減掉了,實在是很不方便~
最明顯的影響是 interface 一詞,這在 ZF 的命名中是非常常見的,目前的解法是加底線、使用縮寫,或是改用其他的詞彙。
不過 interface 這個詞彙是電腦的專有名詞,目前在物件導向中,並無其他的詞彙可替代,實在是很傷腦筋。

PHP 5.3 dev

根據 PHP 5.3 todo 的資訊,PHP 5.3 會在今年第二或是第三季推出,目前我正在考慮改用 5.3 的 namespace 功能加上類似ZF和PEAR的目錄結構來發展與佈署程式。
我放了一份修改過的 PortableAPM 在這裡,需要的人請自行取用。

使用時要注意 mysql 的部份,由於新引進 mysqlnd 的關係,所以即便是可以用 dl 來載入,對於 mysql 相關的 extension 最好在 php.ini 裡先載入。

剛剛找到這個網頁,裡面的資訊表示了PEAR2要採用名稱空間的作法。