Магические методы __get и __set

alex77

Новичок
Магические методы __get и __set

Здравствуйте.
Хочется сделать доступ к загружаемым из БД свойствам объекта через __get и __set. Удобно было бы также реализовать readonly-свойства, например:

PHP:
print $user->id; 
$user->id = 100500; // ошибка

1. В каких случаях следует их использовать, а в каких нет?

2. Подскажите примеры известных приложений на php, где бы это использовалось. Хочется посмотреть, как сделано у других.

p.s.
В инете почитал, в основном не советуют использовать, т.к. вроде медленнее работает(сам проверю), и не работает дополнение кода при работе в IDE.
 

dimagolov

Новичок
alex77, тебе непонятно как с помощью __get и __set сделать read-only свойство? после прочтения мануала это столь очевидно, что вряд ли кто-то тут будет это демонстрировать.

вопрос "а нужно ли оно" глубоко теоретический и вокруг него неоднократно велись споры и обсуждения. в поиск.
 

alex77

Новичок
Видимо я не совсем ясно выразился, мне всё понятно как и что сделать, вопрос как раз и есть теоретический. Нужно ли, если да, то в каких случаях. И хотел пример известного приложения, где такое используется.
 

Духовность™

Продвинутый новичок
В инете почитал, в основном не советуют использовать, т.к. вроде медленнее работает
да, ужасно медленно. сайты надо писать на С.

Удобно было бы также реализовать readonly-свойства, например:
зачем? Какой смысл в объекте User, если он "труп" - только readonly? У меня так было когда-то сделано:

PHP:
 // User_Mapper - класс работающий с БД и создающий объекты User на основе выборок разных методов
$mapper = new User_Mapper();
// Получили объект User (нашли его по ID = 123)
$user = $mapper->findUserById(123);
// Изменили свойство объекта
$user->name = 'other name';
// сохранили объект
$mapper->save($user);
// он нам надоел - удаляем 
$mapper->delete($user);
echo 'Пользователь '.$user->name.' удалён';
Далее, не так давно я отошел от использования __set и __get в объектах моделей. Заместо этого я использую __call и несуществующие функции, основанные на именах свойств класса:

PHP:
$user->getName(); // виртуальная функция - простой getter 
$user->setName($in); // виртуальная функция  - простой setter 
$user->getEmail(); // виртуальная  функция  - простой getter 
$user->setEmail($in); // реальная функция - что то делает cо значением $in, setter
все 3 первых функции обрабатывает __call, последняя является реальной.

Данный подход позволяет навешивать логику на объекты, полученные из базы. Чрезвычайно удобно.

-~{}~ 20.07.10 18:03:

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

alex77

Новичок
Какой смысл в объекте User, если он "труп" - только readonly?
- дык можно только id сделать readonly, ну да ладно.

$user->setEmail($in); // реальная функция - что то делает cо значением $in, setter
В данном случае, если я правильно понял, происходит проверка "валидности" адреса.

Вроде понял что надо для себя, спасибо, только ещё бы пример известного приложения посмотреть...

Ну и немного смущает неудобство с IDE, паходу придётся подглядывать в класс, какие там есть свойства.
хотя это и не проблема, мелочь.

-~{}~ 21.07.10 22:19:

1. Из известных приложений - в typo3 кое где используется.

2. По скорости не сильно отличается:

PHP:
class a
{
    public function __construct() {
        $this->__VALUES__['name'] = 'test';
    }
    
    protected $__VALUES__;
    
    public function __get($name) {
        return $this->__VALUES__[$name];
    }
    
}

class b
{
    public function __construct() {
        $this->name = 'test';
    }
    
    protected $name;
    
    public function getName() {
        return $this->name;
    }
}

$a = new a();

$b = new b();

$start = microtime(true);
for ($i = 0; $i < 100000; $i++) {
    $c = $a->name;
}
$end = microtime(true);
print $end-$start.'<br>';

$start = microtime(true);
for ($i = 0; $i < 100000; $i++) {
    $c = $b->getName();
}
$end = microtime(true);
print $end-$start;

0.39556884765625
0.30794191360474
 
Сверху