我们有一个包含名为 $saved
的公共(public)数组的类,该数组包含在方法之间共享所需的大量数据(下面的示例)...
class Common {
public $saved = array();
public function setUser($data) {
$this->saved['user_data'] = $data;
}
public function getUserID() {
return $this->saved['user_data']['id'];
}
}
像这样工作的代码实际上有数千行。
问题是扩展 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;
}
}
当设置一个似乎不保持静态的变量时,这不太有效(下面的测试用例)...
class Template extends Common {
public function __construct() {
parent::__construct();
$this->saved['user_data'] = array('name' => 'bob');
$user = new User();
}
}
class User extends Common {
public function __construct() {
parent::__construct();
$this->saved['user_data']['name'] .= " rocks!";
$this->saved['user_data']['id'] = array(400, 10, 20);
}
}
$tpl = new Template();
print_r($tpl->saved['user_data']);
$this->saved
在 User
初始化时为空,似乎不是同一个变量,最后的 print_r
而已显示 name => bob 的数组。
有什么想法吗?
最佳答案
首先,我不得不说,IMO,将实例的属性用作类的属性并不是那么好($saved
未声明为static
但它的值与所有实例共享)。
这是一个工作版本 http://codepad.org/8hj1MOCT ,这里是注释代码。基本上,诀窍在于同时使用 ArrayAccess interface和 singleton pattern .
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();
}
}
关于php - 无需更改数千行代码即可创建静态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10706040/