Php 在不更改数千行代码的情况下创建静态数组

Php 在不更改数千行代码的情况下创建静态数组,php,arrays,static,Php,Arrays,Static,我们有一个类,它包含一个名为$saved的公共数组,该数组包含在方法之间共享所需的大量数据(下面的示例) 实际上有成千上万行这样的代码 问题在于,扩展了Common的类的新实例是在某些方法中创建的,因此当它们访问$saved时,它不会保存相同的数据 解决方案是使$saved成为一个静态变量,但是我无法更改对$this->saved的所有引用,因此我想尝试保持代码相同,但使其表现为静态 下面是我尝试使$this->saved调用静态 class PropertyTest { private

我们有一个类,它包含一个名为
$saved
的公共数组,该数组包含在方法之间共享所需的大量数据(下面的示例)

实际上有成千上万行这样的代码

问题在于,扩展了
Common
的类的新实例是在某些方法中创建的,因此当它们访问
$saved
时,它不会保存相同的数据

解决方案是使
$saved
成为一个静态变量,但是我无法更改对
$this->saved
的所有引用,因此我想尝试保持代码相同,但使其表现为静态

下面是我尝试使
$this->saved
调用静态

class PropertyTest {
    private $data = array();

    public function __set($name, $value) {
        $this->data[$name] = $value;
    }

    public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        return null;
    }

    public function __isset($name) {
        return isset($this->data[$name]);
    }

    public function __unset($name) {
        unset($this->data[$name]);
    }
}

class Common {
    public $saved;
    private static $_instance;

    public function __construct() {
        $this->saved = self::getInstance();
    }

    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new PropertyTest();
            self::$_instance->foo = array();
        }
        return self::$_instance->foo;
    }
}
当设置一个变量时,它似乎不保持静态(下面的测试用例),这就不太管用了

$this->saved
在初始化
User
时为空,并且似乎不是同一个变量,最后的
print\r
仅显示name=>bob的数组


有什么想法吗?

我认为这个实现中有很多问题可能会再次困扰你。但是,在当前的实现中,每次都需要构造一个新实例(尽管是通过静态调用)

相反,使用getInstance()作为单例钩子,并将_构造设为私有,因为您只能从公共类的上下文访问它

像这样:

class Common {
    public $saved;

    private static $_instance;

    private function __construct() {
    }

    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new self();
            ... any other modifications you want to make ....
        }
        return self::$_instance;
    }
}
并且永远不要运行parent::_construct(),而是始终使用getInstance()方法


您可能还想放弃扩展这个单例类的想法。这确实是一个糟糕的反模式,从长远来看可能会导致许多问题。相反,只需维护一个其他类可以读/写的
Common
类。因为它是一个单例,所以您不需要担心注入。

首先,我必须说,在我看来,将实例的属性用作类的属性并不是很好(
$saved
没有声明为
static
,但它的值与所有实例共享)

这是一个工作版本,这是注释代码。基本上,诀窍在于同时使用和


我似乎已经解决了这个问题,通过将
$this->saved
作为一个静态变量的引用,它可以工作

class Common {
    private static $savedData = array();
    public $saved;

    public function __construct() {
        $this->saved =& self::$savedData;
    }
}

在我看来,你需要一个全局变量。你可以把它装扮成一个单身汉,但最终它只是一个全球变量。@jeroen,当人们说全球是多么邪恶,应该如何用单身汉来取代它时,我总是笑。它们都是相同的邪恶XD。@Xeoncross非常正确,尽管我还没有看到没有全局变量的程序/脚本…@fire在我看来,你的主要问题是
$this->data[$name]=$value在扩展自
Common
的类中。因此,如果您使用
Common
中的getter和setter,您将有很大的自由将其更改为您想要的格式。谢谢,但它遇到了与我在上一个代码示例中提供的相同的问题,请在此处查看它的实际操作您应该看到name=>bob rocks!我想我已经解决了它!
class Common {
    public $saved;

    private static $_instance;

    private function __construct() {
    }

    public static function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new self();
            ... any other modifications you want to make ....
        }
        return self::$_instance;
    }
}
class Accumulator implements ArrayAccess {

    private $container = array();
    private static $instance = null;

    private function __construct() {
    }

    public function getInstance() {
        if( self::$instance === null ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }

}


class Common {
    public $saved = null;


    public function __construct() {
        // initialize the "saved" object's property with the singleton
        // that variable can be used with the array syntax thanks to the ArrayAccess interface
        // so you won't have to modify your actual code
        // but also, since it's an object, this local "$this->saved" is a reference to the singleton object
        // so any change made to "$this->saved" is in reality made into the Accumulator::$instance variable
        $this->saved = Accumulator::getInstance();
    }

    public function setUser($data) {
        $this->saved['user_data'] = $data;
    }

    public function getUser() {
        return $this->saved['user_data'];
    }

}


class Template extends Common {

    // you can redeclare the variable or not. Since the property is inherited, IMO you should not redeclare it, but it works in both cases
    // public $saved = null;

    public function __construct() {
        // maybe we can move this initialization in a method in the parent class and call that method here
        $this->saved = Accumulator::getInstance();
    }

}
class Common {
    private static $savedData = array();
    public $saved;

    public function __construct() {
        $this->saved =& self::$savedData;
    }
}