Если вы действительно должны это сделать, лучший способ - это перегрузить ArrayObject, который позволяет поддерживать поддержку итераций (foreach), которая все равно будет проходить через все ваши свойства.
Я отмечаю, что вы сказали «без использования массива», и я просто хочу заверить вас, что, хотя технически массив используется в фоновом режиме, вы НИКОГДА НЕ ДОЛЖНЫ ВИДЕТЬ. Вы получаете доступ ко всем свойствам через -> Properyname или foreach ($ class в $ name => $ value).
Вот пример, над которым я работал вчера, обратите внимание, что он также СИЛЬНО ТИП. Таким образом, свойства, помеченные как «целое», выдают ошибку, если вы попытаетесь указать «строку».
Вы можете удалить это, конечно.
Существует также функция-член AddProperty (), хотя это не продемонстрировано в примере. Это позволит вам добавить свойства позже.
Пример использования:
$Action = new StronglyTypedDynamicObject("Action",
new StrongProperty("Player", "ActionPlayer"), // ActionPlayer
new StrongProperty("pos", "integer"),
new StrongProperty("type", "integer"),
new StrongProperty("amount", "double"),
new StrongProperty("toCall", "double"));
$ActionPlayer = new StronglyTypedDynamicObject("ActionPlayer",
new StrongProperty("Seat", "integer"),
new StrongProperty("BankRoll", "double"),
new StrongProperty("Name", "string"));
$ActionPlayer->Seat = 1;
$ActionPlayer->Name = "Doctor Phil";
$Action->pos = 2;
$Action->type = 1;
$Action->amount = 7.0;
$Action->Player = $ActionPlayer;
$newAction = $Action->factory();
$newAction->pos = 4;
print_r($Action);
print_r($newAction);
class StrongProperty {
var $value;
var $type;
function __construct($name, $type) {
$this->name = $name;
$this->type = $type;
}
}
class StronglyTypedDynamicObject extends ModifiedStrictArrayObject {
static $basic_types = array(
"boolean",
"integer",
"double",
"string",
"array",
"object",
"resource",
);
var $properties = array(
"__objectName" => "string"
);
function __construct($objectName /*, [ new StrongProperty("name", "string"), [ new StrongProperty("name", "string"), [ ... ]]] */) {
$this->__objectName = $objectName;
$args = func_get_args();
array_shift($args);
foreach ($args as $arg) {
if ($arg instanceof StrongProperty) {
$this->AddProperty($arg->name, $arg->type);
} else {
throw new Exception("Invalid Argument");
}
}
}
function factory() {
$new = clone $this;
foreach ($new as $key => $value) {
if ($key != "__objectName") {
unset($new[$key]);
}
}
// $new->__objectName = $this->__objectName;
return $new;
}
function AddProperty($name, $type) {
$this->properties[$name] = $type;
return;
if (in_array($short_type, self::$basic_types)) {
$this->properties[$name] = $type;
} else {
throw new Exception("Invalid Type: $type");
}
}
public function __set($name, $value) {
self::sdprintf("%s(%s)\n", __FUNCTION__, $name);
$this->check($name, $value);
$this->offsetSet($name, $value);
}
public function __get($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, $name);
$this->check($name);
return $this->offsetGet($name);
}
protected function check($name, $value = "r4nd0m") {
if (!array_key_exists($name, $this->properties)) {
throw new Exception("Attempt to access non-existent property '$name'");
}
$value__objectName = "";
if ($value != "r4nd0m") {
if ($value instanceof StronglyTypedDynamicObject) {
$value__objectName = $value->__objectName;
}
if (gettype($value) != $this->properties[$name] && $value__objectName != $this->properties[$name]) {
throw new Exception("Attempt to set {$name} ({$this->properties[$name]}) with type " . gettype($value) . ".$value__objectName");
}
}
}
}
class ModifiedStrictArrayObject extends ArrayObject {
static $debugLevel = 0;
/* Some example properties */
static public function StaticDebug($message) {
if (static::$debugLevel > 1) {
fprintf(STDERR, "%s\n", trim($message));
}
}
static public function sdprintf() {
$args = func_get_args();
$string = call_user_func_array("sprintf", $args);
self::StaticDebug("D " . trim($string));
}
protected function check($name) {
if (!array_key_exists($name, $this->properties)) {
throw new Exception("Attempt to access non-existent property '$name'");
}
}
//static public function sget($name, $default = NULL) {
/******/ public function get ($name, $default = NULL) {
self::sdprintf("%s(%s)\n", __FUNCTION__, $name);
$this->check($name);
if (array_key_exists($name, $this->storage)) {
return $this->storage[$name];
}
return $default;
}
public function offsetGet($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
$this->check($name);
return call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function offsetSet($name, $value) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
$this->check($name);
return call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function offsetExists($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
$this->check($name);
return call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function offsetUnset($name) {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
$this->check($name);
return call_user_func_array(array(parent, __FUNCTION__), func_get_args());
}
public function __toString() {
self::sdprintf("%s(%s)\n", __FUNCTION__, $name);
foreach ($this as $key => $value) {
$output .= "$key: $value\n";
}
return $output;
}
function __construct($array = false, $flags = 0, $iterator_class = "ArrayIterator") {
self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args()));
parent::setFlags(parent::ARRAY_AS_PROPS);
}
}