Так получилось, что мы попробовали перевести некоторые проекты на 5.3 в ходе переезда нашего collocated хостинга, в результате обнаружилась забавная несовместимость на уровне багов между 5.2 и 5.3.
Проблема возникла в недрах нашей CMS, и, как оказалось, имеет занятную предысторию.
Итак, жил да был некий абстрактный класс AbstractController. И были у него несколько свойств, объявленные как private, а также реализация подержка динамических свойств, в частности метод
Если опустить все подробности, ситуацию можно описать так:
Метод
Когда-то программисту потребовалось прочитать поле
То есть, __get реализованный в родительском классе, смог получить доступ для приватного поля, будучи вызван для экземпляра производного класса.
Пишем:
Запускаем в 5.2.10:
Результат:
Технический прогресс шагнул вперед и приложение перевели на 5.3. Запускаем и получаем (в 5.3.2):
То есть починили.
UPDATE: все наоборот! Не починили а наоборот сломали, а именно функцию property_exists(). Большое спасибо пользователю LighteR за соответствующий комментарий. Облажался, жара, мозги плавятся.
Морали отсюда две:не ходите куда не положено и пишите юнит-тесты :)
Интересно, много ли shared-хостингов поддерживают нынче 5.3 и когда переход на эту версию станет массовым.
Проблема возникла в недрах нашей CMS, и, как оказалось, имеет занятную предысторию.
Итак, жил да был некий абстрактный класс AbstractController. И были у него несколько свойств, объявленные как private, а также реализация подержка динамических свойств, в частности метод
__get()
.Если опустить все подробности, ситуацию можно описать так:
abstract class AbstractController {
private $layout = 'layout';
public function __get($property) {
if (property_exists($this, $property))
return $this->$property;
else throw new Exception("Missing property: $property");
}
}
class RealController {
protected $action = 'action';
}
Метод
__get
в данном случае реализует read-only доступ к отдельным полям.Когда-то программисту потребовалось прочитать поле
layout
для экземпляра производного класса. Несмотря на private, он вызвал $controller->layout
, и все получилось! Неплохо, подумал программист, и заюзал такую замечательную фичу. Было это в версии 5.2То есть, __get реализованный в родительском классе, смог получить доступ для приватного поля, будучи вызван для экземпляра производного класса.
Пишем:
$a = new RealController();
print $a->layout;
print "\n";
print $a->action;
print "\n";
Запускаем в 5.2.10:
Результат:
layout
action
Технический прогресс шагнул вперед и приложение перевели на 5.3. Запускаем и получаем (в 5.3.2):
action
PHP Fatal error: Uncaught exception 'Exception' with message 'Missing property: layout' in /home/max/test.php:9
Stack trace:
#0 /home/max/a.php(20): AbstractController->__get('layout')
#1 {main}
thrown in /home/max/test.php on line 9
То есть починили.
UPDATE: все наоборот! Не починили а наоборот сломали, а именно функцию property_exists(). Большое спасибо пользователю LighteR за соответствующий комментарий. Облажался, жара, мозги плавятся.
Морали отсюда две:
Интересно, много ли shared-хостингов поддерживают нынче 5.3 и когда переход на эту версию станет массовым.