Пример __get () через Zandstra - PullRequest
3 голосов
/ 28 апреля 2011

Мэтт Зандстра приводит следующий пример в своем тексте «Шаблоны и практика объектов PHP» для иллюстрации метода __get ():

class Person {
    function __get( $property ) {
        $method = "get{$property}";
        if ( method_exists( $this, $method ) ) {
            return $this->$method();
        }
    }
    function getName() {
        return "Bob";
    }
    function getAge() {
        return 44;
    }
}

В действительности мы знаем, что никогда бы не создали такие методы (getName и getAge) для возврата таких статических значений, но вместо этого - мы создали бы свойства name и age в объекте и возвращали бы те, которые используют оператор $ this.

У меня вопрос, показывает ли этот пример полезность. А если нет, может кто-нибудь привести лучший пример того, почему можно использовать __get () для той же цели?

Обоснование для запроса

Если бы мы использовали свойства name и age в объекте, то функция __get () все равно не была бы запущена, потому что попытка получить эти свойства с помощью:

$person = new Person();
$name = $person->name;

приведет к тому, что свойство name будет фактически возвращено, если оно будет общедоступным, или вызовет ошибку видимости, если оно будет частным или защищенным. Функция __get () не будет выполнена ни в одном из этих «реальных» случаев ... я что-то упустил?

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

Ответы [ 4 ]

1 голос
/ 28 апреля 2011

Вы абсолютно правы - я впечатлен, что вы цитируете из книги, этот пример просто отстой.

Использование магического __get метода для вызова методов просто неправильно, есть другие магические методытолько для этого вида использования:

  • __call()
  • __callStatic()
  • __invoke()

__get() и__set() должен использоваться для чтения и записи необъявленного объекта properties .

0 голосов
/ 14 июля 2015
    <?php
        class data {
            public $name="Ankur DalsaniYa"; \\ I wont to change name

            public function __get($var) {
                print "Attempted to retrieve '<b>$var</b>' and failed...\n";
                //$var is print the Unknown and Not Define but call variable print  
            }
        }

        $data = new data;
        echo "<br> Not Define Variable Call : ";
        print $data->title; // Not Defined variable Call then call __get function
        echo "<br><br> Define Variable Call : ";
        print $data->name;  // Define variable Call then Not call __get function
    ?>
0 голосов
/ 28 апреля 2011

Фактическая функциональность магических методов полностью зависит от разработчика, чтобы справиться с ним любым удобным для них способом.Разница в том, как они вызываются.

$obj->property; // invokes __get(), if defined
$obj->method(); // invokes __call(), if defined
$obj(); // invokes __invoke() if defined (php 5.3+)

и т. Д.Так что если вы хотите, чтобы __get() вызывал метод внутри, вы можете.То, как вы хотите справиться с этим, полностью зависит от того, как вы хотите создать свое приложение.

О __get(), если у вас есть открытый член и вы пытаетесь вызвать его с помощью ->, __get() не будетПожар.Однако, если вы попытаетесь получить доступ к недоступному участнику (либо защищенному, частному, либо несуществующему), __get() сработает, и вы сможете справиться с ним так, как вам нравится.

Насколько я понимаю, основная цель__get() по крайней мере, согласно php, это исключает необходимость писать геттеры для каждого члена.Сравните с __set() для сеттеров.Я не хочу вдаваться в подробности, но я думаю, что использование геттеров / сеттеров должно поднять некоторые красные флаги о дизайне.Тем не менее, целевое назначение __get() не должно соблюдаться, за исключением стандартов тех, кто разрабатывает приложение.

Два примера использования __get() могут быть инициализировать свойство, которое может непотребуются при создании экземпляра (например, по запросу БД), таким образом уменьшая накладные расходы.Другой может быть, если у вас есть свойства, хранящиеся в массиве, magical get может вернуть значение, сопоставленное с ключом запрошенного свойства.

С помощью магических функций php вы можете делать очень интересные вещи и писатькод, который является более расширяемым с помощью этих специальных вызовов.Что-то, что мне нравится делать:

class application {
   public function __call($_, $_) {
      throw new Exception("PUT and DELETE not supported");
   }
   public function POST() {
      //update data
      header("Location: $_SERVER[PHP_SELF]", true, 303);
   }
   public function GET() {
      //display data
   }
   public static function inst() {
      return new self;
   }
}

application::inst()->$_SERVER['REQUEST_METHOD']();

Конечно, это использует __call() вместо __get(), но принцип тот же.В данном случае это просто проверка работоспособности.

0 голосов
/ 28 апреля 2011

Как утверждает php.net

"__ get () используется для чтения данных из недоступных свойств. "

Это означает, что __get() (если он определен) вызывается всякий раз, когда вы пытаетесь получить доступ к свойству, которое не существует или является частным / защищенным. В приведенном выше примере показан способ получения значений этих закрытых свойств путем вызова их методов доступа (получателей) всякий раз, когда кто-то пытается получить значения.

Например, позвонив по номеру

echo $a -> publicPropery or echo $a -> getPublicProperty()

приведет к тому же. Однако, если вы вызовете $ a -> privateProperty, вы получите сообщение об ошибке, и

$a -> getPrivateProperty() 

будет в порядке.

Но , если вы определили __get() при каждом вызове $a -> privateProperty, __get() выполняется и перенаправляется на $a -> getPrivateProperty(). В этом случае вам всегда удастся получить ценность и при этом помнить о безопасности. Более того, поскольку вы проверяете наличие метода получения свойства в __get(), вы можете показать соответствующую ошибку или вызвать исключение, если кто-то попытается получить доступ к несуществующим свойствам, что переопределит ошибки видимости php.

...