2012-10-26 67 views
3

我創建實現了ArrayAccess一類,我添加它來阻止功能寫入的動作:防止類解封在PHP

$Obj->Add("key","something"); 
$Obj->Add("key2","something2"); 
$Obj->SetReadOnly(); // sets read only property 
unset($Obj["key2"]); // throws error, object is readonly 

但是,我想阻止解封對象太:

unset($Obj); 

我能做到嗎?我聽到了建議。 感謝您的幫助!

+0

@FoolishSeth - 我假設他使用'__unset()'魔術方法。 – Spudley

+0

我剛剛意識到它可能在ArrayAccess實現中。 – FoolishSeth

+2

爲什麼要防止頂級未設置?這似乎是一個危險和混亂的想法。 – FoolishSeth

回答

2

我無法想象任何你真的想要這樣做的情況。我也可以想象這樣做會在所有對象被銷燬時在腳本終止時導致嚴重的問題。 PHP手冊說,在析構函數拋出異常如下:

注:

試圖從析構函數(稱爲時間腳本終止 )拋出一個異常會導致致命錯誤。

上面的語句意味着如果你不在腳本終止階段,你可以拋出一個異常,所以也許下面是可能的。

public function __destruct() 
{ 
    if ($this -> isReadOnly()) 
    { 
     throw new Exception ('Class is read-only'); 
    } 
} 

但是,正如手冊指出的那樣,這將在腳本關閉期間觸發致命錯誤。

我真的不能看到任何想要防止對象破壞的要點。應該由程序員來管理對象的生命週期。

1

您無法控制未設置的變量名稱,因爲這些名稱在技術上並不是引用對象的一部分。考慮以下幾點:

$a = new MyObject(); 
$b = $a; 

現在你有引用同一個對象。有沒有區別使用$a$b之間,因爲在PHP對象總是通過引用(即你不必在第二行中做$b =& $a)。所以$a$b實質上是同一個對象;不設置$a不會破壞對象,以及不設置$b不會破壞它; 全部引用需要在對象被銷燬之前取消設置。

1

unset()實際上並沒有破壞一個對象,如果這就是你想要阻止的。

只有當對象的所有引用都未被設置或不在範圍內時,對象纔會被銷燬。即使這樣,它也不會發生,直到垃圾收集器運行。

所以,如果你有一些你擔心的代碼會騷擾你的對象,那麼你已經做了很好的工作,使它成爲不變的只讀邏輯。

比方說,你有

$Obj = gotMyObjectSomehow(); 

,你需要將它傳遞給你不想取消設置$的OBJ一個其他一些代碼。只要代碼在函數內部調用,就沒有什麼可關注的。如果你打電話

someFunction($Obj); 

,讓我們說,功能會取消它傳遞的參數在

function someFunction($anObj) { 
    unset($anObj); 
} 

然後你原來$Obj變量仍將設置。

該函數創建引用原始對象的第二個變量,並在其自己的作用域中使用該變量。

0

我不認爲你可以做你要求的 - 不可能阻止一個變量被設置爲這樣。

但是,上面的評論讓我想到了。你說:

....主意,如果你想防止取消設置系統變量的第三方擴展

所以,如果我理解你的權利,你在這裏的目的是保證,而第三方代碼(即您的軟件)正在使用中,與它相關的所有變量是否仍然存在?

現在您還沒有詳細說明該系統中有哪些變量。我們在問題中看到一個對象,但是可能肯定還有比這更多的東西?我猜你已經有了一堆捆綁在一起的東西,對吧?這將有助於解決這些問題,以提供更多的背景;你所要求的實際情況是不可能的,但對你想達到的目標有一些瞭解,我們可以提出替代方案。

好的。所以我的建議是:創建你的對象作爲單身人士。這是純粹主義者經常皺起眉頭,但可能適用於這種情況,具體取決於你在做什麼。這裏的優點是你可以在類方法中封裝對象的所有訪問,這意味着使用你的代碼的開發人員無法訪問該對象的主副本以取消它。

一個單是這樣的:

<?php 
class mySingletonClass { 
    private static $masterObject=null; 

    public static function getInstance() { 
     if(!isset(self::$masterObject)) { 
      self::$masterObject = new self; 
     } 
     return self::$masterObject; 
    } 

    private function __construct() { 
     //your existing constructor, as it already exists, but marked as private. 
    } 

    //...and all the other methods as you already have them. 
} 

類構造方法是私有的,所以只能從類中的方法訪問。因此,您不能再做new classname()。你可以得到這個類的一個對象的唯一方法是從靜態的getInstance()方法中獲取它。關鍵是這個方法總是返回對象的相同副本。

$obj = mySingletonClass::getInstance(); 
unset($obj); 
$obj = mySingletonClass::getInstance(); //will give the exact same object as the first time. 

如果需要,可以取消設置,但原始對象仍然存在,仍然可以訪問。任何其他類都可以使用該方法從程序中的任何位置獲取同一對象的相同副本。這是一個不可摧毀的全球變量。

單身人士通常用於程序的主數據庫連接對象,但它可能對您有用。

我希望有幫助。這是我能想到接近你想要的唯一方法。