2010-07-31 3 views
4

Я хорошо осмотрелся и, похоже, не нашел ответа на эту проблему.Объявление защищенных переменных в методах

В основном я использую метод _call для динамического генерации методов get и set, однако при объявлении значения переменной PHP по умолчанию является общедоступным. Нужно ли вообще объявлять переменную из класса в качестве защищенного?

function __call($method, $arguments) { 
    $prefix = strtolower(substr($method, 0, 3)); 
    $property = strtolower(substr($method, 3)); 

    if (empty($prefix) || empty($property)) { 
     return; 
    } 

    if ($prefix == "get" && isset($this->$property)) { 
     return $this->$property; 
    } 

    if ($prefix == "set") { 

     $this->$property = $arguments[0]; 
    } 
} 
+0

Из интереса, почему вы используете __call, а не __get и __set? –

+0

Мне просто показалось, что я тоже скопировал его: http://onlamp.com/pub/a/php/2005/06/16/overloading.html –

ответ

6

Одним из вариантов было бы иметь защищенный массив и установить в этом массиве элемент из вашего волшебного сеттера.

class MyClass { 
    protected $_myProperties = array(); 

    public function __get($name) { 
     if (isset($this->_myProperties[$name])) { 
      return $this->_myProperties[$name]; 
     } else { 
      return null; 
     } 
    } 

    public function __set($name, $value) { 
     $this->_myProperties[$name] = $value; 
    } 

    public function __isset($name) { 
     return isset($this->_myProperties[$name]); 
    } 
} 
+0

Спасибо, сделайте это. Работает отлично, но удержал метод вызова, поскольку получил привычку использовать $ class-> getSomething(); –

2

Есть в любом случае, чтобы объявить переменную внутри класса защищенными?

Это не похоже. Вы можете использовать Reflection до change the accessibility of properties, но, похоже, это можно эффективно использовать только для того, чтобы публиковать вещи, которые ранее не были публичными.

Возможно, вы захотите рассмотреть возможность сохранения автоматически генерируемых свойств в массиве с соответствующей видимостью.

(Там же __get и __set, но они могут не соответствовать вашим потребностям. Они только дозвонились, когда имущество отсутствует или недоступны. Классы, которые в состоянии коснуться защищенных свойств в обход их.)

+0

Да, я согласен с вашим 2-м абзацем ... храните эти _generated_ 'свойства' в ассоциативном массиве. Ассоциативный массив может быть защищенным свойством вашего класса. Чтобы использовать '__get' или' __set'_I think_, вам нужно будет сделать это таким образом. – MrWhite

+0

Я не согласен. Это побеждает точку переменных-члена. Я использую ассоциативные массивы, когда класс будет хранить неизвестные переменные (например, класс реестра или что-то подобное). Но почему бы не использовать переменные-члены для того, для чего они были разработаны, когда у вас ограниченный набор известных переменных? – ircmaxell

+0

Я могу только представить себе, с вопросом, что он делает своеобразное дурацкое наследование и/или магию видимости. Если код, вышеперечисленный выше, не завершен, я не вижу никаких преобразований, сделанных для свойств ... – Charles

5

Во-первых, я настоятельно рекомендую не returning если префикс или имущественными переменные не установлены. Это сделает отладку ОЧЕНЬ трудной. Вместо этого замените return; на throw new BadMethodCallException('Method Does Not Exist: '.$method);

Во-вторых, разве это не побеждает точку защищенных переменных? Он позволяет читать и записывать все свойства без какой-либо проверки. Если вы собираетесь это сделать, вы также можете сделать их общедоступными.

Я лично считаю $foo->bar = 'baz'; более читаемым, чем $foo->setBar('baz');. Не потому, что это «легче» понять, а потому, что второй лишний раз лишний раз.

Лично я предлагаю сделать __get и __set и добавить проверку. Весь смысл защиты переменных - это доверие (чтобы вы могли доверять настройкам). Конечно, вы можете использовать отражение или подклассификацию, чтобы изменить их, но я обычно предполагаю, что если кто-то зайдет так далеко, они заслуживают каких-либо непреднамеренных заговоров, если они испортили переменную.

И имейте в виду, что если вы используете какой-либо вид магического метода, вам необходимо добавить элементы документации, если вы хотите, чтобы ваш IDE намекнуть методы/переменные для вас ...

EDIT:

И не забывайте, что если вы объявите методы /__set, вы можете переопределить их в дочерних классах. Поэтому, если ребенок объявляет новые переменные, вы можете обрабатывать их там, а затем вызвать parent::__get для обработки переменных по умолчанию. Поэтому не используйте массив только для того, чтобы у вас был один метод для всех детей. Сделайте валидацию для членов, о которых вы знаете, и позвольте своим детям справляться с собственной проверкой ...

+2

+1 Не согласен с $ foo-> setBar ('baz'); без необходимости verbode по сравнению с $ foo-> bar = 'baz'; потому что методы getter и setter всегда позволяют проверять атрибуты, в то время как атрибут non-private всегда можно установить в обход любой проверки ... но здесь очень много очень полезных фрагментов информации. –

+0

Это всего лишь резервный метод для любых переменных, которые я мог бы использовать нужно добавить в класс. Вообще говоря, я всегда использую методы get и set, когда это необходимо для защищенных переменных. Я полностью понимаю трудности с отладкой и буду использовать этот метод экономно, чтобы достичь СУХОЙ. –

+0

Ну, я использую синтаксис 'getBar()' время от времени, но я стараюсь не делать этого, если это действительно имеет смысл. Мне просто не нравится беспорядок наличия 50 методов в классе только для получения/установки переменных-членов ... В большинстве случаев это просто необязательно (но не всегда) ... – ircmaxell

Смежные вопросы