2009-09-15 48 views
3

我在考慮將每個類放入一個單獨的文件並在類定義之外進行靜態初始化。我應該如何彌補PHP中缺少靜態初始化器?

這樣做的問題是,在實際需要所述類之前會發生初始化(當包含該類的文件第一次包含時會發生)。這是一個問題,因爲可能發生該類不會被使用,因此初始化是不必要的。而且我認爲在代碼的開頭不包含使用的文件的做法只是一種骯髒的技術。

如果有人有這個問題的可行解決方案,我將不勝感激。

+0

您認爲您需要靜態初始化程序嗎?如果你更清楚你想做什麼,我們可以幫助你更好。我從來不需要他們;你可能會推翻這一點。 – ryeguy 2009-09-15 18:00:51

+2

我需要它們建立與數據庫的連接。但請意識到,解釋爲什麼我不應該這樣做,並不能真正解決這個問題,正如我懷疑的那樣 - 並不是我的獨有。 – kahoon 2009-09-15 18:05:21

回答

2

當找不到類時,可能會查找__autoload它被調用並應該包含該文件包含該類。您可以將靜態初始化器放在該函數中。

+1

您可以將靜態初始化器放到包含該類的PHP文件中,並讓__autoload爲您包含類文件。手動包括類文件的這種方式不會導致任何問題。 – 2009-09-15 20:39:22

+0

我不知道__autoload,我非常喜歡這個解決方案。我相信這是最接近我可以模擬所需的功能。另一件好事是我可以避免逐個包含每個需要的文件;我只需創建一個包含__autoload方法的文件,並在需要時執行該工作。謝謝! – kahoon 2009-09-15 22:09:34

+0

這就是我們爲我們的班級所做的,使用includes管理40-50班是非常困難的。我希望有一種方法可以爲JS做同樣的事情。我們最終添加了大量不必要的JS文件。 – 2009-09-15 22:14:52

3

看看這樣的代碼。它使用的數據庫的單一實例但你仍然可以創建類的實例:

class DB 
{ 
    private static $_db; 

    public static function pdo() 
    { 
     if (is_null(self::$_db)) 
     { 
      self::$_db=new PDO('pgsql:host=localhost; 
           port=5432; 
           dbname=testdb; 
           user=postgres; 
           password=abc123'); 
      self::$_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } 

     return self::$_db; 
    } 

public static function factory() 
{ 
    return new self; 
} 

private function __construct() {} 

當你想在DB的一個實例,你做DB::factory()。 DB使用self::pdo()來返回單例以訪問數據庫。

+0

謝謝,但我已經這樣做了。我的問題是,每次定義使用靜態$ _db變量的進一步方法以避免拋出異常時,您都必須執行空檢查。這可能意味着一些嚴重的性能損失。 – kahoon 2009-09-15 18:21:32

+0

單個空檢查幾乎不是性能問題。如果你想使用這種設計模式,那麼這是你唯一的選擇。你問了一個PHP本來不支持的解決方法;你必須放棄一些東西。 – ryeguy 2009-09-15 18:25:40

+3

我剛剛檢查過,我可以在一臺較舊的雙核筆記本電腦上每秒進行大約1百萬次is_null比較。你真的覺得這很重要嗎?如果可表達性和易用性受到影響,則表現無關緊要。 – ryeguy 2009-09-15 18:46:01

0

使用Singleton模式,而不是靜態的呼叫:

<?php 
class Foo { 

    protected static $_instance; 

    /** 
    * @return Foo 
    */ 
    public static function getInstance() { 
     return (null === self::$_instance)? 
      self::$_instance : 
      self::$_instance = new Foo(); 
    } 

    protected function __construct() { 
     // initialize here 
    } 
} 
0

這是我這樣做的方法。唯一的代價是每次構建時測試$ doneinit靜態成員。

class Foo { 
    private static $doneinit=false; 

    private static init() { 
     // do static initialisation here 

     self::$doneinit=true; 
    } 

    public function __construct() { 
     if (!self::$doneinit) self::init(); 

     // go on to do the rest of construction 
    } 
} 

簡單,並且它保持了課堂上的一切。

3

單身的答案在這裏有一個問題...如果你在創建類的實例之前使用靜態方法...那麼靜態初始化程序沒有運行...所以你可能會說可以運行初始化器在每一個靜態方法......這是真的,但只是獲取和設置靜態變量...我想也可以使用__get和__set魔術功能...這只是一個語言問題,因爲它不支持靜態intialization ...這是可以做到的方式......

文件Hi.php

class Hi{ 
public static $v = "0"; 
} 

Hi::$v= "2"; 
// end of Hi.php file 

簡單的使用以.php文件類...並且執行 類定義之外的靜態初始化...