Более подробно рассматривая вашу проблему, вы можете создать класс, который моделирует концепцию многомерного объекта.
Решение, которое я публикую, не распространяется от ArrayObject
для архивации целейВы упоминаете.Поскольку вы пометили свой вопрос как oop, я думаю, что важно усилить разделение способа хранения состояния объекта и способа доступа к нему.
Надеюсь, это поможет вам архивировать то, что вам нужно!
Из того, что вы сказали, многомерный объект - это объект, который:
- обрабатывает несколько уровней вложенной информации
- он делает это, предоставляя доступ для чтения / записи кинформация через свойства
- хорошо ведет себя при доступе к неопределенным свойствам.Это означает, что, например, вы делаете следующее для пустого экземпляра:
$config->database->host = 'localhost'
уровни database
и host
инициализируются автоматически, а host
вернет 'localhost'
при запросе. - в идеале, будет инициализироваться из ассоциативных массивов (поскольку вы уже можете разбирать в них файлы конфигурации)
Предлагаемое решение
Итак, как эти функции могут бытьреализован?
Второй прост: использование PHP __get
и __set
методов.Они будут вызываться всякий раз, когда выполняется чтение / запись для недоступного свойства (которое не определено в объекте).Хитрость будет заключаться в том, чтобы не объявлять какое-либо свойство и обрабатывать операции свойства с помощью этих методов и отображать имя свойства beign, принимаемое как ключ, в ассоциативный массив, используемый в качестве хранилища.В основном они предоставят интерфейс для доступа к информации, хранящейся внутри.
Для третьего нам нужен способ создания нового уровня вложенности при получении необъявленного свойства.Ключевым моментом здесь является понимание того, что возвращаемое значение для свойства должно быть многомерным объектом, поэтому из него можно также создавать дополнительные уровни вложенности: всякий раз, когда нас просят о свойстве, имя которого отсутствует во внутреннем массиве,мы свяжем это имя с новым экземпляром MultiDimensionalObject
и вернем его.Возвращенный объект также сможет обрабатывать определенные или неопределенные свойства.
Когда записывается необъявленное свойство, все, что нам нужно сделать, это присвоить его имя со значением, предоставленным во внутреннем массиве.
Четвертый прост (см. Реализацию __construct
).Нам просто нужно убедиться, что мы создаем MultiDimensionalObject
, когда значение свойства является массивом.
Наконец, первое: то, как мы обрабатываем вторую и третью функции, позволяет нам читать и записывать свойства (объявленные и незаявленные) на любом уровне вложенности.Вы можете сделать что-то вроде $config->foo->bar->baz = 'hello'
на пустом экземпляре, а затем успешно запросить $config->foo->bar->baz
.
Важно Обратите внимание, что MultiDimensionalObject
вместо beign сам массив это составленный с массивом, позволяющим вам при необходимости изменить способ хранения состояния объекта.
Реализация
/* Provides an easy to use interface for reading/writing associative array based information */
/* by exposing properties that represents each key of the array */
class MultiDimensionalObject {
/* Keeps the state of each property */
private $properties;
/* Creates a new MultiDimensionalObject instance initialized with $properties */
public function __construct($properties = array()) {
$this->properties = array();
$this->populate($properties);
}
/* Creates properties for this instance whose names/contents are defined by the keys/values in the $properties associative array */
private function populate($properties) {
foreach($properties as $name => $value) {
$this->create_property($name, $value);
}
}
/* Creates a new property or overrides an existing one using $name as property name and $value as its value */
private function create_property($name, $value) {
$this->properties[$name] = is_array($value) ? $this->create_complex_property($value)
: $this->create_simple_property($value);
}
/* Creates a new complex property. Complex properties are created from arrays and are represented by instances of MultiDimensionalObject */
private function create_complex_property($value = array()){
return new MultiDimensionalObject($value);
}
/* Creates a simple property. Simple properties are the ones that are not arrays: they can be strings, bools, objects, etc. */
private function create_simple_property($value) {
return $value;
}
/* Gets the value of the property named $name */
/* If $name does not exists, it is initilialized with an empty instance of MultiDimensionalObject before returning it */
/* By using this technique, we can initialize nested properties even if the path to them don't exist */
/* I.e.: $config->foo
- property doesn't exists, it is initialized to an instance of MultiDimensionalObject and returned
$config->foo->bar = "hello";
- as explained before, doesn't exists, it is initialized to an instance of MultiDimensionalObject and returned.
- when set to "hello"; bar becomes a string (it is no longer an MultiDimensionalObject instance) */
public function __get($name) {
$this->create_property_if_not_exists($name);
return $this->properties[$name];
}
private function create_property_if_not_exists($name) {
if (array_key_exists($name, $this->properties)) return;
$this->create_property($name, array());
}
public function __set($name, $value) {
$this->create_property($name, $value);
}
}
Демо
Код: var_dump (new MultiDimensionalObject ());
Результат:
object(MultiDimensionalObject)[1]
private 'properties' =>
array
empty
Код:
$data = array( 'database' => array ( 'host' => 'localhost' ) );
$config = new MultiDimensionalObject($data);
var_dump($config->database);
Результат:
object(MultiDimensionalObject)[2]
private 'properties' =>
array
'host' => string 'localhost' (length=9)
Код:
$config->database->credentials->username = "admin";
$config->database->credentials->password = "pass";
var_dump($config->database->credentials);
Результат:
object(MultiDimensionalObject)[3]
private 'properties' =>
array
'username' => string 'admin' (length=5)
'password' => string 'pass' (length=4)
Код:
$config->database->credentials->username;
Результат:
admin