Март 05 2008

Перехват обращения к несуществующим свойствам объектов в PHP5

Категория: PHPgugglegum @ 18:52

В строгих языках программирования типа C++ и Java программист обязан явно определять какими свойствами обладает тот или иной класс, причем явно указывая их области видимости (public, protected или private). В PHP4 такой строгости не было и в некоторых случаях это приводило к ошибкам, которые достаточно трудно отловить.

В PHP5 у свойств классов появились области видимости и все стало более-менее строго. Обращение к несуществующему статическому свойству класса

<?php

class A { }

A::$myVar = 'test';

?>

приводит к фатальной ошибке: “Fatal error: Access to undeclared static property: A::$myVar in C:\test.php on line 7″. Однако, для совместимости с PHP4 при обращении к свойству объекта никаких ошибок не генерируется. В PHP4 вы могли расширить объект, добавив в него новые свойства прямо в runtime вот так:

<?php

class A {
}

$a = new A();
$a->MyVar = 'test';

?>

Разумеется, делать так ни в коем случае не нужно ни в 4-ой, ни в 5-ой версии PHP, но PHP на это не ругается. Часто вследствие невнимательности, Вы можете ошибиться в написании имени свойства объекта (например, перепутать регистр букв). В случае чтения несуществующего свойства Вы получите “Notice: Undefined property: A::$MyVar in C:\1\test3.php on line 10″. А в случае присвоения значения — никаких сообщений. Просто вместо изменения значения свойства вы создадите новое свойство, которое при всем при этом будет иметь область видимости public. Отловить такую ошибку обычно довольно трудно, поэтому я предлагаю решение, которое позволяет отлавливать попытку установки значения для несуществующего свойства объекта в PHP5.

Мое решение основано на создании базового класса для всех классов, который использует перегрузку свойств посредством методов __get() и __set(). Этот базовый класс выглядит следующим образом:

<?php

class ClassBase {

  protected function __get($key) {
    throw new Exception('Attempt to read undefined property $'.$key.' of '.get_class($this).' class');
  }

  protected function __set($key, $value) {
    throw new Exception('Attempt to set value to undefined property $'.$key.' of '.get_class($this).' class');
  }

}

?>

И объявляем все наши классы потомками от ClassBase:

<?php

class A extends ClassBase {
}

$a = new A();
$a->MyVar = 'test';

?>

При выполнении данного примера сработает Exception, который если не отловить через try .. catch, приведет к аварийному завершению скрипта с ошибкой “Fatal error: Uncaught exception ‘Exception’ with message ‘Attempt to set value to undefined property $MyVar of A class’ in C:\work\test.php:10″.

Просто и элегантно. Строго говоря, мое решение есть ни что иное как синтаксическая соль для языка PHP5 в части работы с ООП.

Напишите что Вы об этом думаете


*


*


rel=nofollow включен, спам не поднимет Page Rank Вашего сайта



Anti-Spam Image
Введите этот код, чтобы подтвердить, что вы человек
*

* — Обязательно для заполнения

Перейти на главную страницу