Небольшая идея о реализации геттеров и сеттеров в PHP версии > 5.4 и размышления о подходе к свойствам класса в контексте PHP.
Теория
Есть несколько способов обращения к свойствам класса:
1. Сделать их public.
2. Определить методы доступа типа getA, setA.
3. Использовать магические методы __get, __set.
Тут стоит остановиться на специфике PHP, как языка в целом. Динамическая типизация, легкий синтаксис и множество готовых решений открывают безграничные просторы для быстрого прототипирования. PHP действительно позволяет написать много работающего кода без продумывания всей архитектуры в самом начале. И это действительно важно, в современном мире бешеной конкуренции и, практически, беззащитности большинства идей. Поэтому, не стоит рассматривать конечный код PHP и сравнивать его с другими языками — нужно рассматривать весь процесс разработки.
Итак, беспечное, противоречащее канонам ООП и хорошего стиля, назначение аттрибута public нетипизированным свойствам на самом деле имеет огромное значение в первоначальной разработке архитектуры. На этом этапе мы можем с легкостью менять типы свойств объекта, или их имена, нам не нужно беспокоиться о их защите или корректности.
Также логично, что обратиться к свойству класса $a->b = 1 быстрее и короче и на этом этапе не имеет смысла создавать методы доступа (ведь пока нас не волнуют вопросы инкапсуляции — мы занимаемся творчеством).
И вот, у нас появился работающий прототип — настало время подумать о дальнейшей поддержке кода, о защите информации и других программистах. После первого этапа у нас остались классы, определились названия их свойств. И во всем проекте мы обращаемся к свойствам напрямую $a->b. Тут возникает проблема — как нам ограничить доступ к свойствам, не меняя обращения к ним везде. К сожалению, в PHP пока отсутствуют нативные решения этой проблемы. Но все же мы можем это реализовать чуть менее красиво.
Вопрос решается магическими методами __get и __set и созданием методов доступа. А для удобства разработки мы добавляем doc-комментарии к классу. В целом, практически любой объект удобно использовать по такой схеме и логично было бы вынести одинаковые части в отдельный код. До PHP 5.4 это было возможно реализовать только при помощи наследования, но практически — было невозможно из-за отсутствия множественного наследования. Да и в целом — наследовать другой класс с целью лишь вынесения общего кода нарушает логику связей объектов.
И вот, в PHP 5.4 нам подарили не геттеры и сеттеры, а трейты. Честно говоря, я не вижу много причин их использования — в основном желание воспользоваться ими говорит о плохой объектной системе проекта. Но вот некоторую не хватающую функциональность PHP они закрывают. Лично меня больше бы устроили геттеры и сеттеры.
Практика
Нижеприведенный код является небольшим примером реализации геттеров и сеттеров. При желании можно добавлять различные возможности. Главное, что с трейтами это нужно будет делать лишь в одном месте.
trait GetterSetter { public function __get($name) { $getter = 'get' . ucfirst($name); if ( ! method_exists($this, $getter) ) { throw new \Exception('Not found getter for property - ' . $name); } return $this->$getter(); } public function __set($name, $value) { $setter = 'set' . ucfirst($name); if ( ! method_exists($this, $setter) ) { throw new \Exception('Not found setter for property - ' . $name); } $this->$setter($value); return $this; } }
В классе A, свойство b контролируется нами с помощью трейта, а c пока «в свободном плаванье».
/** * * @property int $b * */ class A { use GetterSetter; /** * @var unknown Временно любой тип значения */ public $c; private $_b; public function getB() { return $this->_b + 1; } public function setB($value) { if ( ! ($value === 2 || $value === 3 ) ) { throw new \Exception('Invalid value ' . $value . ' for b' ); } $this->_b = $value - 1; return $this; } }
Пример обращения к свойству.
$a = new A; $a->b = 7;
Что еще можно сделать на основе такого трейта:
1. Свойства read-only, write-only и т.д.
2. Реализовать присвоение значение свойству в трейте, а в самом классе методы проверки типа checkB().
P.S. Ждем ваши варианты в опрос и примеры использования трейтов.
ссылка на оригинал статьи http://habrahabr.ru/post/186420/
Добавить комментарий