Intereting Posts
Форсировать композитор, чтобы требовать версию PHP между версией X и версией Y Отправить форму с помощью кнопки вне формы BitmapData от Flash до PHP до электронной почты Файл изображения Android, отправленный в файл загрузки файла php, – это тип приложения / октета-потока, а не изображение / jpeg? Установка и включение Xdebug на MAMP PRO Ошибка PHP-скрипта при вызове с Android HttpClient Проверить строку на плохие слова? Отменить внутри array_walk_recursive не работает Статическая функция класса доступа через переменную PHP – Проблемы с удалением «\ r \ n \ r \ n» из этой строки: «Я хотел бы: \ r \ n \ r \ n1.) Сбросить этот беспорядок \ r \ n \ r \ n \ 2.) Теперь Пожалуйста" Присоединить многомерный массив, такой как SQL file_get_contents (- Исправить относительные URL-адреса Подключение двух таблиц – объединение строк за строкой PHP. Загрузите веб-фотографию в альбом facebook через Graph API. Как узнать, сколько строк и столбцов следует читать из файла Excel с помощью PHPExcel?

Является ли это разумным способом обработки getters / seters в классе PHP?

Я собираюсь попробовать что-то с форматом этого вопроса, и я очень открыт для предложений о лучшем способе справиться с этим.

Я не хотел просто сбрасывать кучу кода в вопросе, поэтому я разместил код для класса на refactormycode.

базовый класс для простой обработки свойств класса

Я думал, что люди могут либо публиковать фрагменты кода здесь, либо вносить изменения в refactormycode и отправлять ссылки на их рефакторинг. Я сделаю upvotes и соглашусь ответить (при условии, что есть четкий «победитель») на основе этого.

Во всяком случае, к самому классу:

Я вижу много споров о методах класса getter / setter и лучше ли просто обращаться к простым переменным свойств напрямую или должен быть определен каждый класс с явными методами get / set, бла-бла-бла. Мне нравится идея иметь явные методы в случае, если вам придется добавить больше логики позже. Тогда вам не нужно изменять какой-либо код, который использует класс. Однако я ненавижу иметь миллион функций, которые выглядят так:

public function getFirstName() { return $this->firstName; } public function setFirstName($firstName) { return $this->firstName; } 

Теперь я уверен, что я не первый человек, который это сделал (я надеюсь, что есть лучший способ сделать это, что кто-то может мне предложить).

В принципе, класс PropertyHandler имеет метод __call magic. Любые методы, которые проходят через __call, которые начинаются с «get» или «set», затем направляются к функциям, которые устанавливают или извлекают значения в ассоциативный массив. Ключ в массив – это имя вызывающего метода после get или set. Итак, если метод, входящий в __call, является «getFirstName», ключ массива – «FirstName».

Мне понравилось использовать __call, потому что он автоматически позаботится о случае, когда подкласс уже имеет метод getFirstName. Мое впечатление (и я могу ошибаться) в том, что методы магии __get & __set не делают этого.

Итак, вот пример того, как он будет работать:

 class PropTest extends PropertyHandler { public function __construct() { parent::__construct(); } } $props = new PropTest(); $props->setFirstName("Mark"); echo $props->getFirstName(); 

Обратите внимание, что PropTest на самом деле не имеет методов «setFirstName» или «getFirstName», а также свойство PropertyHandler. Все, что происходит, это манипулировать значениями массива.

В другом случае ваш подкласс уже расширяет что-то еще. Поскольку вы не можете иметь истинное множественное наследование в PHP, вы можете сделать свой подкласс экземпляром PropertyHandler как приватную переменную. Вы должны добавить еще одну функцию, но тогда все будет вести себя точно так же.

 class PropTest2 { private $props; public function __construct() { $this->props = new PropertyHandler(); } public function __call($method, $arguments) { return $this->props->__call($method, $arguments); } } $props2 = new PropTest2(); $props2->setFirstName('Mark'); echo $props2->getFirstName(); 

Обратите внимание, как в подклассе есть метод __call, который просто передает все вместе с методом PropertyHandler __call.


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

Фактически, практически невозможно использовать какой-либо инструмент для создания документов, поскольку явные методы, которые не документируются, не существуют.

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

Related of "Является ли это разумным способом обработки getters / seters в классе PHP?"

Как я это делаю:

 class test { protected $x=''; protected $y=''; function set_y ($y) { print "specific function set_y\n"; $this->y = $y; } function __call($function , $args) { print "generic function $function\n"; list ($name , $var ) = split ('_' , $function ); if ($name == 'get' && isset($this->$var)) { return $this->$var; } if ($name == 'set' && isset($this->$var)) { $this->$var= $args[0]; return; } trigger_error ("Fatal error: Call to undefined method test::$function()"); } } $p = new test(); $p->set_x(20); $p->set_y(30); print $p->get_x(); print $p->get_y(); $p->set_z(40); 

Который будет выводить (добавление строк для ясности)

 generic function set_x specific function set_y generic function get_x 20 generic function get_y 30 generic function set_z Notice: Fatal error: Call to undefined method set_z() in [...] on line 16 

@Брайан

Моя проблема заключается в том, что добавление «дополнительной логики позже» требует добавления общей логики, которая применяется ко всем свойствам, к которым обращаются с помощью getter / setter, или к которым вы используете if или switch для оценки того, какое свойство вы обращаетесь, чтобы вы могли применить специфической логики.

Это не совсем так. Примите мой первый пример:

 class PropTest extends PropertyHandler { public function __construct() { parent::__construct(); } } $props = new PropTest(); $props->setFirstName("Mark"); echo $props->getFirstName(); 

Предположим, что мне нужно добавить логику для проверки FirstNames. Все, что мне нужно сделать, это добавить метод setFirstName в мой подкласс, и этот метод будет автоматически использоваться вместо этого.

 class PropTest extends PropertyHandler { public function __construct() { parent::__construct(); } public function setFirstName($name) { if($name == 'Mark') { echo "I love you, Mark!"; } } } 

Я просто не удовлетворен ограничениями, которые имеет PHP, когда дело доходит до неявных методов доступа.

Я полностью согласен. Мне нравится способ Python справиться с этим (моя реализация – это просто неуклюжая копия).

Да, правильно, переменные должны быть объявлены вручную, но я нахожу это лучше, так как опасаюсь опечатки в сеттере

 $props2->setFristName('Mark'); 

будет автоматически генерировать новое свойство (FristName вместо FirstName), что усложнит процесс отладки.

Мне нравится иметь методы вместо того, чтобы просто использовать публичные поля, но моя проблема с реализацией по умолчанию PHP (с использованием __get () и __set ()) или вашей пользовательской реализации заключается в том, что вы не устанавливаете геттеры и сеттеры для каждого свойства основа. Моя проблема заключается в том, что добавление «дополнительной логики позже» требует добавления общей логики, которая применяется ко всем свойствам, к которым обращаются с помощью getter / setter, или к которым вы используете if или switch для оценки того, какое свойство вы обращаетесь, чтобы вы могли применить специфической логики.

Мне нравится ваше решение, и я приветствую вас за это – я просто не удовлетворен ограничениями, которые имеет PHP, когда дело доходит до неявных методов доступа.

@Отметка

Но даже ваш метод требует нового объявления метода, и он несколько убирает преимущество поместить его в метод, чтобы вы могли добавить больше логики, потому что для добавления большей логики требуется старомодное объявление метода. В своем состоянии по умолчанию (которое там, где оно впечатляет в том, что оно обнаруживает / делает), ваш метод не предлагает преимуществ (в PHP) по публичным полям. Вы ограничиваете доступ к полю, но предоставляете карт-бланш через методы доступа, которые не имеют каких-либо ограничений. Я не знаю, что непроверенные явные аксессоры предлагают какое-либо преимущество перед публичными полями на любом языке, но люди могут и должны быть свободны исправить меня, если я ошибаюсь.

Я всегда рассматривал эту проблему в аналогичном с __call, который заканчивается в значительной степени как кодовый табличный код во многих моих классах. Тем не менее, он компактный и использует классы отражения, чтобы добавлять только геттеры / сеттеры для свойств, которые вы уже установили (не будут добавлять новые). Простое добавление getter / setter явно добавит более сложные функции. Ожидается, что

Код выглядит следующим образом:

 /** * Handles default set and get calls */ public function __call($method, $params) { //did you call get or set if ( preg_match( "|^[gs]et([AZ][\w]+)|", $method, $matches ) ) { //which var? $var = strtolower($matches[1]); $r = new ReflectionClass($this); $properties = $r->getdefaultProperties(); //if it exists if ( array_key_exists($var,$properties) ) { //set if ( 's' == $method[0] ) { $this->$var = $params[0]; } //get elseif ( 'g' == $method[0] ) { return $this->$var; } } } } 

Добавьте это в класс, где вы объявили свойства по умолчанию:

 class MyClass { public $myvar = null; } $test = new MyClass; $test->setMyvar = "arapaho"; echo $test->getMyvar; //echos arapaho 

Класс отражения может добавить что-то полезное к тому, что вы предлагаете. Аккуратное решение @Mark.

Совсем недавно я также подумал о том, как обращаться с геттерами и сеттерами, как вы предложили (второй подход был моим фаворитом, то есть частным массивом $ props), но я отбросил его, потому что это не получилось бы в моем приложении.

Я работаю над довольно большим SoapServer-приложением, и мыльный интерфейс PHP 5 вводит значения, которые передаются через мыло непосредственно в ассоциированный класс, не беспокоясь о существующих или несуществующих свойствах в классе.

Я не могу не помещать свои 2 цента …

Я взял использование __get и __set в этой усадьбе http://gist.github.com/351387 (аналогично тому, как это делает доктрина), а затем только доступ к свойствам через $obj->var за пределами класс. Таким образом, вы можете переопределить функциональность по мере необходимости, вместо создания огромной функции __get или __set или переопределения __get и __set в дочерних классах.