Видимость и поведение переменных PHP с помощью магического метода


Этот вопрос связан с: Пример волшебных методов PHP

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

<?php
    class Magic {
        public $a = "A";
        protected $b = array(
            "a"=>"A", 
            "b"=>"B", 
            "c"=>"C"
        );
        protected $c = array(1,2,3);

        public function __get($v) {
            echo "$v,";
            return $this->b[$v];
        }

        public function __set($var, $val) {
            echo "$var: $val,";
            $this->$var = $val;
        }
    }

    $m = new Magic();
    echo $m->a.",".$m->b.",".$m->c.",";
    $m->c = "CC";
    echo $m->a.",".$m->b.",".$m->c;
?>

Вывод: b,c,A,B,C,c: CC,b,c,A,B,C

$m->c = "CC"; Здесь у нас уже есть защищенная переменная с таким же именем. Итак, как это должно вести себя в контексте видимости?

Если он перезаписывает значение защищенной переменной c, то не является ли это отверстием для петли для защищенные/частные переменные? (Я думаю, что это было бы не так)

Если нет, то оператор: $this->$var = $val;, похоже, создает общедоступную переменную с тем же именем, которое уже определено как защищенное. Возможно ли это?

Также, после этого утверждения: $m->c = "CC";, когда мы снова обращаемся к $m->c, PHP снова вызывает __get, как будто c не имеет публичной видимости. Означает ли это, что у $this->$var = $val; нет жизненного времени для немедленного следующего утверждения? (Я думаю, что это тоже было бы не так)

Кто-нибудь может объяснить, пожалуйста, это следует ли вести себя в таких случаях и как это дало такой результат?

Author: Community, 2014-01-21

2 answers

Похоже, что c изменяется только методами. Пока он защищен, магические методы разоблачают его.

Если вы посмотрите на этот пример:

class Magic
{
    protected $b = 'B';

    public function __get($v)
    {
        return 'C';
    }

    public function __set($v, $val)
    {
        $this->$v = $val;
    }
}

$magic->b = 'D';
echo $magic->b; // Outputs: C

Первый вызов устанавливает свойство b в D, однако, поскольку средство получения жестко запрограммировано для возврата C, модификатор доступа protected по-прежнему соблюдается.

РЕДАКТИРОВАТЬ.

Еще одно применение магических геттеров/сеттеров - доступ к коллекциям. Этот пример демонстрирует их гибкость:

class Magic
{
    private $properties = array();

    public function __get($key)
    {
        if(isset($this->properties[$key])) {
            return $this->properties[$key];
        }
    }

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

    public function dump($return = false)
    {
        if($return) {
            return print_r($this->properties, true);
        } else {
            print_r($this->properties);
        }
    }
}

$magic = new Magic();

$magic->a = '123';
$magic->b = '456';
$magic->c = '789';

echo '<pre>';

echo sprintf('A: %s%s', $magic->a, PHP_EOL);
echo sprintf('B: %s%s', $magic->b, PHP_EOL);
echo sprintf('C: %s%s', $magic->c, PHP_EOL);

echo PHP_EOL;

echo $magic->dump(true);

Вывод:

A: 123
B: 456
C: 789

Array
(
    [a] => 123
    [b] => 456
    [c] => 789
)

Они являются всего лишь функциями и поэтому следуют одним и тем же правилам, разница лишь в методе, в котором они вызываются.

 2
Author: Flosculus, 2014-01-21 10:04:32

Ваши геттер и сеттер применяются к разным переменным.

Получатель обращается к элементу свойства $b Установщик обращается непосредственно к указанному свойству.

Видимость здесь не имеет значения, так как весь ваш доступ происходит из методов класса. Таким образом, они могут получить доступ к общедоступным и защищенным объектам без каких-либо различий.

Думайте о волшебной функции как о обычной функции со странным названием. Это то же самое, что получить к ним доступ в этом способ:

$m->__get("a");
$m->__set("c", "CC");
 1
Author: ToBe, 2014-01-21 09:34:40