Немного не понятно с __set и __get

RASAMAHA

Новичок
Понадобилась мне реализация класса с несуществующими свойствами. Дошло дело до __set и __get.
Нашел пример:
PHP:
class Example   
{  
    public function __set($name, $value)  
    {  
       $this->$name = $value;   
    }  
      
    public function __get($name)  
    {  
        return $this->$name;   
    }      
}  
   
    $obj = new Example();  
    $obj->variable = 'Меня в классе нет';  
    echo $obj->variable;
Куда проще, но у меня вопрос вот в чем, на моей версии 5.3.5 работает так же прекрасно следующий код:
PHP:
class Example   
{  

}  
    $obj = new Example();  
    $obj->variable = 'Not';  
    echo $obj->variable;
Те есть в классе нет свойства variable, но код все равно работает без ошибок и выводит Not.
Где-то наверно затупил(
 

RASAMAHA

Новичок
А на практике какая разница в этом?
print_r в обоих случаях пишет одно и тоже.
Example Object ( [variable] => Not1 )
Example Object ( [variable] => Меня в классе нет )
 

RASAMAHA

Новичок
То есть в самом классе можно будет использовать этот "атрибут"?
 

korchasa

LIMB infected
То есть в самом классе можно будет использовать этот "атрибут"?
Да, если даже свойства не существует, то PHP их создает для конкретного инстанса объекта. Но только для него.
PHP:
<?php
class News {}

$n = new News;
var_dump(property_exists($n, 'foo'));
$n->foo = 42;
var_dump(property_exists($n, 'foo'));

$n2 = new News;
var_dump(property_exists($n2, 'foo'));
 

AmdY

Пью пиво
Команда форума
RASAMAHA
ничего страшного, просто у тебя отключены ошибки. так и должно быть. магические методы немного для других целей. почитай про прокси объекты.
основная фишка в том, что ты можешь не просто присвоить аттрибут. а обработать его.
 

RASAMAHA

Новичок
AmdY, ошибки не отключены. Ничего не показывает.
прекрасно работает след. код:
PHP:
class News {
public function getName()  
{  
    return $this->foo;   
} 
}

$n = new News;
$n->foo = 42;
echo $n->getName();
Выводит 42.

А можно пример обработки атрибута? Про прокси что то пока найти ничего не могу(
 

Духовность™

Продвинутый новичок
То есть в самом классе можно будет использовать этот "атрибут"?
нет. это в корне не правильный подход. Если у тебя в классе нужно `использовать этот "атрибут"`, то он ДОЛЖЕН быть явно объявлен:

PHP:
class a
{
    protected $var1;
}
__set и __get методы они нужны не для того, что бы создавать члены класса, а для того, что бы в объект пихать данные, ключи которых не известны. Например, если мы хотим создать внутри объекта какое-то хранилище, например, хранилище данных для дальнейшей подстановки в шаблонизатор. Вот тогда да - ты создаешь в классе массив private $data и через __get и __set заполняешь этот массив, а шаблонизатор, например, парсит шаблон и заменяет метки на твои данные из $data.

В остальных случаях __set и __get использовать нельзя.
 
  • Like
Реакции: AmdY

RASAMAHA

Новичок
Духовность™, я не спорю, что это неправильно, просто работает и с __set и __get и без них одинаково.
Тоже можно создать "какое-то хранилище" для шаблонизатора без __set и __get.
 

Духовность™

Продвинутый новичок
Духовность™, я не спорю, что это неправильно, просто работает и с __set и __get и без них одинаково.
в PHP много чего "просто работает". Способов выстрелить себе в ногу - полно. Надо стремиться изначально писать правильно.

Тоже можно создать "какое-то хранилище" для шаблонизатора без __set и __get.
__set и __get -- это синтаксический сахар, который тем не менее, позволяет добиться инкапсуляции хранилища
 

Mols

Новичок
__set и __get методы они нужны не для того, что бы создавать члены класса, а для того, что бы в объект пихать данные, ключи которых не известны.
От оно чё Михалыч....
Я вот всю жизнь думал, что для "...пихать данные, ключи от которых не известны..." есть ассоциативные массивы.
А тут такие новости.
Имхо довольно необдуманное заявление. (в части для чего они нужны, т.е. создавать свойства через них конечно не стоит, но ключи могут быть известны, и не просто известны, а ещё и могут информировать о необходимости выполнить доп обработку)
 

Духовность™

Продвинутый новичок
Я вот всю жизнь думал, что для "...пихать данные, ключи от которых не известны..." есть ассоциативные массивы.
не надо утрировать, я достаточно четко описал, в каком контексте надо использовать магические сеттеры. Типичный пример - View, Request, Response. Для особо непонятливых могу привести пример такого хранилища:

PHP:
<?php
/**
 * Абстрактный класс реализующий интерфейс Cover_Interface.
 * Данный класс является базовым для многих классов системы.
 */
abstract class Cover_Abstract_Simple implements Cover_Interface
{
    protected $data = array();

    public function __get($key)
    {
        return isset($this->data[$key]) ? $this->data[$key] : null;
    }

    public function __set($key, $value)
    {
        $this->data[$key] = $value;
    }

    public function __isset($key)
    {
        return isset($this->data[$key]);
    }

    public function __unset($key)
    {
        unset($this->data[$key]);
    }

    public function getData()
    {
        return $this->data;
    }

    public function setData($data)
    {
        foreach ($data as $key => $value)
        {
            $this->$key = $value;
        }
    }

    public function clear()
    {
        $this->data = array();
    }

    public function __toString(){}
}
но ключи могут быть известны, и не просто известны, а ещё и могут информировать о необходимости выполнить доп обработку)
Если ключи известны, т.е. в классе объявлены переменные-члены, то для того, что бы "выполнить доп обработку" надо ЯВНО написать get/set методы.
 

Mols

Новичок
Кто сказал, что
" ключи известны" === " в классе объявлены переменные-члены" ?
Да и вообще какие __set __get в таком случае....
Насчет надо/не_надо не забывайте писать ИМХО.
Кому надо, тот пусть пишет.
Объект вполне может иметь какой нить конфигуриуемый массив типа.
$availableFields
В котором вполне может быть что-то вроде.
PHP:
$availableFields['bornDate']=array('type'=>'DATE','null'=>false)
И там уже кто во что горазд.
От проверок на входе, до использования специальных классов для работы с этим значением, форматирования на выходе и чего хошь.

надо ЯВНО написать get/set методы.
Ну пишите хотя бы ИМХО... ну так авторитарно, что ппц.
По сути тут нечего мне сказать. С жестким "надо" я не соглашусь.
Но это высказывание построено на ложном предположении " ключи известны" === " в классе объявлены переменные-члены", так что чего уж....
 
Сверху