防止类在php中不稳定

防止类在php中不稳定,php,Php,我创建了一个实现ArrayAccess的类,并将其添加为防止写入操作的函数: $Obj->Add("key","something"); $Obj->Add("key2","something2"); $Obj->SetReadOnly(); // sets read only property unset($Obj["key2"]); // throws error, object is readonly 但是,我也要防止对象不稳定: unset($Obj);

我创建了一个实现ArrayAccess的类,并将其添加为防止写入操作的函数:

 $Obj->Add("key","something");
 $Obj->Add("key2","something2");
 $Obj->SetReadOnly(); // sets read only property
 unset($Obj["key2"]); // throws error, object is readonly
但是,我也要防止对象不稳定:

 unset($Obj);
我能做到?我听到建议。
谢谢你的帮助

我无法想象在什么情况下你会真的想这么做。我还可以想象,当所有对象都被销毁时,这样做会导致脚本终止时出现严重问题。PHP手册对在析构函数中引发异常做了如下说明:

注:

试图从析构函数(在时间中调用)引发异常 脚本终止)导致致命错误

上面的语句意味着,如果不在脚本终止阶段,则可以抛出异常,因此可能会出现以下情况

public function __destruct ()
{
    if ($this -> isReadOnly ())
    {
        throw new Exception ('Class is read-only');
    }
}
但是,正如手册所指出的,这将在脚本关闭期间触发致命错误


老实说,我看不出想要阻止物体破坏有什么意义。应该由程序员来管理对象生命周期

您无法控制未设置的变量名,因为从技术上讲,这些名称不是所引用对象的一部分。考虑以下事项:

$a = new MyObject();
$b = $a;
现在您有两个对同一对象的引用。使用
$a
$b
之间没有区别,因为在PHP中,对象总是通过引用使用(即,您不必在第二行中执行
$b=&$a
)。所以
$a
$b
本质上是同一个对象;取消设置
$a
不会破坏对象,取消设置
$b
也不会破坏对象;在销毁对象之前,所有引用都需要取消设置。

unset()
实际上不会销毁对象,如果您正试图阻止的话

只有当对象的所有引用都已取消设置或不再在作用域中时,对象才会被销毁。即使这样,在垃圾收集器运行之前,它也不会发生

因此,如果您有一些担心会干扰对象的代码,那么您已经很好地将其与只读逻辑保持不变

假设你有

$Obj = gotMyObjectSomehow();
您需要将它传递给一个不想取消设置$Obj的其他代码。只要在函数中调用该代码,就没有什么可担心的。如果你打电话

someFunction($Obj);
假设函数取消了它传入的参数的设置

function someFunction($anObj) {
    unset($anObj);
}
然后仍将设置原始的
$Obj
变量


该函数创建引用原始对象的第二个变量,并在其自己的范围内使用该变量。

我认为您无法按要求执行操作-无法防止像这样取消设置变量

然而,你上面的评论让我思考。你说:

。。。。如果您想在第三方扩展中防止未设置的系统变量

因此,如果我理解正确,您的目标是确保在使用第三方代码(即您的软件)时,与之相关的所有变量保持不变

现在您还没有详细说明这个系统中有哪些变量。我们在问题中看到了一个对象,但想必还有更多的对象?我猜你有很多东西可以联系在一起,对吗?在这类问题中,提供更多的上下文会有所帮助;你真正想要的东西是不可能的,但是如果你对你想要达到的目标有一点了解,我们可以想出其他的选择

好的。因此,我的建议是:将对象创建为单例。这通常是不赞成的纯粹主义者,但可能在这种情况下工作得很好,具体取决于你在做什么。这里的美妙之处在于,您可以将对对象的所有访问封装在类方法中,这意味着使用您的代码的开发人员没有访问对象主副本的权限来取消设置它

单身汉的工作原理如下:

<?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.
}
如果需要,可以取消设置它,但原始对象仍然存在,并且仍然可以访问。您的任何其他类都可以使用该
getInstance()
方法从程序中的任何位置获取同一对象的相同副本。这是一个不可摧毁的全局变量

单例通常用于程序的主数据库连接对象,但在这里它可能是一种有用的模式


我希望这有帮助。这是我能想到的接近你想要的东西的唯一方法。

@傻瓜塞思--我想他在使用
\u unset()
魔术方法。我刚刚意识到它可能在ArrayAccess实现中。你为什么要阻止顶级unset?这似乎是一个危险且令人困惑的想法。当脚本结束时,所有变量都将
unset
抛出错误。@如果要在第三方扩展中防止unset系统变量,那么愚蠢设置不是一个危险的想法
$obj = mySingletonClass::getInstance();
unset($obj);
$obj = mySingletonClass::getInstance();  //will give the exact same object as the first time.