странное поведение в __set в CActiveRecord

привет

код упростил дальше просто некуда

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

  1. в модели Observation ввожу поле и сеттер метод для него



private $refine=null;

....

....

....

public function setRefine($value){

  $this->refine = $value;

}



  1. гдето в контроллере



$model = new Observation('search');

$model->unsetAttributes();


$model->refine = array('some','test','values');



вылазят такие глюки

  1. иногда, пока еще не понял почему вызывается __get(‘refine’) (CActiveRecord line 145) и выдает ошибку что данное свойство не определено. Хотя нигде даже не пытаюсь получить значение refine вне модели

  2. самое на мой взгляд не правильное (проверял с помощью отладчика)

вызываеться __set - CActiveRecord line 156

потом CActiveRecord::setAttribute line 703

в нем property_exists($this,$name), которая возвращает true (ну все таки правильно) и срабатывает $this->$name=$value

но значение refine как было null так и осталось

далее setAttribute возвращает true, и далее метод __set не вызывает (вызвал бы если бы setAttribute вернул false) родительский __set, что бы последний вызвал нужный сеттер метод.

надеюсь понятно написал

теперь как бы такие вопросы

  1. имея property_exists($this,$name) в setAttribute и getAttribute

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

$model->field => __set/__get => setAttribute/getAttribute

  1. из-за #1 не возможно вызвать соответсвующий getter/setter метод. А бывает что нужно

  2. почему все таки не срабатывает $this->$name=$value (CActiveRecord line 706)

ревизия Yii 3477

Всё это удивило даже меня :)

И ведь действительно, в вашем случае private работать не будет, т.к. метод setAttribute() объявлен в родительском классе и не имеет доступа к private переменной в дочернем (Область видимости в PHP 5). Нужно объявлять её как protected и тогда всё заработает.

НО метод setRefine() в PHP 5.3+ всё равно не будет вызван, потому что property_exists, начиная с 5.3.0, проверяет существование свойства вне зависимости от его доступности, т.е. возвращает true и для private, и для protected (в отличие от более ранних версий).

Мне кажется, что такое поведение не задумывалось разработчиками Yii, но у Yii в требованиях нет PHP версии 5.3 и выше, поэтому в каких-то случаях это будет работать, а в каких-то нет независимо от версии фреймворка, что не очень хорошо :)

Проблему с private и вызовом метода setRefine() можно решить, используя разные имена для поля и setter’а, например:




private $_refine=null;

....

....

....

public function setRefine($value){

  echo 'Works!';

  $this->_refine = $value;

}



спасибо за ответ

да с областью видимости я накосячил

почему же я тогда не получаю ошибки в этом месте

$this->$name=$value

доберусь до компа еще раз все проверю

andy_s, спасибо за помощь

и… вы таки проследите что бы при переходе на 5.3 все было исправлено ;)

Я всего-лишь модератор, но возможно этот топик прочтет samdark, и тогда появится шанс, что всё будет исправлено. Ну или можно по-старинке “report a bug” нажать :D