ФорумПрограммированиеPHP для идиотовPHP и ООП → Динамически сделать свойство приватным

Динамически сделать свойство приватным

  • Lirck

    Сообщения: 1658 Репутация: N Группа: Джедаи

    Spritz 1 февраля 2009 г. 14:32

    Возможно ли это? Например есть класс Test, после заполнения свойства, нужно сделать его приватным (чтобы нельзя было изменять):

    $test = new Test();
    $test->config = 'config';

    // Как то делаем свойство config приватным

    echo $test->config; // Ошибка


    P.S. При этом, свойство config явно не указано в классе Test.

    Вот класс где это используется:

    // Ядро
    // $_instance - экземпляр класса
    // $_vars - массив переменных
    class Core
    {
    private static $_instance = null;
    private $_vars = array();
    private $_config = array();

    // Создание экземпляра класса
    public static function instance()
    {
    if (self::$_instance == null)
    self::$_instance = new self();
    return self::$_instance;
    }

    // Функция автозагрузки
    // $file - файл
    public static function autoload($file)
    {
    if (isset($this->_config['core']['dirs']))
    {
    foreach ($this->_config['core']['dirs'] as $dir)
    {
    if (is_readable($dir . $file . '.php'))
    {
    include_once $dir . $file . '.php';
    break;
    }
    }
    }
    }

    // Получение переменной
    // $var - имя переменной
    public function __get($var)
    {
    if (isset($this->_vars[$var]))
    return $this->_vars[$var];
    }

    // Присваивание значения
    // $var - имя переменной
    // $val - значение
    public function __set($var, $val)
    {
    if (!isset($this->_vars[$var]))
    {
    if (is_object($val))
    {
    $val->__core = self::instance();
    $val->__config = $this->_config[$var];
    }
    $this->_vars[$var] = $val;
    }
    }

    public function config($array)
    {
    $this->_config = $array;
    }

    // Запрещяем вызывать эти методы
    private function __construct() {}
    private function __clone() {}
    }

    // Регистрируем функцию автозагрузки
    spl_autoload_register(array('Core', 'autoload'));

    class Test {}
    $config['test']['123'] = 'zzz';
    Core::instance()->config($config);
    Core::instance()->test = new Test();
    Core::instance()->test->__config['123'] = 'xxx'; // Должна быть ошибка (нельзя переопределять свойство)
    print_r(Core::instance()->test);
  • Timur

    Сообщения: 1068 Репутация: N Группа: Джедаи

    Spritz 1 февраля 2009 г. 15:13, спустя 40 минут 23 секунды

    aivee, а зачем?

    Ну можно поиграться с перегрузкой
    <?php
    class Foo
    {
       /**
        * Массив "скрытых" свойств
        */
       private $properties = array();
       
       /**
        * Добавляет новое свойство key с заданным значением value. Если
        * такое свойство уже существует, бросает исключение
        */
       public function __set($key, $value)
       {
           if (array_key_exists($key, $this->properties)) {
               throw new Exception("Property '$key' is already installed");
           }
           $this->properties[$key] = $value;
       }
       
       /**
        * При попытке получить значения свойства выбрасывает исключение
        */
       public function __get($key)
       {
           if (array_key_exists($key, $this->properties)) {
               throw new Exception("Cannot access private property Foo::$$key");
           }
       }
    }

    // Test #1
    try {
       $foo = new Foo();
       $foo->bar = 'a';
       $foo->bar = 'b';
    } catch (Exception $e) {
       echo $e->getMessage() . '<br />';
    }

    // Test #2
    try {
       $foo = new Foo();
       $foo->bar = 'a';
       echo $foo->bar;
    } catch (Exception $e) {
       echo $e->getMessage() . '<br />';
    }
    ?>


    нужно сделать его приватным (чтобы нельзя было изменять)

    так всё-таки приватным, или только для чтения? В коде сделано именно приватном, если нужно только для чтения, то замени метод __get():

        public function __get($key)
    {
    if (! array_key_exists($key, $this->properties)) {
    throw new Exception("Undefined property Foo::$$key");
    }
    return $this->properties[$key];
    }
  • Lirck

    Сообщения: 1658 Репутация: N Группа: Джедаи

    Spritz 1 февраля 2009 г. 15:15, спустя 2 минуты 23 секунды

    Дело в том, что нельзя изменять код класса Test. Я выше дополнил.
    Или ну его нафиг, оставить всё как есть? Только незнаю, нормально ли это, что конфиги классов можно будет изменять по ходу выполнения приложения?
  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz 1 февраля 2009 г. 15:54, спустя 38 минут 34 секунды

    aivee, вау, чувак, растеш на глаза
    я бы тебе выдал премию самого толкового нуба на форуме и перевел в почетные ламеры))

    есть вариант при котором ты сделаешь реальные сетеры и гетеры, то есть


    class Test{
    privat $a = array();
    public function set($name, $value){
    $this->a[$name] = $value;
    }
    }

    $test = new Test();
    $test->set('name','value');

  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz 1 февраля 2009 г. 15:55, спустя 1 минуту 14 секунд

    Timur,
    "Undefined property Foo::$$key"

    это глупость
  • Lirck

    Сообщения: 1658 Репутация: N Группа: Джедаи

    Spritz 1 февраля 2009 г. 15:57, спустя 1 минуту 56 секунд


    aivee, вау, чувак, растеш на глаза
    я бы тебе выдал премию самого толкового нуба на форуме и перевел в почетные ламеры))

    есть вариант при котором ты сделаешь реальные сетеры и гетеры, то есть


    class Test{
    privat $a = array();
    public function set($name, $value){
    $this->a[$name] = $value;
    }
    }

    $test = new Test();
    $test->set('name','value');




    Не подходит, так как нельзя изменять код класса Test. Ладно, оставлю всё как есть сейчас.
    Только незнаю, нормально ли это, что конфиги классов можно будет изменять по ходу выполнения приложения?
  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz 1 февраля 2009 г. 16:00, спустя 3 минуты 26 секунд

    есть еще один вопрос может кто знает

    есть класс наследованый от класса с публичным конструктором

    class MyArrayObject extends ArrayObject{}


    нужно сделать из него синглтон
    как известно менять модификатор приватности нельзя

    class MyArrayObject extends ArrayObject{
    private function __construct(){}
    }


    вопрос как сделать синглтон
  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz 1 февраля 2009 г. 16:02, спустя 1 минуту 23 секунды

    а я думал код твой… а ты просто разметил обьяву…
  • Lirck

    Сообщения: 1658 Репутация: N Группа: Джедаи

    Spritz 1 февраля 2009 г. 16:06, спустя 4 минуты 14 секунд


    есть еще один вопрос может кто знает

    есть класс наследованый от класса с публичным конструктором

    class MyArrayObject extends ArrayObject{}


    нужно сделать из него синглтон
    как известно менять модификатор приватности нельзя

    class MyArrayObject extends ArrayObject{
    private function __construct(){}
    }


    вопрос как сделать синглтон


    Мб в instance написать parent::__construct() или как то так. Лучше на мой вопрос ответьте =)))
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 1 февраля 2009 г. 16:10, спустя 4 минуты

    CTAPbIu_MABP, если я правильно понял, ты не хочешь дать вызывать конструктор? если так, то просто сделай в нем throw new excpetion)
    Сапожник без сапог
  • Lirck

    Сообщения: 1658 Репутация: N Группа: Джедаи

    Spritz 1 февраля 2009 г. 18:04, спустя 1 час 54 минуты 12 секунд

    Чувствую, без изменения класса Test - это сделать нереально. Так что добавил в класс Test метод configure, который заполняет приватное свойство _config.

    class Configurator
    {
    protected $config = null;

    public function configure($arr)
    {
    if ($this->config == null)
    $this->config = $arr;
    }
    }

    class Test extends Configurator
    {
    public function hello()
    {
    print_r($this->config);
    }
    }

    $test = new Test();
    $config['123'] = '321';
    $test->configure($config);
    $test->hello();
  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz 2 февраля 2009 г. 0:33, спустя 6 часов 28 минут 26 секунд

    phpdude, да но класс то создавать надо! тоесть надо бросать по условию и вот тут проблема…
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 2 февраля 2009 г. 6:32, спустя 5 часов 59 минут 4 секунды


    phpdude, да но класс то создавать надо! тоесть надо бросать по условию и вот тут проблема…
    и в чем проблема?)
    static $instance;
    function __construct()
    {
    if(!self::$isCreated)
    {
    self::$instance = $this;
    }
    else
    {
    killall();
    }
    }
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!