Xwab
Форумыnavigate_nextПрограммирование на PHP

Области хранения данных в реестре
Сообщения
wapmorgan

Базовый класс
<?php

class Registry
{
/**
 * Хранилище
 */
 static private $data = array();




 /**
  * Сохранение значения
  */
 static public function set($name, $value, $space = 'global')
{
self::$data[$space][$name] = $value;

return $value;
}



/**
  * Получение значения
  */
 static public function get($name, $space = 'global')
{
return isset(self::$data[$space][$name]) ? self::$data[$space][$name] : false;
}



/**
 * Очищение всех данных
 */
 static public function clear($space = 'global')
 {
 self::$data[$space] = array();
 
return true;
 }
 
 
 
 /**
  * Проверка на существование
  *
  * @since 19.11.2010
  * @fail Назвать метод isset() невозможно
  */
  static public function is_set($name, $space = 'global')
  {
  return isset(self::$data[$space][$name]);
  }
 
 
 
  /**
  * Дамп данных
  *
  * @since 19.11.2010
  */
  static public function dump($space = 'global')
  {
  return self::$data[$space];
  }
 
 
}

?>
Производные классы, для хранения данных в других областях видимости строятся по подобию
<?php

class MF_Registry extends Registry
{
static private $space = 'MF';

static public function set($var_name, $var_set){return parent::set($var_name, $var_set, self::$space);}

static public function get($var_name){return parent::get($var_name, self::$space);}
}

?>
Возможно ли усовершенствовать такой механизм?

28 Ноя 2010, 23:47
OZ_

Я хоть не Дональд Кнут, и моё мнение не абсолютная истина, но, раз уж прозвучал вопрос...

Итак, первое, самое очевидное - в переменной $space нет никакого смысла. Различные имена реестров уже на 100% достаточно разделяют области видимости.

Дальше. Всё, что не может быть подсказано IDE,
a) Может стать причиной опечатки
b) Не может быть проверено до выполнения, что увеличивает количество "подводных камней" - ошибок, которые проявляются не сразу при запуске, а позже, в процессе использования.

Поэтому методы set и get использовать в текущем виде нельзя (имена полей передаются в виде строк).

Честно говоря, к реестру, на мой взгляд, не применима инкапсуляция, поскольку реестр не является объектом, обрабатывающим свои свойства. В реестре вполне можно объявить public свойства и использовать их. Всё равно любой класс может вызвать и get и set и никаких проверок соответствию типа ни в get ни в set быть не может, поскольку тип всех переменных сразу не задашь. А вот при получении данных из реестра, объект очень легко может проверить соответствие типа, что он и должен сделать.

Однако, если уж хочется именно соблюсти, то можно создавать методы с явными именами, вроде "setNameOfProperty" и "getNameOfProperty".
Это кажется сложным и не универсальным, но, учтите, что реестр будет использовать только само приложение! Никакой из объектов не должен обращаться к реестру напрямую.
Из реестра будут только передаваться значения при создании объектов.

Например, приложение может создать
$controller=new MainController(MF_Registry::$params);
это правильный вариант.
А когда объект MainController сам обращается к реестру по имени, это неправильный вариант. Никто из объектов не должен знать о существовании реестра. Иначе все они станут зависимы от реестра. То есть, при изменении реестра, нерабочими станут ВСЕ объекты, которые использовали его. Это недопустимо.

Так вот, я отвлёкся.
Если не возводить здесь не нужную (на мой взгляд) инкапсуляцию, можно просто объявить нужные имена полей и всё, реестр готов.
С инкапсуляцией эти поля будут protected и всем им нужно будет создать getter и setter. Но это уже детали.
А в каждом расширяющем классе просто добавлять свои поля.
Кстати, чтобы расширяющий класс мог использовать свойство родителя, оно должно быть protected, не private.

По поводу реестра в целом - не храните в реестре функции, храните только переменные. Ваши объекты не будут знать имя реестра, значит им нужно будет передать ссылку на функцию. Это возможно с обычным объектом (передать ссылку на экземпляр), но не со статическим. Поэтому хранить функции нужно именно в обычных (динамических) классах.

29 Ноя 2010, 0:35
Replikon

Ну и зачем собственно так задрачиваться?  у меня в реестре только 2 метода: Set и Get. И то Get возвращает не одно свойство, а массив со свойствами. Принимаю дескриптор реестра в конструкторе, назначаю ему переменную и потом работаю с этим массивом.
Области видимости... Какие еще области видимости, они нахер не нужны.

29 Ноя 2010, 14:05
wapmorgan

3, я собственно, использую статические методы именно для того что бы не пришлось каждый раз передавать объект реестра.

01 Дек 2010, 15:19
wapmorgan

2, у меня [пока что] монолитная структура.
Имена областей хранения (то бишь $spac'ы) нужны для отделения областей.
Цитата:
"Кстати, чтобы расширяющий класс мог использовать свойство родителя, оно должно быть protected, не private."

В производных классах не нужно использование свойства $data (если ты про него).
Цитата:
"Итак, первое, самое очевидное - в переменной $space нет никакого смысла. Различные имена реестров уже на 100% достаточно разделяют области видимости."

Производные класса обращаются к универсальным сеттерам/геттерам, передавая им и область видимости, из которой/в которую помещаются данные.

01 Дек 2010, 15:23
OZ_

Morgan,
1) разные имена реестра более чем достаточно разделяют области видимости. $space не нужна.
2)
"В производных классах не нужно использование свойства $data"
Да, а в методах get/set оно не используется разве? Private - значит доступно только родительскому классу.

3)
"Производные класса обращаются к универсальным сеттерам/геттерам"
Вместо цитирования ты мог написать, почему тебе хочется делать именно так, даже после того, как я рассказал, почему это не самый лучший вариант.

В данный момент твой реестр абсолютно ничем не отличается от массива $GLOBALS.
Обычный реестр в виде статического класса мог, хотя бы, помочь не делать опечатки в именах свойств, а этот и того не делает.

Напиши, для чего нужен реестр, как он будет использоваться - может подскажем чего. Хотя ты не особо слушаешь советы

01 Дек 2010, 16:09
wapmorgan

6, производные классы обращаются к методам базового класса, больше они ничего не делают.
Производные классы, напрямую, никакие дейсвия с массивом не производят.

01 Дек 2010, 17:43
wapmorgan

Цитата:
"Обычный реестр в виде статического класса мог, хотя бы, помочь не делать опечатки в именах свойств, а этот и того не делает."

?

Цитата:
" ничем не отличается от массива $GLOBALS."

Отличается.

Есть базовый класс, Registry.
От него производный - MF_Registry.

В Registry я храню такие данные как, объект для работы с бд/шаблонизатором.
В MF_Registry я храню системные данные.
Данные о модулях, данные роутинга.
Т.е. в MF_Registry хранятся данные, которые используются только во внутренностях системы.

01 Дек 2010, 17:47
OZ_

Morgan, абсолютно тоже самое Вы можете хранить в массиве $GLOBALS, разницы нет никакой.

"Т.е. в MF_Registry хранятся данные, которые используются только во внутренностях системы."
Это правильный подход. Главное не забывать, что внутри всех классов не должно быть обращения к этому реестру по имени.

Реестр начинает отличатся от $GLOBALS тогда, когда у статического класса появляются именованные поля (свойства), а не какие-то призрачные get/set. Если уж IDE не пользуетесь и автокомплит не аргумент - подумайте о возможности отправлять значение по ссылке.

01 Дек 2010, 19:00
XsErG

$GLOBALS это системная переменная, трогать ее - плохо!!! Пусть себе живет. Registry с "именнованными полями" в похапе получается в одном варианте, когда он не статичен, а значит мы теряем в глобальной области видимости. А значит нужно строить огромную цепочку передач регистра в объекты и 100% где то нужно его похерить и вырвимозгом заниматься. А еще.. а еще мы юзаем няшку в виде уже не призрачных, а магических __get и __set, ведь вы же хотите иметь не только жестко заданные параметры? Потому что ЖЗП - плохо! И снова имеем то, что имеем ide не будут комплитить обработку __get/__set.
З.Ы. Усовершенствовать именно это механизм можно аж так:
{return parent::set($var_name, $var_set, __CLASS__);}
Только зачем нам два регистра со всякой туфтой, которая прекрасно ложиться в один?
Почему бы не сделать один суперкласс ( скажем Component) который будет обрабатывать что-то вроде $this->db у всех потомков и выдавать им коннект к бд? или $this->template будет выдавать всем потомкам один и тот же шаблонизатор. А вот эти куча регистров-запутайсамсебя вам не нужны


__________
посл.ред. 02 Дек 2010, 1:11; всего 1 раз 02 Дек 2010, 1:00
Ответить на тему