2010-01-22 169 views
0

我想弄清楚如何處理我的PHP應用程序中的設置。我幾乎決定要使用Confg類文件,以便將來自動加載並且靈活。以下是我正在玩的一些東西。我可以從現有變量中設置PHP類屬性嗎?

我知道你不能設置一個變量來顯示一個常量,所以我嘗試使用一個公共靜態屬性。

爲什麼我不能設置public static $ ip = $ _SERVER ['REMOTE_ADDR']; ??

<?php 
// config.class.php 
class Config 
{ 
    const URL = 'http://www.foo.com'; 
    const DB_User = 'dbname'; 

    public static $test = 'test string'; 
    public static $ip = $_SERVER['REMOTE_ADDR']; 
} 

/////////////////////////////////////////////////////// 
//index.php 

// works 
echo Config::URL; 

// works 
echo Config::$test; 

// DOES NOT WORK 
echo Config::$ip; 

?> 

回答

2

儘管這不會回答你的問題(jspcal回答它正確),一個快速的解決方案,可能適合你會使用Singleton design pattern需求。這裏是一個另類:

<?php 

// config.class.php 
class Config 
{ 
    /** 
    * Instance container 
    * @var Config 
    */ 
    private static $instance = null; 

    /** 
    * Constants container 
    * @var array 
    */ 
    private $constants = array(
     'url'  => 'http://www.foo.com/', 
     'db_user' => 'dbname' 
    ); 

    /** 
    * Options container 
    * @var array 
    */ 
    private $options = array(); 

    /** 
    * Don't allow outside initialization 
    */ 
    private function __construct() 
    { 
     // Set options (could load from external source) 
     $this->options = array(
      'test' => 'test string', 
      'ip' => $_SERVER['REMOTE_ADDR'] 
     ); 
    } 

    /** 
    * Disable cloning 
    */ 
    private function __clone() { } 

    /** 
    * Get new instance of class 
    */ 
    public function getInstance() 
    { 
     if (null === self::$instance) { 
      self::$instance = new self(); 
     } 
     return self::$instance; 
    } 

    /** 
    * Retrieve value with constants being a higher priority 
    * @param $key Key to get 
    */ 
    public function __get($key) 
    { 
     if (isset($this->constants[$key])) { 
      return $this->constants[$key]; 
     } elseif (isset($this->options[$key])) { 
      return $this->options[$key]; 
     } 
    } 

    /** 
    * Set a new or update a key/value pair 
    * @param $key Key to set 
    * @param $value Value to set 
    */ 
    public function __set($key, $value) 
    { 
     $this->options[$key] = $value; 
    } 
} 

/////////////////////////////////////////////////////// 
//index.php 

// works 
$config = Config::getInstance(); 
echo $config->url; 
echo $config->test; 
echo $config->ip; 

更新時間:不知道你想要的常量/有那樣的優先選擇。這只是一個例子。

+0

雖然這是你正在尋找的替代品,我建議可能有一個數組設置爲私人存儲的價值和使用PHP魔術變量__get __set和檢索數組的值。 – William 2010-01-22 20:58:31

+0

實際上,這是有點什麼,我正在考慮如何做,所以這很好+1 – JasonDavis 2010-01-22 20:59:42

+0

更新了一個更好的例子。 – William 2010-01-22 21:08:55

3

成員必須使用常量表達式(如字符串常量,數字文字等)進行初始化。如果你嘗試用動態表達式(如變量或函數調用的值)初始化一個成員,php會給出一個分析錯誤...

這不像其他一些langs像python或javascript,它考慮類定義是與可執行表達式相提並論......所以在這裏你的想法是非常實用的,但PHP不支持,現在至少...

但也有一些替代品來處理這個:

在類定義之後添加初始化:

class C {...} 
C::$var = $_SERVER['REMOTE_ADDR']; 

或有一個初始化函數:

function init() 
{ 
    if (self::$init === false) { 
    self::$var = $_SERVER['REMOTE_ADDR']; 
    self::$init = true; 
    } 
} 

C::init(); 

或較新的PHP可以使用__autoload()掛鉤,做一些靜態初始化...

+0

你知道有什麼好的替代方法來獲得類似的結果嗎? – JasonDavis 2010-01-22 20:49:57

+0

請注意,對於堅持PHP4的人來說,'C :: init()'可以工作,但'C :: $ var'不能。 – user535673 2013-01-09 16:01:41

0

它不會起作用,因爲PHP少了點允許它。

一般來說,我不會建議把你的應用程序的配置成一個類(至少在PHP),還有在我看來,沒有真正的優勢 - 更好的把它變成一個全球性的陣列左右:)

+0

我正在考慮創建一個將拉入數組文件的類,這樣我就可以將文件路徑傳遞到數組文件或其他行。 – JasonDavis 2010-01-22 20:51:17

0

PHP根本不允許這樣做。如果你仔細想想,不管怎樣,將REMOTE_ADDR作爲配置數據的一部分是沒有意義的。您可以將其視爲請求數據的一部分,而不是應用程序配置。

至於你的配置,我會建議使用.ini文件進行配置,因爲PHP有​​一個內置的INI解析器(請參閱parse_ini_file函數)。這與PHP爲自己的配置選擇INI文件格式(即php.ini)一致。

退房這個問題,例如:What's Is the Best File Format for Configuration Files

+0

至少告訴我爲什麼你低估了。我回答了他的問題,甚至提出了一個建議... – 2010-01-22 21:13:22

1

不是您的問題的直接答案,但爲什麼不使用較少硬編碼的方法,例如,你可以在你的應用程序重複使用一個通用的配置類

// MyConfig.php 
class MyConfig { 
    protected $_data; 

    public function __construct($path) 
    { 
     $config = include $path; 
     $this->_data = $config; 
    } 

    public function __get($val) 
    { 
     if(array_key_exists($val, $this->_data)) { 
      return $this->_data['val']; 
     } else { 
      trigger_error("Key $val does not exist", E_USER_NOTICE); 
     } 
    } 
} 

,你可以從一個數組填寫特定應用的

// app-config.php 
return array(
    'ip' => $_SERVER['REMOTE_ADDR'], 
    'url' => 'http://www.foo.com'; 
    'db' => array(
     'host' => 'foo.com', 
     'port' => 3306 
    ), 
    'caching' => array(
     'enabled' => false 
    ) 
); 

,然後在你的引導使用像

$config = new MyConfig('/path/to/app-config.php'); 
+0

如果我正確理解他,他希望配置處於全局範圍內。雖然他可以通過將其更改爲單例模式或使用註冊表模式來輕鬆解決此問題。 – William 2010-01-22 21:10:40

+0

這可能是我將要去的路線,是的,我確實需要讓它全局可訪問 – JasonDavis 2010-01-22 21:15:39

+0

我寧願爲此設置一個依賴注入服務容器,但由於我已經多次向Jason提出這個建議,我猜他有他沒有使用的理由。沒有人,我會通過一個註冊表通過一個Singleton,只是爲了能夠擁有多個Config對象,以防萬一我需要其他的我想擁有的全局可用的配置。註冊表更專注於此。 – Gordon 2010-01-22 21:33:35

1

這沒有回答你的問題,但在我看來,處理配置的更好方法實際上是使用配置文件,如INI或XML文件。

您可以使用例如在Zend Config類讀寫這些文件(這個類甚至可以用一個簡單的PHP數組作爲配置處理。

最終這會讓你的代碼更易於維護。

閱讀其他的答案和評論之後您可能也有興趣在Zend Registry類。

一般來說,我會建議使用這類東西的框架或現成的組件。你不需要重新發明輪子,你可以從對方的經驗中獲益。

+0

構建我自己的主要原因是現在真正的學習體驗。我喜歡從你發佈的類似東西中學習代碼 – JasonDavis 2010-01-22 22:50:29

2

嘗試使用define()來做到這一點(給一個常數!):

// config.class.php 
define(REMOTE_ADDR, $_SERVER['REMOTE_ADDR']); 

    class Config 
    { 
     const URL = 'http://www.foo.com'; 
     const DB_User = 'dbname'; 

     public static $test = 'test string'; 
     public static $ip = REMOTE_ADDR; 
    } 
相關問題